3

I want to put several method pointers in a container, so I implemented a simple std::function- like template class:

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 Method in a container, and call Invoke() to call a function. It worked. But once I changed the declaration of func to:

void func(int&&);

It seems like no matter which type I pass to Method::Invoke(), a int&& will not be deduced, so the dynamic_cast fails.

Should I make some amendment to Method::Invoke? If so, How? Or there is a different solution?

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
Bei
  • 71
  • 6

1 Answers1

0

You should use perfect-forwarding via std::forward, otherwise your rvalue/lvalue references won't likely be retained (for more informations see this beautiful answer):

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)...);
//                      ^^^^^^^^^^^^^^^^^^^    ^
}
Community
  • 1
  • 1
Shoe
  • 74,840
  • 36
  • 166
  • 272
  • How about `func` take a `int` parameter? My understanding: `Args` will be deduced `int`, and the `dynamic_cast` fails. – Bei May 17 '15 at 09:08