Consider this code:
#include <tuple>
int main()
{
int i;
long k;
auto tup1 = std::make_tuple<long>(i); // Compiles
auto tup2 = std::make_tuple<int>(k); // Compiles
auto tup3 = std::make_tuple<int>(i); // Does not compile
auto tup4 = std::make_tuple<int>(i+0); // Compiles
auto tup5 = std::make_tuple(i); // Compiles
}
Why does auto tup3 = ...
not compile? Apparently, make_tuple<int>(...)
wants an rvalue reference as its argument; but why?
(I'm using GCC 6.1.0.)
std::make_tuple
and std::make_pair
are designed to deduce template parameters (among other things, like unpacking reference wrappers). Providing them explicitly is a mistake.
In this particular case, it's because template deduction for rvalues yields their type, analogous to this example:
template<typename T>
void foo(T&&);
foo(42); // foo<int>(int&&)
int i{};
foo(i); // foo<int&>(int&) // after reference collapsing
and that's why make_tuple<int>(...)
wants a rvalue reference to its argument.
If you want to force conversions, all you need to say is
auto tup1 = std::tuple<long>(i);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With