可变参数模板未编译

1 c++ recursion templates variadic-templates

#include <iostream>

template<typename A, typename... B>
void prints(A num, B... args){
    std::cout << num << std::endl;
    prints(args...);
}

int main(){
    prints(1,2,3);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我编译时,我收到这些错误:

在实例化 'void prints(A, B ...) [with A = int; B = {}]':
错误:没有用于调用“prints()”的匹配函数

main.cpp:4:10: 注意:模板参数推导/替换失败:
main.cpp:7:11: 注意:候选人需要至少 1 个参数,0 提供

max*_*x66 5

您的函数等待 1 个或多个参数:

template<typename A, typename... B>
void prints(A num, B... args)
Run Code Online (Sandbox Code Playgroud)

当您仅使用 1 个参数调用它时,args...包为空,因此递归调用:

prints(args...);
Run Code Online (Sandbox Code Playgroud)

变成

prints();
Run Code Online (Sandbox Code Playgroud)

但是您的函数等待(至少)1 个参数,因此无法匹配此调用。

您需要添加一个零参数重载prints()以匹配空调用:

void prints()
{ }
Run Code Online (Sandbox Code Playgroud)

并且您必须在递归版本之前声明它。

正如从 C++17 开始的 Evg(感谢)所指出的,您可以避免零参数重载,并且使用if constexpr,您只能在args...不为空时调用递归。

那就是...从 C++17 开始你可以写

template <typename A, typename... B>
void prints (A num, B... args) {
   std::cout << num << std::endl;

   if constexpr ( sizeof...(args) > 0u )
      prints(args...);
}
Run Code Online (Sandbox Code Playgroud)

并且您不再需要零参数重载。

请注意,如果您只是编写(使用简单的if, no if constexpr

   if ( sizeof...(args) > 0u )
      prints(args...);
Run Code Online (Sandbox Code Playgroud)

你会得到(没有零参数重载)一个编译错误,因为编译器prints(args...)sizeof...(args)为零时也必须编译该部分(正是if constexpr为了避免这种情况)。