按照定义 Args 应该是可以接受 0 个参数的,但是为什么如下的代码不能正确编译呢?( c++11)
#include <iostream>
#include <string>
template <typename T, typename... Args>
auto print(std::ostream& os, const T& t, const Args&... rest) -> decltype(os)
{
os << t;
if (sizeof...(Args) == 0)
return os << t;
else
return print(os, rest...);
}
int main()
{
print(std::cout, std::string("hepup"));
print(std::cout, 1, 2.23434);
print(std::cout, "hello", '\n', 3.134, true, 1e8);
return 0;
}
错误提示的是
recursive.cc:16:16: error: no matching function for call to 'print'
return print(os, rest...);
^~~~~
recursive.cc:21:5: note: in instantiation of function template specialization
'print<std::__1::basic_string<char>>' requested here
print(std::cout, std::string("hepup"));
^
recursive.cc:10:6: note: candidate function template not viable: requires at least 2
arguments, but 1 was provided
auto print(std::ostream& os, const T& t, const Args&... rest) -> decltype(os)
^
1 error generated.
诸如此类的。
按照标准A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates)
那么应该是可以接受 0 个参数,然后通过判断条件结束递归。可是为什么会编译出错呢?
1
geelaw 2020-01-07 14:47:50 +08:00
因为一个对 print(os) 的调用总是会产生,所以出错。
一种解法是用 if constexpr 阻止不发生的路径的代码生成。 另一种是用重载 template <typename T> std::ostream &print(std::ostream &os, T const &t) { return os << t; } template <typename T, typename ...TRest> std::ostream &print(std::ostream &os, T const &t, const TRest &...rest) { return print(os << t, rest...); } 第一个版本更加优先。 更自然的解法是允许 0 个东西被打印: template <typename T> std::ostream &print(std::ostream &os) { return os; } template <typename T, typename ...TRest> std::ostream &print(std::ostream &os, T const &t, const TRest &...rest) { return print(os << t, rest...); } |
2
ipwx 2020-01-07 14:49:08 +08:00
|
3
ipwx 2020-01-07 14:50:27 +08:00
哦不用类型特例化包一层,还是用楼上的函数重载吧。。。写 Python 写多了忘记了 C++ 有函数重载这回事情,看见编译器报错不让函数模板特例化就下意识上类型特例化了。
|
4
jimages OP @geelaw 第一个方法的确可以解,这也是书上的标准解法。而至于第二个方法,我刚刚已经试过了,这样似乎是不行的?我的代码大概如下,https://paste.ubuntu.com/p/bCjScgBPm2/
报错仍然为 no matching function for call to 'print',具体错误内容与之前的错误提示类似。 |