원문 - scope(exit) in C++11

사실 매우 간단하므로 원문을 보시면 금방 아실거라고 생각합니다만, D 언어의 scope(exit)를 C++11의 람다와 auto를 이용하여 구현한 것입니다. BOOST에도 비슷한 것이 있지만 C++11의 기능을 이용하여 더 쉽고 간단하네요.

처음에는 std::function을 사용했지만, std::function이 꽤나 느리고(RTTI를 사용하기 때문이라고 하는군요), 템플릿 인수를 넣어줘야 하기 때문에(원문에는 없었지만 VC++10에서는 그러면 컴파일이 안되더라는...) 대신 템플릿을 이용한 것을 추천합니다.

template<typename F>
class ScopeExit
{
public:
     ScopeExit(F f) : m_f(f) {}
     ~ScopeExit() { m_f(); }

private:
     F m_f;
};

생성자에서 함수를 저장했다가 소멸자에서 호출하는, 더이상 할 말이 없을 정도로 간단한 클래스입니다. 여기서 더 간단히 쓰기 위해서 매크로와 헬퍼 함수를 추가합니다

// AutoScope 객체를 생성하기 위한 헬퍼
template<typename F>
ScopeExit<F> MakeScopeExit(F f)
{
     return ScopeExit<F>(f);
};

// 한번더 거치지 않으면 ScopeExit___LINE__이라는 이름의 변수가 생성됨
#define STRING_JOIN2(arg1, arg2)          DO_STRING_JOIN2(arg1, arg2)
#define DO_STRING_JOIN2(arg1,arg2)     arg1 ## arg2
#define MAKE_SCOPE(code)\
     auto STRING_JOIN2(ScopeExit_, __LINE__) = MakeScopeExit([&]()(code;))

MAKE_SCOPE 매크로를 사용하여 코드를 적어주면, 'ScopeExit_행번'이라는 이름의 ScopeExit 객체가 생성됩니다. __LINE__을 이용하므로 같은 행에 두 번 이상쓸 수는 없습니다만... 아마 그렇게 쓰는 분은 안계실 거라고 믿겠습니다.
원문에서는 캡쳐시 값으로 넘기고 있는데... 일단 여기서는 참조로 넘기고 있습니다. 적당히 취향에 맞춰서 바꾸면 될 듯 하네요(리플에서도 싸우고 있...)

사용 예시는 다음과 같습니다.

class Test
{
public:
     Test() { std::cout << "Test class constructed" << std::endl; }
     ~Test() { std::cout << "Test class destructed" << std::endl; }
};

int main()
{
     {
          Test* test = new Test;
          SCOPE_EXIT(delete test);
     }
     getchar();
     return 0;
}


+ Recent posts