我一直在尝试使用模板化函数调用一组类似函数来避免样板。
FooA(float a, Widget* w);
FooB(int b, Widget* w);
FooC(int c, Widget* w);
FooD(int d, int e, Widget* w);
template <typename... Args>
static void RunFoo(void (*foo)(Args..., Widget*), Args... args) {
Widget w
foo(args, &w);
}
我不明白为什么这样可以正常使用:
float a = 10;
RunFoo(FooA, a);
但是每当我尝试使用多个参数时它都会失败:
int a = 10;
int b = 3;
RunFoo(FooD, a, b);
无法编译错误: “候选模板被忽略:模板参数扣除失败”
这是否超出了c ++模板的功能?
答案 0 :(得分:4)
template<class T>struct tag {using type=T;};
template<class Tag>using type_t=typename Tag::type;
template<class T>using block_deduction=type_t<tag<T>>;
template <typename... Args>
static void RunFoo(block_deduction<void(*)(Args...,Widget*)> foo, Args... args) {
Widget w
foo(args, &w);
}
你无法推断Args..., Widget*
- 参数包必须是最后的。
两种情况都是平等的#34;扣除。 block_deduction
可防止对该参数进行扣减。所以其他推论发生了,并且有效。
请注意,这种扣除通常是个坏主意。您不想推导出一个参数,并在其他地方生成函数指针。它很脆弱。
这可能会更好:
template <class F, class... Args>
static std::result_of_t<F(Args..., Widget*)> RunFoo(F&& f, Args&&... args) {
Widget w
return std::forward<F>(f)(std::forward<Args>(args)..., &w);
}
如果要传递重载集,请将重载设置包装在重载集对象中。 std::result_of_t<?>
是C ++ 14,在C ++ 11中替换为typename std::result_of<?>::type
。