参数包迭代

Parameter pack iteration

为什么这段代码无法编译?

#include <iostream>
#include <typeinfo>

template <typename ...Ts>
void f();

template <typename T>
void f() {
    std::cout << typeid(T).name() << std::endl;
}

template <typename T, typename U, typename ...Ts>
void f() {
    std::cout << typeid(T).name() << ", ";
    f<U, Ts...>();
}

int main(int argc, char** argv)
{
    f<int, float, char>();
}

MSVC 编译器错误: 错误 C2668:'f':对重载函数的调用不明确

预期输出:

int, float, char

附带问题:是否有更现代的方法来做同样的事情?

编辑 我找到了一种接受零模板包的方法:

#include <typeinfo>
#include <iostream>
#include <type_traits>

template <typename ...Ts>
using is_empty_pack = std::enable_if_t<sizeof ...(Ts) == 0>;

template <typename ...Ts, typename = is_empty_pack<Ts...>>
void f() {}

template <typename T, typename ...Ts>
void f() {
    std::cout << typeid(T).name();
    if constexpr (sizeof ...(Ts) > 0) std::cout << ", "; else std::cout << std::endl;
    f<Ts...>();
}

int main(int argc, char *argv[])
{
    f<>();
    f<int>();
    f<int, float>();
}

还有其他建议吗?

使用 g++ 编译可以非常清楚地解释正在发生的事情:

prog.cc: In function 'int main(int, char**)':
prog.cc:20:24: error: call of overloaded 'f<int, float, char>()' is ambiguous
   20 |     f<int, float, char>();
      |     ~~~~~~~~~~~~~~~~~~~^~
prog.cc:5:6: note: candidate: 'void f() [with Ts = {int, float, char}]'
    5 | void f();
      |      ^
prog.cc:13:6: note: candidate: 'void f() [with T = int; U = float; Ts = {char}]'
   13 | void f() {

您提供了三个不同的模板函数 f,其中两个可以与您在此处编写的内容相匹配。

编辑: 也许您认为第一个是声明,另外两个是特化,但这不是模板的工作方式。专门化意味着专门化特定模板参数的类型或值,而不是专门化模板参数的数量

正在删除

template <typename ...Ts>
void f();

将使程序编译并 运行 具有预期的行为。