Ralph Tandetzky
Ralph Tandetzky

Reputation: 23660

What is the difference between std::tie and std::make_tuple with std::ref arguments?

Is there any semantic difference between writing the expression

std::tie( x, y, z )

and the following expression?

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

If so, what are the differences?

By the way, this question is not asking the same as What is the difference between assigning to std::tie and tuple of references? because the tuple of references is not created via std::ref, but by explicitly specifying the type.

Upvotes: 22

Views: 3079

Answers (2)

Barry
Barry

Reputation: 304182

There is almost no functional difference between the two expressions. tie() is just shorter whereas make_tuple() is more generic.


According to [tuple.creation], make_tuple does:

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

Let Ui be decay_t<Ti> for each Ti in Types. Then each Vi in VTypes is X& if Ui equals reference_wrapper<X>, otherwise Vi is Ui.

Hence std::make_tuple( std::ref(x), std::ref(y), std::ref(z) ) yields a std::tuple<X&, Y&, Z&>.

On the other hand, tie does:

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

Returns: tuple<Types&...>(t...). When an argument in t is ignore, assigning any value to the corresponding tuple element has no effect.

Hence, std::tie(x, y, z) also yields a std::tuple<X&, Y&, Z&>.


Except in one edge case.

Upvotes: 19

cpplearner
cpplearner

Reputation: 15938

There is a difference when any of x, y and z is a specialization of 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&>
}

Upvotes: 16

Related Questions