Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type of reference binding from std::tuple [duplicate]

What is the type of a here?

#include <iostream>
#include <tuple>

using namespace std;

int main()
{
    float x{};
    std::tuple<int> tpl( x );
    auto& [ a ] = tpl;
    static_assert( std::is_same_v< decltype( a ), int> );
    //static_assert( std::is_same_v< decltype( a ), int&> );
}

According to Standard 11.5/3:

[...] Given the type Ti designated by std::tuple_element<i, E>::type, variables are introduced with unique names ri of type “reference to Ti” initialized with the initializer (11.6.3), where the reference is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise. Each vi is the name of an lvalue of type Ti that refers to the object bound to ri; the referenced type is Ti.

Here, i is 0 for the first element (int) and E is std::tuple<int>, so Ti has type std::tuple_element<0, std::tuple<int>>::type, i.e. int. Further ri (a in our case) has type "reference to Ti", i.e. lvalue reference int&, but not just int. What is wrong in that quote and why int type is deduced by both the compilers clang and gcc?

like image 930
Denis Avatar asked Jun 13 '26 22:06

Denis


2 Answers

It's true that the type of variable r0 is int&. But v0, here called a, is a different thing, the name of a structured binding, and is not technically a variable at all, just a different sort of name.

So we need to look at the description of decltype, in [dcl.type.decltype]:

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, decltype(e) is the referenced type as given in the specification of the structured binding declaration;

So here the "referenced type" is just int.

Of course, decltype((a)) is int& as we'd expect. decltype on a name without doubled parentheses is used to find out how a name is "declared", not how the name behaves, so it's not obvious that decltype(a) "should" be one thing or another, since a doesn't have a normal declaration. Though it is potentially a bit useful that given std::tuple<int, int&> t{0, n}; auto& [a, b] = t;, we have decltype(a) is int but decltype(b) is int&.

like image 192
aschepler Avatar answered Jun 16 '26 13:06

aschepler


Note

the referenced type is Ti.

For structured bindings, decltype yields the referenced type ([dcl.type.decltype]):

if e is an unparenthesized id-expression naming a structured binding, decltype(e) is the referenced type as given in the specification of the structured binding declaration;

like image 22
cpplearner Avatar answered Jun 16 '26 15:06

cpplearner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!