2016-04-25 14 views
17

Czy istnieje różnica znaczeniowa między piśmie ekspresjęJaka jest różnica między std :: tie a std :: make_tuple z argumentami std :: ref?

std::tie(x, y, z) 

oraz następujące wyrażenie?

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

Jeśli tak, jakie są różnice?

Nawiasem mówiąc, to pytanie nie pyta o to samo, co What is the difference between assigning to std::tie and tuple of references?, ponieważ krotka odnośników nie jest tworzona przez std::ref, ale poprzez jawne określenie typu.

Odpowiedz

15

Istnieje prawie i sztylet; brak różnicy funkcjonalnej między tymi dwoma wyrażeniami. tie() jest tylko krótszy, natomiast make_tuple() jest bardziej ogólny.


Według [tuple.creation] make_tuple robi:

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

Niech Ui być decay_t<Ti> dla każdego Ti typów. Następnie każdy z nich jest , który jest równy reference_wrapper<X>, w innym przypadku .

Stąd std::make_tuple(std::ref(x), std::ref(y), std::ref(z)) plony & sztylet; a std::tuple<X&, Y&, Z&>.

Z drugiej strony, tie robi:

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

Powroty:tuple<Types&...>(t...). Gdy argument w t jest ignore, przypisanie dowolnej wartości do odpowiedniego elementu krotki nie ma wpływu.

W związku z tym std::tie(x, y, z) również daje std::tuple<X&, Y&, Z&>.


& sztylet; Z wyjątkiem jednego edge case.

14

Jest różnica, gdy którykolwiek z x, y i z jest specjalizacja 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&> 
}