我有一个带有“Attach”功能的类,它接受一个函数对象并将其存储到一个集合中。类本身是在函数签名上模板化的。像这样:
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);
};
要将Listening
上的函数传递给Event
,我需要写一下:
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);
,这样事件Attach将与&lt; Signature&gt;中包含的适当数量的参数神奇地绑定。 (在这个例子中,int(int, int, int)
)?我对这里你想到的任何模板元编程魔术持开放态度。
感谢。
编辑:事实证明我在这里不需要boost::mem_fn
,因为boost::bind
是等效的,所以在我的宏中我可以使用:
bind(&MyClass::Hello, myClass, _1, _2, _3);
,而不是:
bind(mem_fn(&MyClass::Hello), myClass, _1, _2, _3);
但问题仍然存在:如何将&MyClass::Hello
传递给事件类并使用模板重载来处理_1
,_2
,_3
等隐含的问题。函数原型用于模板Event
类?
答案 0 :(得分: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);
答案 1 :(得分:2)
在成员函数中为不同数量的参数重载Attach
:
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));
}
如果您还需要处理const
成员函数,那么您将需要第二组重载。