【发布时间】:2014-06-02 12:20:53
【问题描述】:
我看到了以下博客文章,其中解释了如何使用可变参数模板构建 C++ 委托:http://blog.coldflake.com/posts/2014-01-12-C++-delegates-on-steroids.html
我在这里复制了帖子中的 Delegate 类:
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 。有没有更好的解决方案?
【问题讨论】:
-
如果您不介意要求每个被调用者都以这种方式存储,您可以保留
shared_ptr<void>而不是void*。 -
你可以看看使用共享指针。
-
这不是问题的答案,而是一个捕获
shared_ptr给被调用者并调用函数的 lambda,它似乎可以轻松完成Delegate所做的所有事情:auto a = std::make_shared<A>(); auto d = [a](int x) { a->foo(x); }; -
@BigLudinski 删除器仍然会知道实际类型并做正确的事情(只要它被创建为
std::shared_ptr<A>并且稍后仅转换为std::shared_ptr<void>)。 -
@BigLudinski 它应该可以正常工作。这里有解释stackoverflow.com/questions/5913396/…
标签: c++ templates delegates variadic