我想在容器中放入几个方法指针,所以我实现了一个简单的std::function
- 类似模板类:
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));
...
然后我添加了一个包装来从Invoke()
调用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;
}
现在,我可以在容器中放置一些Method实例,并调用Invoke()
来调用函数。有效。但是,一旦我将func
的声明更改为:
void func(int&&);
似乎无论我传递给Method::Invoke()
哪种类型,都不会推断出int&&
,因此dynamic_cast
会失败。
我应该对Method::Invoke
做一些修改吗?如果是这样,怎么样?或者有一个不同的解决方案?
答案 0 :(得分:0)
您应该通过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)...);
// ^^^^^^^^^^^^^^^^^^^ ^
}