Подтвердить что ты не робот

В чем разница между std:: tie и std:: make_tuple с аргументами std:: ref?

Есть ли какая-либо смысловая разница между написанием выражения

std::tie( x, y, z )

и следующее выражение:

std::make_tuple( std::ref(x), std::ref(y), std::ref(z) )

Если да, то каковы различия?

Кстати, этот вопрос не задает то же самое, что В чем разница между назначением std::tie и кортежем ссылок?, потому что кортеж ссылок не созданный с помощью std::ref, но явно указывая тип.

4b9b3361

Ответ 1

Существует почти & dagger; нет функциональной разницы между этими двумя выражениями. tie() меньше, тогда как make_tuple() является более общим.


Согласно [tuple.creation], make_tuple делает:

template<class... Types>
constexpr tuple<VTypes...> make_tuple(Types&&... t);

Пусть Ui будет decay_t<Ti> для каждого Ti в типах. Тогда каждый Vi в VTypes равен X&, если Ui равно reference_wrapper<X>, в противном случае Vi есть Ui.

Следовательно, std::make_tuple( std::ref(x), std::ref(y), std::ref(z) ) дает & dagger; a std::tuple<X&, Y&, Z&>.

С другой стороны, tie делает:

template<class... Types>
constexpr tuple<Types&...> tie(Types&... t) noexcept;

Возвращает: tuple<Types&...>(t...). Когда аргумент в t равен ignore, присвоение любого значения соответствующему элементу набора не влияет.

Следовательно, std::tie(x, y, z) также дает a std::tuple<X&, Y&, Z&>.


& dagger; За исключением одного краевого случая.

Ответ 2

Существует разница, когда любая из x, y и z является специализацией std::reference_wrapper.

#include <tuple>
#include <functional>

void f(std::reference_wrapper<int> x, int y, int z)
{
    std::tie(x,y,z); // type is std::tuple<std::reference_wrapper<int>&, int&, int&>
    std::make_tuple(std::ref(x),std::ref(y),std::ref(z)); // type is std::tuple<int&, int&, int&>
}