지난 2일 간
관해서 포스팅했다. 오늘 이걸 실제로 광범위하게 적용시켜봤는데, 그러다 보니 문제점들이 확실히 보였다(…).
테스트 하는 동안 가장 문제가 되었던 것은 참조형으로 넘겨준 변수 문제였다. (포인터로 넘겨주는 일은 "없다고 가정하는 상황"이라서 일단 그 문제는 넘어가자 :p )
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> 를 사용해서†
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를 돌려주게 된다.
C++ template 함수의 타입 추론…
몇 일 전에 연이어서 C++로 일종의 지연된 함수호출 객체를 만드는 코드에 관해 포스팅했었다. (#1, #2, #3 참조)
마지막 포스팅에서도 해결 못했던 문제가 아래 코드에 나와있는 템플릿 함수를 ….