我看到以下博客文章解释了如何使用可变参数模板构建C ++代理:http://blog.coldflake.com/posts/2014-01-12-C++-delegates-on-steroids.html
我在这里的帖子中复制了代表课程:
template<typename return_type, typename... params>
class Delegate
{
typedef return_type (*Type)(void* callee, params...);
public:
Delegate(void* callee, Type function)
: fpCallee(callee)
, fpCallbackFunction(function) {}
template <class T, return_type (T::*TMethod)(params...)>
static Delegate from_function(T* callee)
{
Delegate d(callee, &methodCaller<T, TMethod>);
return d;
}
return_type operator()(params... xs) const
{
return (*fpCallbackFunction)(fpCallee, xs...);
}
private:
void* fpCallee;
Type fpCallbackFunction;
template <class T, return_type (T::*TMethod)(params...)>
static return_type methodCaller(void* callee, params... xs)
{
T* p = static_cast<T*>(callee);
return (p->*TMethod)(xs...);
}
};
这里给出了如何使用该类的示例:
class A
{
public:
int foo(int x)
{
return x*x;
}
int bar(int x, int y, char a)
{
return x*y;
}
};
int main()
{
A a;
auto d = Delegate<int, int>::from_function<A, &A::foo>(&a);
auto d2 = Delegate<int, int, int, char>::from_function<A, &A::bar>(&a);
printf("delegate with return value: d(42)=%d\n", d(42));
printf("for d2: d2(42, 2, 'a')=%d\n", d2(42, 2, 'a'));
return 0;
}
这项技术非常酷,除了我还想让Delegate类管理被调用者的生命周期(换句话说,我想在堆上实例化A,并且当Delegate实例被删除或去超出范围,它也应该能够删除被调用者(在这种情况下为A实例))。有一个简单的方法吗?我错过了什么吗?一种解决方案是传递一个删除对象,它会将void * fpCallee转换为正确的类型,然后调用delete ont。有更好的解决方案吗?
答案 0 :(得分:4)
您可以使用shared_ptr<void>
来存储被叫方而不是void*
(请参阅this question了解为什么这不会导致删除问题;感谢Kindread)。这将要求您将每个被叫方保持在shared_ptr
,但如果您不介意,则可以解决您的问题。
虽然这不是问题的答案,但你可以使用lambda而不是Delegate
来完成同样的事情:
auto a = std::make_shared<A>();
auto d = [a](int x) { a->foo(x); };