我有一个带有重载+ =运算符的模板类Delegate,它使得使用类似于C#的委托。
// ... generalized version of the template omitted from code
template<typename... TArgs>
class Delegate<void, TArgs...>
{
private:
using Func = std::function<void(TArgs...)>;
std::vector<Func> funcs;
public:
template<typename T> Delegate& operator+=(T mFunc) { funcs.push_back(Func(mFunc)); return *this; }
void operator()(TArgs... mParams) { for (auto& f : funcs) f(mParams...); }
};
这就是我要做的事情:
struct s
{
void test() { }
void run()
{
Delegate<void> d;
d += [] { /* do something */ ; };
d += test; // does not compile
}
};
有没有办法允许d += test;
工作?
答案 0 :(得分:3)
void test(int x, int y) { return x - y; }
怎么编译?该函数应该不返回任何内容。其返回类型为void
。
另外,我假设您已定义(或声明)主模板:
template<typename R, typename... TArgs>
class Delegate;
同时假设delegate
是拼写错误,因为类模板为Delegate
。
无论如何,test
没有返回任何内容,它编译得很好:
http://stacked-crooked.com/view?id=c56b7a2e758f8fbc361228834c90822b
对于成员函数指针,您当前的实现不支持它。请注意,非静态成员函数指针采用R (C::*MemPtr)(Args...) cv
的形式。只是努力吧。
答案 1 :(得分:1)
成员函数也需要一个对象的实例来处理。如果使用std::mem_fn
提取函数,则可以将其作为第一个参数,并且还可以使用std::bind
将当前对象绑定到函数
代码清楚说明:
struct s
{
void test() { }
void run()
{
Delegate<void> d;
d += [] { /* do something */ ; };
d += std::bind(std::mem_fn(&s::test), this); // does compile
}
};
我真的没有找到d += test
的方法。你真的需要传递实际的对象。这个lambda版本更清楚地表明您需要当前对象:
struct s
{
void test() { }
void run()
{
Delegate<void> d;
d += [this] { test(); };
}
};
当然,您不需要在运算符+ =行中指定它。您可以在构造函数中修改Delegate
以获取this
,如下所示(runv1
),或者添加一个成员函数,该函数提供可以添加测试函数的代理对象(runv2
):(虽然我没试过这些)
struct s
{
void test() { }
void runv1()
{
Delegatev2<s, void> d(this);
d += test;
}
void runv2()
{
Delegate<void> d;
auto memd = d.getMemberDelegate(this);
memd += test;
}
};
答案 2 :(得分:0)
正如Nawaz在编辑中所说,你使用了一个成员(非satic)函数,它与你的std :: function的void()签名不兼容。
两个解决方案:
std::function<void(s&)>
std::bind(&s::test,&s);
(就像K-ballo说的那样,而Csq说的那样)此外,您应该使用rref和std :: forward来实现完美转发。