make_tuple с параметрами шаблона не компилируется
Рассмотрим этот код:
#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
}
Почему auto tup3 = ...
не компилировать? По-видимому, make_tuple<int>(...)
хочет ссылку на значение в качестве аргумента; но почему?
(Я использую GCC 6.1.0.)
1 ответ
Решение
std::make_tuple
а также std::make_pair
предназначены для вывода параметров шаблона (среди прочего, как распаковка справочных упаковщиков). Предоставление их явно является ошибкой.
В данном конкретном случае это происходит потому, что вывод шаблона для rvalues возвращает их тип, аналогичный следующему примеру:
template<typename T>
void foo(T&&);
foo(42); // foo<int>(int&&)
int i{};
foo(i); // foo<int&>(int&) // after reference collapsing
И вот почему make_tuple<int>(...)
хочет Rvalue ссылку на свой аргумент.
Если вы хотите форсировать конверсии, все, что вам нужно сказать, это
auto tup1 = std::tuple<long>(i);