尝试编译以下代码片段:此代码显然使用C ++ 11功能,并在“C ++编程语言”一书§3.4.4中有所描述。
template<typename T>
void g(T x)
{
std::cout << x << " ";
}
template<typename T, typename... Tail>
void f(T head, Tail... tail) {
g(head); // do something to head
f(tail...); // tr y again with tail
}
void f() {}
int main()
{
f(1, "Lol", 5);
getchar();
}
VS17输出:
C2672'f':未找到匹配的重载函数行:21
'void f(T,Tail ......)':期望2个参数 - 0提供Line:19
有任何想法吗 ?
这里有三件事不正确。
tail
参数阴影模板名称tail
f()
的基本情况f()
必须在其他f(...)
之前定义,因为高级函数查找不会在这样的递归函数中发生。解决方案
将参数tail
的名称更改为其他类似的名称
template<typename T, typename... tail>
void f(T head, tail... ftail) { //tail here was shadowing actual template name tail so changed to ftail
g(head); // do something to head
f(ftail...); // try again with tail
}
当您对f()
进行递归调用时,会出现没有值传递给f(..)
的时间,因为每次递归调用都会减少传递的参数数量1。
所以让我们说你开始使用f(1, "Lol", 2)
,内部递归调用f("Lol", 2)
这个内部调用f(2)
调用f()
,但你的函数f
预计至少有1个参数。因此错误
要解决这个问题,请简单地将f
重载为基本情况,不要使用任何参数
void f(){
//last recursive call made
}
这是完整的代码
#include<iostream>
template<typename T>
void g(T x)
{
std::cout << x << " ";
}
void f(){ }
template<typename T, typename... tail>
void f(T head, tail... ftail) {
g(head); // do something to head
f(ftail...); // try again with tail
}
int main()
{
f(1, "Lol", 5);
getchar();
}
首先是MCVE:
template<typename T, typename... Tail>
void f(T head, Tail... tail) {
f(tail...); // tr y again with tail
}
f(1, 2, 3);
现在实例化:
f<int, int, int>(1, 2, 3);
编译为:
template<T = int, Tail...={int,int}>
void f(int head, int tail0, int tail1) {
f(tail0, tail1); // tr y again with tail
}
递归调用是:
f<int,int>(tail0, tail1); // tr y again with tail
编译为:
template<T = int, Tail...={int}>
void f(int head, int tail0) {
f(tail0); // tr y again with tail
}
递归调用解析为:
f<int>(tail0); // tr y again with tail
编译为:
template<T = int, Tail...={}>
void f(int head) {
f(); // tr y again with tail
}
在这里我们试着打电话给f()
。
没有有效的f()
调用可见,因此您收到错误消息。
调用void f() {}
的f()
在这里没有帮助,因为在模板中查找是在f()
可见之前完成的。
如果您想以简单的方式解决这个问题,可以在inline void f(){}
模板上方添加f
。
更复杂的方式?
template<class...Ts>
void f(Ts...ts) {
using discard=int[];
(void)discard{ 0, ( void(
g(ts)
),0)...};
}
这也消除了递归。或者在c++17:
template<class...Ts>
void f(Ts...ts) {
( (void)(g(ts)), ... );
}
这也更快编译,因为它创建了更少(和更短)的符号。