为什么我的模板参数包不起作用?

Why doesn't my template parameter pack work?

我一直在尝试获得一个模板化函数来调用一组类似的函数以避免样板。

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

编译失败,报错: "candidate template ignored: failed template argument deduction"

这是否超出了 c++ 模板的能力?

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*那样推断——参数包通常必须放在最后。

两种情况都是"equal"推导。 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