管理C ++委托生命周期

时间:2014-06-02 12:20:54

标签: c++ templates delegates variadic

我看到以下博客文章解释了如何使用可变参数模板构建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。有更好的解决方案吗?

1 个答案:

答案 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); };