模板化 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);
};
要将 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 就会神奇地与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
、用于模板化 Event
类的函数原型暗示了 _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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将
Attach()
制作为模板将允许您实现您的目标。代码变得混乱,但它让你可以按照你想要的方式调用它。Making
Attach()
a template would allow you to do what you're aiming for. The code gets messy but it let's you call it the way you want.在成员函数中重载
Attach
不同数量的参数:如果您还需要处理
const
成员函数,那么您将需要第二组重载。Overload
Attach
for different numbers of parameters in the member function:If you need to handle
const
member functions too then you'll need a second set of overloads.