How to implement type resistor for std :: function like classes?

I want to put multiple pointers to pointers in a container, so I applied a simple class-like std::function

pattern:

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;
};

      

It has a base class, so I can write code like this:

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

      

Then I add a wrapper to call Invoke()

from MethodHolderBase

:

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;
}

      

Now I can put some instances of the method in a container and call Invoke()

to call the function. It worked. But as soon as I changed the declaration func

to:

void func(int&&);

      

It seems that no matter what type I pass to Method::Invoke()

, a int&&

will not be inferred, so it dynamic_cast

fails.

Do I need to make some amendment Method::Invoke

? If so, how? Or is there another solution?

+3


source to share


1 answer


You have to use flawless forwarding through std::forward

, otherwise rvalue / lvalue references are unlikely to be preserved ( see this beautiful answer for more information ):

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

      



and then:

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

      

0


source







All Articles