Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why structured bindings don't return references to struct members using `auto&` but the members themselves are returned

I thought that using structured bindings and auto& specifier I can obtain references to structure members and use them directly instead of going through the structure.

However, the following code works and the static asserts hold:

struct Test
{
    int i;
    char c;
    double d;
};
Test test{ 0, 1, 2 };
auto& [i, c, d] = test;
i = 4;
c = 5;
d = 6;
// i, c, d are not references !
static_assert(!std::is_same_v<decltype(i), int&>);
static_assert(!std::is_same_v<decltype(c), char&>);
static_assert(!std::is_same_v<decltype(d), double&>);
cout << &i << " == " << &test.i << " (" << std::boolalpha << (&i == &test.i) << ")" << endl; // (true)
cout << test.i << ", " << (int)test.c << ", " << test.d << endl; // 4, 5, 6

But I thought C++ doesn't allow one variable to have more than one name except if one is the real variable and others are references but in this case the variable i is the same as test.i and neither of them is a reference.

like image 623
dev65 Avatar asked Mar 02 '23 21:03

dev65


1 Answers

In the array and type case, structured bindings aren't references - they're aliases to the corresponding members. The main reason for this is to support bitfields. You can't have a reference to a bitfield, but you can have an alias to one:

struct X {
    uint8_t a : 2;
    uint8_t b : 6;
};

void f(X& x) {
    auto& [a, b] = x; // fine, a just means "x.a"
    auto& a2 = x.a;   // error
}

Separately from that, decltype() does something special on structured bindings - it will only ever give you a reference type if the member the binding refers to is a reference type, as in:

struct Y {
    int& a;
    int b;
};

void f(Y& y) {
    auto& [a, b] = y;
    // decltype(a) is int&, decltype(b) is int
}
like image 59
Barry Avatar answered Mar 05 '23 16:03

Barry