模板化boost :: bind自动处理成员函数的多个参数(Templating boost::bind to automatically handle multiple arguments for member function)

我有一个带有“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将与<Signature>中包含的适当数量的参数神奇地绑定(在本例中为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 Event类的函数原型所隐含的_1 , _2 , _3等?

I have a class with an "Attach" function that accepts a function object and stores it into a collection. The class itself is templated on the function signature. Something like this:

template<class Signature> class Event { public: void Attach(boost::function<Signature> signature) { MySignatures.push_back(signature); } private: std::list<boost::function<Signature>> MySignatures; };

To demonstrate usage, consider the following class:

class Listening { public: int SomeFunction(int x, int y, int z); };

To pass the function on Listening into Event, I would need to write:

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

So instead of doing so for each case which may be prone to error, I write a set of macros, as follows:

#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.

and then I can write:

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

which is much easier to read (I think). Now to my question: how can I instead write:

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

or even better:

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

, such that the event Attach will magically bind correctly with the appropriate number of arguments as contained in <Signature> (in this example, int(int, int, int))? I'm open to any template meta-programming magic you have in mind here.

Thanks.

Edit: it turns out I don't need boost::mem_fn here, because boost::bind is equivalent, so in my macro I can use:

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

,instead of:

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

The question remains however: how to pass &MyClass::Hello to the event class and use template overloading to handle the _1, _2, _3, etc. implied by the function prototype used to template the Event class?

最满意答案

重载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成员函数,那么您将需要第二组重载。

Overload Attach for different numbers of parameters in the member function:

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)); }

If you need to handle const member functions too then you'll need a second set of overloads.

更多推荐