C++에서 Python의 with statment 구현하기

파이썬에는 객체의 생성과 소멸의 범위를 확실하게 정하는 목적으로 with 문법이 존재한다. 파이썬은 C와 달리 블럭 스코프를 이용해서 객체의 생성주기를 통제할수 없기 때문에 with가 존재한다.

with open("x.txt") as f:
    data = f.read()
    ...

C에서는 블럭 스코프가 존재하기 때문에 with statement가 필요없지만 그래도 한번 만들어본 이유는 리눅스 커널의 for_each_process 매크로를 보고 for문을 매크로로 이용해서 확장하는 것이 가능하겠다는 생각을 했기 때문이다.

#define for_each_process(p) \
    for (p = &init_task ; (p = next_task(p)) != &init_task ; )

Code

Repo

#define WITH_COND_VAR(LINE) __with_run_##LINE
#define WITH_FOR(EXPR, LINE) \
    int WITH_COND_VAR(LINE) = false; \
    for(EXPR ; WITH_COND_VAR(LINE) == false ; WITH_COND_VAR(LINE) = true)
#define WITH(EXPR) WITH_FOR(EXPR, __LINE__)

for문의 구조를 이용했다. for(...) {} 에서 블럭을 제외한 부분을 매크로로 생성했다. for문이 1번만 돌아가도록 하려면 상태를 저장하는 변수가 필요하다. 이것은 전처리기의 ## 연산자를 이용해서 만들었다. ## 연산자를 이용하면 매크로 토큰을 이어붙일 수 있다.

응용

객체의 생성자와 소멸자를 이용해서 객체가 존재하는 스코프에서의 실행시간을 측정하는 PROFILE 매크로가 있다고 가정하자. 일반적인 C++에서는 다음과 같은 형태로 PROFILE 매크로를 이용한다.

while(!quitGame)
{
    {
        PROFILE("Poll Joypad");
        PollJoypad();
    }
    {
        PROFILE("Game Object Update");
        UpdateGameObjects();
    }
    ...
}

WITH 매크로를 이용하면 다음과 같은 식으로 코드를 짤 수 있다.

while(!quitGame)
{
    WITH(PROFILE("Poll Joypad"))
    {
        PollJoypad();
    }
    WITH(PROFILE("Game Object Update"))
    {
        UpdateGameObjects();
    }
    ...
}

Reference


comments powered by Disqus