Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::tuple decompose into rvalue references

Tags:

c++

c++17

Why does std::tuple decompose into rvalue references?

#include <tuple>

template <typename, typename> struct same_type;
template <typename T> struct same_type<T, T> {};

void foo() {
  std::tuple tuple(1, 'a', 2.3, true);
  auto[i, c, d, b] = tuple;
  same_type<decltype(i), int &&>{};
  same_type<decltype(c), char &&>{};
  same_type<decltype(d), double &&>{};
  same_type<decltype(b), bool &&>{};
}

This compiles without error using gcc trunk. I would have expected the plain types instead, e.g.

same_type<decltype(i), int>{};

Live example

like image 391
octoploid Avatar asked Nov 15 '16 08:11

octoploid


1 Answers

GCC bug. decltype applied to a structured binding returns the referenced type, which for the tuple-like case is the exact type returned by std::tuple_element. In other words, the language tries pretty hard here to hide the fact that those are actually references.

[dcl.type.simple]/4:

For an expression e, the type denoted by decltype(e) is defined as follows:

  • if e is an unparenthesized id-expression naming a structured binding ([dcl.struct.bind]), decltype(e) is the referenced type as given in the specification of the structured binding declaration;
  • [...]

[dcl.struct.bind]/3:

Otherwise, if the expression std::tuple_size<E>::value is a well-formed integral constant expression [...] Given the type Ti designated by std::tuple_element<i, E>::type, each vi is a variable of type “reference to Ti” initialized with the initializer, where the reference is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise; the referenced type is Ti.

like image 123
T.C. Avatar answered Nov 18 '22 17:11

T.C.