模板化 boost::bind 自动处理成员函数的多个参数

发布于 2024-09-15 06:30:25 字数 2092 浏览 4 评论 0原文

我有一个带有“附加”函数的类,它接受函数对象并将其存储到集合中。类本身是根据函数签名进行模板化的。像这样的事情:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忆沫 2024-09-22 06:30:26

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

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.

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);
恍梦境° 2024-09-22 06:30:25

在成员函数中重载 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文