Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the types of identifiers introduced by structured bindings in C++17?

To my knowledge, identifiers introduced by structured bindings in C++17 are in fact references to some "hidden" variable. Such that

auto [ a, b ] = std::make_tuple(1, 2);

is kind-of equivalent to

auto e = std::make_tuple(1, 2);
auto& a = std::get<0>(e);
auto& b = std::get<1>(e);

However, if I print out std::is_reference<decltype(a)>::value, I get 0 in the first case 1 in the second. Why is that?

like image 748
Daniel Langr Avatar asked Jun 21 '17 09:06

Daniel Langr


2 Answers

To my knowledge, identifiers introduced by structured bindings in C++17 are in fact references to some "hidden" variable.

If by "reference" you mean the language construct reference, this isn't quite correct. The specifiers in the declaration appertain to the "hidden variable" you speak of. The reference qualifier is optional. The code you presented would be more like this:

const auto& e = std::make_tuple(1, 2);
using E = remove_reference_t<decltype((e))>;
std::tuple_element<0, E>::type& a = get<0>(e);
std::tuple_element<1, E>::type& b = get<1>(e);
like image 191
user8193326 Avatar answered Sep 18 '22 14:09

user8193326


if I print out std::is_reference<decltype(a)>::value, I get 0 in the first case 1 in the second.

Why is that even if we can prove that a and b refer to the elements in the tuple and one can modify those values by means of them?
I'm not a language lawyer, but probably it is due to this bullet of the standard (working draft):

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


Side note. You should use this form to do so that a and b refer to the elements in the tuple:

auto tup = std::make_tuple(1, 2);
auto & [ a, b ] = tup;

It follows a minimal, working example:

#include <tuple>
#include <type_traits>
#include <iostream>

int main() {
    auto tup = std::make_tuple(1, 2);
    auto & [ a, b ] = tup;
    a = 0;
    std::cout << a << ", " << std::get<0>(tup) << std::endl;
}

See it on Coliru. On the other side, what you get is a copy of the values using the expression below:

auto [ a, b ] = std::make_tuple(1, 2);

Here is an article that explains it better and is a bit more comprehensible than the standard for humans.

like image 23
skypjack Avatar answered Sep 19 '22 14:09

skypjack