C++로 지연된 함수콜 구현하기
지난 2일 간
관해서 포스팅했다. 오늘 이걸 실제로 광범위하게 적용시켜봤는데, 그러다 보니 문제점들이 확실히 보였다.
테스트 하는 동안 가장 문제가 되었던 것은 참조형으로 넘겨준 변수 문제였다. (포인터로 넘겨주는 일은 “없다고 가정하는 상황"이라서 일단 그 문제는 넘어가자)
class A : private boost::noncopyable {
public:
A() {}
virtual ~A() {}
void Do3(int a, int b, int& c) {
cout << "A::Do3(" << a << ", " << b << ", " << c << ")" << endl;
}
};
void foo() {
A a;
int tmp_val = 3;
shared_ptr<Closure> c = MakeClosure<A, void, int, int, int&>(a, &A::Do3, 1, 2, tmp_val);
c->Execute();
tmp_val = 0;
c->Execute();
}
foo 의 실행결과는 다음과 같다. (foo에서 Closure를 만드는 부분의 타입 추론 문제 때문에 템플릿 인자를 명시적으로 썼다)
A::Do3(1, 2, 3)
A::Do3(1, 2, 0)
_지금 구현한 것을 사용하는 곳에서 원하는 동작_은 두 번의 실행 모두 (1, 2, 3) 이라고 찍히는 것이다. 템플릿 클래스 멤버 변수들의 타입을 실행될 함수의 인자타입과 동일하게 했었는데, 이를 참조자 형태인 경우에만 원래의 타입이 되게 수정하는 코드를 넣었다. 즉, 원래
A0 m_A0;
A1 m_A1;
처럼 선언되던 것을, boost::remove_reference<T>
를 사용해서1
typename boost::remove_reference<A0>::type m_A0;
typename boost::remove_reference<A1>::type m_A1;
로 선언되게 수정했다. 그러고 나니 원하는 대로의 출력이 나오게 되었다.
이제 남은 문제: MakeClosure
라는 보조 함수를 통해서 템플릿 인자 타입을 자동 연역하게 했었는데, 참조형인 경우에는 이게 제대로 되지 않는다. 뭘 해주면 이걸 자동으로 찾을까? 즉, 위에 사용한 코드의 MakeClosure 부분의 템플릿 인자 목록을 지우면,
“int인지 int&인지 모호하다.” 라는 에러가 나오게 되는데(VC++ 2005기준) 이를 피할 방법은 없을까? 라는 것.
-
boost::remove_reference<T>
는<boost/type_traits/remove_reference.hpp>
에 정의되어 있다. T가 어떤 타입 U의 참조형(U&
)일 때만 U로 바꿔준다. T가 그렇지 않은 타입인 경우 그대로 T를 돌려주게 된다. ↩︎