Mohammad Rahimi
Mohammad Rahimi

Reputation: 1123

`ref-qualified` `identifier-list` is not a reference in C++ Structured binding but act as one

In C++ Structured binding if we use & as the ref-qualifier like bellow:

tuple tpl{ 1 };
auto& [myInt] = tpl;

when we assign to myInt, changes are reflected to tpl:

myInt = -1;
cout << get<0>(tpl) << "    " << endl; // -1

Here myInt ac as a reference. But when we query the type of myInt we get int, not int&!

cout << type_name<decltype(myInt)>() << endl;

How is that possible?!

This article goes deeper into the Structured binding and states:

In a cruel twist of fate, if hidden is const or a const reference, then that const-ness propagates to the destinations. But the reference-ness of hidden does not propagate.

How reference-ness does not propagate but still act as one?

Here is the complete code and the result compiled with MS Visual Studio 2022 with the latest C++ standard.

#include <iostream>
#include <tuple>

template <typename T>
constexpr auto type_name() {
    std::string_view name, prefix, suffix;
#ifdef __clang__
    name = __PRETTY_FUNCTION__;
    prefix = "auto type_name() [T = ";
    suffix = "]";
#elif defined(__GNUC__)
    name = __PRETTY_FUNCTION__;
    prefix = "constexpr auto type_name() [with T = ";
    suffix = "]";
#elif defined(_MSC_VER)
    name = __FUNCSIG__;
    prefix = "auto __cdecl type_name<";
    suffix = ">(void)";
#endif
    name.remove_prefix(prefix.size());
    name.remove_suffix(suffix.size());
    return name;
}

using namespace std;

int main() {
    tuple tpl{ 1 };

    decltype(auto) myIntRef{ get<0>(tpl) };
    cout << type_name<decltype(myIntRef)>() << endl;
    
    auto& [myInt] = tpl;
    myInt = -1;
    cout << type_name<decltype(myInt)>() << endl;
    cout << get<0>(tpl) << "    " << endl;
}

and the result:

int&
int
-1

Upvotes: 2

Views: 64

Answers (0)

Related Questions