我编写了一个可变参数模板,用递归打印所有参数:
#include <iostream>
using std::ostream; using std::istream;
using std::cin; using std::cout; using std::endl;
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
if (sizeof...(rest)) {
os << t << ", ";
return myprint(os, rest...);
}
else
return os << t;
}
int main(int argc, char *argv[]) {
myprint(cout, "hello");
return 0;
}
但是当我用g++ -std=c++1y
编译它时,它会抱怨:
error: no matching function for call to ‘myprint(std::ostream&)’
return myprint(os, rest...);
在函数myprint
中,我检查了sizeof...(rest)
的值。当它为0时,它不会调用myprint(os, rest...)
。所以我不知道为什么会拨打myprint(std::ostream&)
。
我还搜索了相关问题,我发现它需要基本情况。但为什么我需要一个基本案例,而且sizeof...
可以在一个可变参数模板中工作?
对于简单的无限递归情况:
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
os << t << ", "; // print the first argument
return print(os, rest...); // recursive call; print the other arguments
}
上述代码根本无法针对相同的错误进行编译。
答案 0 :(得分:4)
对于您使用的if statement,无论条件, statement-true 和 statement-false 都必须有效得到true
或false
的结果。
从C ++ 17开始,您可以使用constexpr if;当 condition 的值为false
时, statement-true 将被丢弃。 e.g。
if constexpr (sizeof...(rest)) {
os << t << ", ";
return myprint(os, rest...);
}
else
return os << t;
如果你不能使用C ++ 17,你可以为参数个数只有一个的情况添加另一个模板重载,以阻止递归,例如。
template <typename T>
ostream &myprint(ostream &os, const T &t) {
return os << t;
}
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
os << t << ", ";
return myprint(os, rest...);
}
答案 1 :(得分:2)
songyuanyao's answer解释了为什么它无效并为C ++ 17提供了解决方案。或者,您可以在此之前将myprint
作为基本案例。
template <typename T>
ostream &myprint(ostream &os, const T &t) {
return os << t;
}
template <typename T, typename... Args>
ostream &myprint(ostream &os, const T &t, const Args&... rest) {
os << t << ", ";
return myprint(os, rest...);
}