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
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 bydecltype(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 typeTi
designated bystd::tuple_element<i, E>::type
, eachvi
is a variable of type “reference toTi
” 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 isTi
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With