我有以下代码:
#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));
}
我有两个问题:
1。
我不明白为什么行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.
然而,如果我将参数f
转换为std::function
(如在非注释行中),它就可以工作。
2。
最令人费解的问题是,如果我使用func
的非变量版本(即只需将typename...
替换为typename
,那么实际上func
需要{{1} }}作为参数),然后std::function<Return(Params)>
中的注释行按需运行。有什么想法吗?
答案 0 :(得分:11)
我不明白为什么行
func<void, double>(f);
会给我一个编译错误
编译器不知道你希望Params
完全 double
,它认为你可能希望它推断出包含更多元素的包,例如如double, int, void*, char
或double, double, double
或其他一些类型,并且它不知道如何从参数f
中推断出来。
理论上可以有std::function
的其他特化,可以从f
构造,并允许编译器推导出Params
的多个类型的包(它可以&如果没有实例化 std::function
的每个可能的特化并测试它们,那就不是真的。
如果我将参数
f
强制转换为std::function
(如在非注释行中),则可以正常工作。
因为现在编译器能够正确推导出Params
。
最令人费解的问题是,如果我使用
func
[...]的非变量版本,那么main中的注释行将按照需要运行。有什么想法吗?
因为现在编译器知道Params
是单一类型,而不是零或更多类型的包,所以当你说func<void, double>
它知道Params
是double
时,而不是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");
我只给出了两个参数的显式模板参数,因此仍然必须推导出第三个参数。
当你有一个可变参数模板时,可能会有任何数量的其他参数被推断出来。