std :: function中的可变参数模板参数匹配

vso*_*tco 8 c++ templates variadic-templates c++11

我有以下代码:

#include <iostream>
#include <functional>

template<typename Return, typename... Params>
void func(std::function<Return(Params... )> x) {}

void f(double) {}

int main() {
    //func<void, double>(f); // compile error here in the variadic case
    func(std::function<void(double)>(f));
}
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

我不明白为什么这行func<void, double>(f);会给我一个编译错误

/Users/vlad/minimal.cpp:10:5: error: no matching function for call to 'func'
    func<void, double>(f); // compile error here in the variadic case
    ^~~~~~~~~~~~~~~~~~
/Users/vlad/minimal.cpp:5:6: note: candidate template ignored: could not match 'function<void (double, type-parameter-0-1...)>' against 'void (*)(double)'
void func(std::function<Return(Params... )> x) {}
     ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

而如果我将参数f转换为std::function(如在非注释行中)它可以工作.

2.最令人费解的问题是,如果我使用非变量版本func(即只是替换typename...typename实际上func需要一个std::function<Return(Params)>as参数),那么注释行将main按照需要工作.有什么想法吗?

Jon*_*ely 11

我不明白为什么这行func<void, double>(f);会给我一个编译错误

编译器不知道你想Params成为准确 double,它认为也许你希望它演绎一包有更多的元素,比如double, int, void*, chardouble, double, double或类型的其他一些包,它不知道如何推断,从参数f.

从理论上说可能有其他专长的std::function可能是constructible从f并让编译器来推断一个以上类型的包Params(它无法知道这是不是没有真正的实例每一个可能的专业化std::function和测试它们,这是不可行的.

而如果我将参数f转换为std::function(如在非注释行中)它可以工作.

因为现在编译器能够Params正确推导出来.

最令人费解的问题是,如果我使用func[...] 的非变量版本,那么主要的注释行将按照需要使用.有什么想法吗?

因为现在编译器知道它Params是单个类型,而不是一个零或更多类型的包,所以当你说它func<void, double>知道Paramsdouble,而不是double, int, void*, char或其他一些参数包时.

编辑回答您的评论,请考虑以下事项:

template<typename T, typename U, typename V>
int func(T t, U u, V v)
{ return 0; }

int i = func<int, char>(1, '2', "three");
Run Code Online (Sandbox Code Playgroud)

我只给出了两个参数的显式模板参数,因此仍然必须推导出第三个参数.

当您拥有可变参数模板时,可能还有许多其他参数需要推导出来.

  • 不,没有必要为每个参数提供一个显式的模板参数,所以`func <void,double>`只说前两个参数是`void`和`double`,它没有说没有更多的参数. (3认同)