Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are template arguments not deduced automatically in that example?

While playing around with variadic templates I came around that:

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;
};

I want just learn to understand what's going on here: We can instantiate such tuple by

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

but not with:

tuple myTuple2(1234, 33.444, "I", "like", "C++");

Why is the compiler not able to infer automatically the types from the list of given types?

If I do

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

...
...

swap<int>(a, b);
swap(a, b);

both variants are possible. Is that not possible for variadic template arguments? What are the rules C++ uses for inferring types?

like image 574
MichaelW Avatar asked Dec 06 '19 13:12

MichaelW


1 Answers

tuple myTuple2(1234, 33.444, "I", "like", "C++");

Is a variable declaration and initialization by calling the constructor, while

swap(a, b);

Is a function call.

While C++ always had function template argument deduction, it didn't support class template argument deduction until C++17. That is the reason why std::make_tuple exists. Because you couldn't do std::tuple t(1, 2.4) and so you had a function and could write auto t = std::make_tuple(1, 2.4).

So you need C++17 and for your example you also need a deduction guide:

template <class... Ts>
tuple(Ts...) -> tuple<Ts...>;

And it works.

like image 83
bolov Avatar answered Sep 21 '22 17:09

bolov