为什么在那个例子中没有自动推导出模板参数?

mic*_*ael 7 c++ templates variadic-templates

在使用可变参数模板时,我遇到了:

template <class... Ts> struct tuple {};

template <class T, class... Ts>
struct tuple<T, Ts...> : tuple<Ts...> 
{
    tuple(T t, Ts... ts) : tuple<Ts...>(ts...), tail(t) {}

    T tail;
};
Run Code Online (Sandbox Code Playgroud)

我只想学会理解这里发生了什么:我们可以通过以下方式实例化这样的元组

tuple<int, double, const char*, const char*, const char*> myTuple(1234, 33.444, "I", "like", "C++");
Run Code Online (Sandbox Code Playgroud)

但不是:

tuple myTuple2(1234, 33.444, "I", "like", "C++");
Run Code Online (Sandbox Code Playgroud)

为什么编译器不能从给定类型列表中自动推断类型?

如果我做

template <class T>
void swap(T& first, T& second) {
   T aux = first;
   first = second;
   second = aux;
}

...
...

swap<int>(a, b);
swap(a, b);
Run Code Online (Sandbox Code Playgroud)

两种变体都是可能的。这对于可变参数模板参数是不可能的吗?C++ 用于推断类型的规则是什么?

bol*_*lov 12

tuple myTuple2(1234, 33.444, "I", "like", "C++");
Run Code Online (Sandbox Code Playgroud)

是通过调用构造函数来声明和初始化变量,而

swap(a, b);
Run Code Online (Sandbox Code Playgroud)

是一个函数调用。

虽然 C++ 总是有函数模板参数推导,但它直到 C++17 才支持类模板参数推导。这就是std::make_tuple存在的原因。因为你不能做std::tuple t(1, 2.4),所以你有一个函数,可以写auto t = std::make_tuple(1, 2.4).

所以你需要 C++17,对于你的例子,你还需要一个演绎指南:

template <class... Ts>
tuple(Ts...) -> tuple<Ts...>;
Run Code Online (Sandbox Code Playgroud)

它的作品

  • 也许可以通过指出 C++17 之前的正常答案是定义一个函数 `make_tuple` 并使用 `auto myTuple2 = make_tuple(1234, 33.444, "I", "like", "C++") 来扩展答案;` (2认同)