2016-03-31 1 views
2

S'il vous plaît voir le code suivant (voir vivre here):Confusion sur le type de retour de std :: get() sur les objets std :: tuple

#include <iostream> 
#include <tuple> 
#include <type_traits> 
#include <utility> 

struct S { 
    int&& v; 
}; 

int main() { 
    std::tuple<int&&> t(1); 
    std::cout << std::is_same<int, decltype(std::get<0>(t))>{} << std::endl; 
    std::cout << std::is_same<int&, decltype(std::get<0>(t))>{} << std::endl; 
    std::cout << std::is_same<int&&, decltype(std::get<0>(t))>{} << std::endl; 
    S s{1}; 
    std::cout << std::is_same<int&&, decltype(s.v)>{} << std::endl; 
} 

Je me attends de voir la sortie 0 0 1 1, mais à la fois GCC et clang donnent la sortie 0 1 0 1 à la place. Vraiment confus. Quelqu'un pourrait-il me donner une explication?

Répondre

3

Regardez la signature de std::get:

template< std::size_t I, class... Types > 
constexpr std::tuple_element_t<I, tuple<Types...> >& 
    get(tuple<Types...>& t) 

template< std::size_t I, class... Types > 
constexpr std::tuple_element_t<I, tuple<Types...> >&& 
    get(tuple<Types...>&& t) 

Dans votre cas t est une l-value, il retourne int&& & qui est devenu int&.

+0

Toutes les idées pour lesquelles 'std :: tuple_element <0, std :: tuple > :: type &' renvoie un 'int &' Comment does 'int &' + '&' s'effondre dans int &? – James

+0

@Phantom: Regardez [concise-explication-of-reference-collapsing-rules] (http://stackoverflow.com/questions/13725747/concise-explanation-of-reference-collapsing-rules-requested-1-aa- 2) – Jarod42

+0

Merci. C'est exactement ce que je cherchais. – James

1

Les std::get pertinentes sont ces surcharges:

template< std::size_t I, class... Types > 
typename std::tuple_element<I, tuple<Types...> >::type& 
get(tuple<Types...>& t); 

template< std::size_t I, class... Types > 
typename std::tuple_element<I, tuple<Types...> >::type&& 
get(tuple<Types...>&& t); 

Notez qu'une référence lvalue est renvoyée si l'argument est une lvalue, et une référence rvalue est renvoyée si l'argument est un rvalue. t est une lvalue, donc une lvalue est retournée.