【问题标题】:How to implement a type eraser for std::function like classes?如何为 std::function 之类的类实现类型橡皮擦?
【发布时间】:2015-05-16 06:50:00
【问题描述】:

我想在一个容器中放几个方法指针,所以我实现了一个简单的std::function-like模板类:

template<typename ...Args>
class MethodHolder : MethodHolderBase
{
public:
    typedef void(*MethodType)(Args...);
    MethodHolder(MethodType method) : method(method) {}
    virtual ~MethodHolder() {}

    void Invoke(Args... args)
    { method(args...); }

private:
    MethodType method;
};

它有一个基类,所以我可以编写如下代码:

void func(int);
...
std::vector<MethodHolderBase*> funcs;
funcs.push_back(new MethodHolder<int>(&func));
...

然后我添加一个包装器以从MethodHolderBase 调用Invoke()

class Method
{
public:
    ...//constructors, assignment operator, destructor
    template<typename ...Args>
    void Invoke(Args&&... args)
    {
        auto pHolder = dynamic_cast<MethodHolder<Args...>*>(pBase);
        if (pHolder)
            pHolder->Invoke(args...);
    }
private:
    MethodHolderBase* pBase;
}

现在,我可以将一些 Method 的实例放在一个容器中,然后调用 Invoke() 来调用一个函数。有效。但是一旦我将func 的声明更改为:

void func(int&&);

似乎无论我传递给Method::Invoke()的哪种类型,都不会推导出int&amp;&amp;,因此dynamic_cast失败。

我应该对Method::Invoke 做一些修改吗?如果是这样,如何?还是有其他解决方案?

【问题讨论】:

    标签: c++ type-erasure std-function


    【解决方案1】:

    您应该通过std::forward 使用完美转发,否则您的右值/左值引用可能不会被保留(更多信息see this beautiful answer):

    void Invoke(Args&&... args)
    //              ^^
    { method(std::forward<Args>(args)...); }
    //       ^^^^^^^^^^^^^^^^^^^    ^
    

    然后:

    template<typename ...Args>
    void Invoke(Args&&... args)
    {
        auto pHolder = dynamic_cast<MethodHolder<Args&&...>*>(pBase);
        //                                           ^^
        if (pHolder)
            pHolder->Invoke(std::forward<Args>(args)...);
    //                      ^^^^^^^^^^^^^^^^^^^    ^
    }
    

    【讨论】:

    • func 带一个int 参数怎么样?我的理解:Args会被推导出int,而dynamic_cast会失败。
    猜你喜欢
    • 2020-01-29
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多