Reputation: 23660
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
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
bedecay_t<Ti>
for eachTi
in Types. Then eachVi
inVTypes
isX&
ifUi
equalsreference_wrapper<X>
, otherwiseVi
isUi
.
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 int
isignore
, 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
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