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?
source to share
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)...);
// ^^^^^^^^^^^^^^^^^^^ ^
}
source to share