【问题标题】:Managing C++ Delegate lifetime管理 C++ 委托生命周期
【发布时间】: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&lt;void&gt; 而不是 void*
  • 你可以看看使用共享指针。
  • 这不是问题的答案,而是一个捕获 shared_ptr 给被调用者并调用函数的 lambda,它似乎可以轻松完成 Delegate 所做的所有事情:auto a = std::make_shared&lt;A&gt;(); auto d = [a](int x) { a-&gt;foo(x); };
  • @BigLudinski 删除器仍然会知道实际类型并做正确的事情(只要它被创建为 std::shared_ptr&lt;A&gt; 并且稍后仅转换为 std::shared_ptr&lt;void&gt;)。
  • @BigLudinski 它应该可以正常工作。这里有解释stackoverflow.com/questions/5913396/…

标签: c++ templates delegates variadic


【解决方案1】:

您可以使用shared_ptr&lt;void&gt; 来存储被调用者而不是void*(请参阅this question 了解为什么这不会导致删除问题;感谢 Kindread)。这将要求您将每个被调用者保留在 shared_ptr 中,但如果您不介意,它会解决您的问题。

虽然这不是问题的答案,但您可以使用 lambda 而不是 Delegate 完成几乎相同的事情:

auto a = std::make_shared<A>();
auto d = [a](int x) { a->foo(x); };

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多