Search code examples
c++c++11tupleslanguage-lawyerdecltype

Confusion about the return type of std::get() on std::tuple objects


Please see the following code (see it live here):

#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;
}

I'm expecting to see the output 0 0 1 1, but both GCC and clang give the output 0 1 0 1 instead. Really confused. Could someone give me an explanation?


Solution

  • Look at signature of 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 )
    

    In your case t is a l-value, so it return int&& & which became int&.