Consider the following code that uses structured bindings from C++17:
int a = 0, b = 0;
auto [x, y] = std::tie(a, b);
y = 1;
std::cout << a << ' ' << b << '\n';
Since I used auto
, I would expect the code to print 0 0
as y
should be a copy. However, it prints 0 1
. Why? I thought that a bare auto
never deduces a reference.
One of the first things that C++ programmers learn about auto is that bare auto never deduces a reference. In the present post, I show you two examples when it seemingly does. The first one involves proxy objects. The second one concerns structured bindings from C++17.
A structured binding declaration introduces all identifiers in the identifier-list as names in the surrounding scope and binds them to subobjects or elements of the object denoted by expression. The bindings so introduced are called structured bindings.
The auto there works just the same. for(auto val : range) will always copy, for(auto& ref : range) will always be a reference.
The auto keyword in C++ automatically detects and assigns a data type to the variable with which it is used. The compiler analyses the variable's data type by looking at its initialization. It is necessary to initialize the variable when declaring it using the auto keyword.
As cppreference notes, the portion of the declaration preceding [
(i.e. auto
in your case) does not apply to the introduced identifiers. Instead, it applies to a hidden variable that is created by the compiler under the covers. Your structured-binding declaration
auto [x, y] = std::tie(a, b);
is roughly equivalent to
auto e = std::tie(a, b);
decltype(std::get<0>(e)) x = std::get<0>(e);
decltype(std::get<1>(e)) y = std::get<1>(e);
As you can see, auto
is applied to the hidden variable e
and not to the declaration of x
and y
. The type of e
is std::tuple<int&, int&>
, and decltype(std::get<1>(e))
gives you int&
.
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