2010-08-19 2 views
3

함수 객체를 받아들이고 그것을 콜렉션에 저장하는 "Attach"함수가있는 클래스가 있습니다. 클래스 자체는 함수 시그니처에 템플리트됩니다. 이런 식으로 뭔가 :템플릿 boost :: bind가 멤버 함수의 복수 인수를 자동으로 처리합니다.

template<class Signature> 
class Event 
{ 
public: 

void Attach(boost::function<Signature> signature) 
{ 
    MySignatures.push_back(signature); 
} 

private: 

std::list<boost::function<Signature>> MySignatures; 
}; 

고려, 다음 클래스 사용법을 설명하기 위해 :


class Listening 
{ 
public: 

int SomeFunction(int x, int y, int z); 
}; 

EventListening의 기능을 전달하기를, 내가 쓸 필요가 : 그래서


Event<int(int, int, int)> myEvent; 
Listening myListening; 

myEvent.Attach(boost::bind(boost::mem_fn(&Listening::SomeFunction), &myListening, _1, _2, _3)); 

오류가 발생할 가능성이있는 각 사례에 대해 이렇게하는 대신 다음과 같이 일련의 매크로를 작성합니다.


#define EventArgument0(x, y) boost::bind(boost::mem_fn(x), y) 
#define EventArgument1(x, y) boost::bind(boost::mem_fn(x), y, _1) 
#define EventArgument2(x, y) boost::bind(boost::mem_fn(x), y, _1, _2) 
#define EventArgument3(x, y) boost::bind(boost::mem_fn(x), y, _1, _2, _3) 
#define EventArgument4(x, y) boost::bind(boost::mem_fn(x), y, _1, _2, _3, _4) 

etc. 

후, 나는 쓸 수있다 : (내 생각)을 읽는 것이 훨씬 쉽다


myEvent.Attach(EventArgument3(&Listening::SomeFunction, &myListening)); 

. 이제 내 질문에 : 내가 대신 쓸 수있는 방법 :


myEvent.Attach(EventArgument(&Listening::SomeFunction, &MyListening)); 

또는 더 나은 :


myEvent.Attach(&Listening::SomeFunction, &myListening); 

, < 서명에 포함 된 이벤트가 마술 인수의 적절한 수의 제대로 바인딩에 연결하도록 > (이 예에서는 int(int, int, int))? 나는 당신이 여기서 염두에두고있는 모든 템플리트 메타 프로그래밍 매직에 열려 있습니다.

감사합니다.

편집 : 그것은 boost::bind이 상당하기 때문에 그렇게 내가 여기 boost::mem_fn 필요하지 않습니다 밝혀 내 매크로 내가 사용할 수 있습니다

bind(mem_fn(&MyClass::Hello), myClass, _1, _2, _3); 

질문 : 대신

bind(&MyClass::Hello, myClass, _1, _2, _3); 

을, 그러나, 이벤트 클래스에 &MyClass::Hello을 전달하고 템플릿 과부하를 사용하여 , _2, _3 등을 처리하는 방법은을 템플릿으로 사용하는 함수 프로토 타입에 의해 암시됩니다.클래스?

+0

Google/Bing에서 "완벽한 전달"을 시도 했습니까? C++ 0x를 사용할 수 있다고 가정합니다. – Henrik

+0

저는 지금 그것을보고 있습니다, 예를 들어 여기 : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm. 그게 어떻게 문제를 해결하는 데 도움이되는지는 분명하지 않습니다. – Robinson

답변

2

과부하 Attach : 당신이 너무 후 const 멤버 함수를 처리해야하는 경우

template<typename R,typename T,typename U> 
void Attach(R (T::*pmf)(),U* p)) 
{ 
    Attach(boost::bind(pmf,p)); 
} 

template<typename R,typename T,typename U,typename A1> 
void Attach(R (T::*pmf)(A1),U* p)) 
{ 
    Attach(boost::bind(pmf,p,_1)); 
} 

template<typename R,typename T,typename U,typename A1,typename A2> 
void Attach(R (T::*pmf)(A1,A2),U* p)) 
{ 
    Attach(boost::bind(pmf,p,_1,_2)); 
} 

당신이 오버로드의 두 번째 세트가 필요합니다.

+0

Brilliant. shared_ptr을 사용하기 위해 약간 변경했습니다. (그래서 weak_ptr 참조를 유지하고 이벤트를 시작하기 전에 .expired() 포인터를 놓을 수 있습니다). 그렇지 않으면 훌륭한 솔루션입니다. 감사. – Robinson

2

Attach() 템플릿을 사용하면 목표로 할 수 있습니다. 코드가 지저분 해지지만 원하는 방식으로 호출 할 수 있습니다. 멤버 함수에서 매개 변수의 서로 다른 숫자

template<typename A1> 
void Attach(A1 a1); 

template<typename A1, typename A2> 
void Attach(A1 a1, A2 a2); 

template<typename A1, typename A2, typename A3> 
void Attach(A1 a1, A2 a2, A3 a3); 

template<typename A1, typename A3, typename A4> 
void Attach(A1 a1, A2 a2, A3 a3, A4 a4); 
관련 문제