使用可变参数模板打印列表

print a list using variadic templates

我需要你的帮助来找出为什么以下代码无法编译。

#include <iostream>

template <int I>
void foo(){
  std::cout << I << std::endl;
  std::cout << "end of list" << std::endl;
}

template <int I, int ... Ints>
void foo(){
  std::cout << I << std::endl;
  foo<Ints...>();
}


int main(){
  foo<1, 2>();
  return 0;
}

我遇到了这个错误。

function_parameter_pack.cpp: In instantiation of ‘void foo() [with int I = 1; int ...Ints = {2}]’:
function_parameter_pack.cpp:17:13:   required from here
function_parameter_pack.cpp:12:15: error: call of overloaded ‘foo<2>()’ is ambiguous
   foo<Ints...>();
   ~~~~~~~~~~~~^~
function_parameter_pack.cpp:4:6: note: candidate: void foo() [with int I = 2]
 void foo(){
      ^~~
function_parameter_pack.cpp:10:6: note: candidate: void foo() [with int I = 2; int ...Ints = {}]
 void foo(){

不是应该选择更专业的功能吗?即只有一个模板(第一个)。

foo<2> 同样匹配两个模板(因为 int... 也匹配零个 int),这就是编译器抱怨歧义的原因。

Isn't a more specialized function is supposed to be chosen?

是的,但它们同样特别。通过查看函数的参数而不是模板参数来推断哪个是更专业的匹配函数。

解决这个问题的一种方法是使第二个函数模板采用 2 个或更多模板参数:

#include <iostream>

template<int I>
void foo() {
    std::cout << I << std::endl;
    std::cout << "end of list" << std::endl;
}

template<int I, int J, int... Ints>
void foo() {
    std::cout << I << std::endl;
    foo<J, Ints...>();
}

int main() {
    foo<1>();
    foo<1, 2>();
    foo<1, 2, 3>();
}

另一种解决问题的方法是使用一个什么都不做的终端递归函数,它接受与值不同的东西(可能是类型名),但有一个默认值,

template <typename = void>
void foo() {
  std::cout << "end of list" << std::endl;
}

Ints... 为空时拦截 foo<Ints...>() 调用。

拦截每个模板整数值的递归情况保持不变

template <int I, int ... Ints>
void foo(){
  std::cout << I << std::endl;
  foo<Ints...>();
}

我更喜欢使用虚拟数组的解决方案,因此它的工作方式类似于折叠表达式。

template<int... Ints>
void foo() {
    char dummy[] {((std::cout << Ints << ','), '0')...};
    std::cout << '\n';
}

https://godbolt.org/z/1Y1noK