andreasfertig / cppinsights

C++ Insights - See your source code with the eyes of a compiler
https://cppinsights.io
MIT License
4.04k stars 238 forks source link

Structure binding variables is rvalue reference? #636

Closed contestjia closed 5 months ago

contestjia commented 5 months ago

Hello Andreas ,The result shows 'structure binding variables is rvalue reference', code snippet

#include <iostream>
#include <type_traits>

int main(){
  auto [a, b] = std::make_tuple(2, 7);
}

result:

#include <iostream>
#include <type_traits>

int main()
{
  std::tuple<int, int> __make_tuple5 = std::make_tuple(2, 7);
  int && a = std::get<0UL>(static_cast<std::tuple<int, int> &&>(__make_tuple5));
  int && b = std::get<1UL>(static_cast<std::tuple<int, int> &&>(__make_tuple5));
  return 0;
}

but gcc/clang compilers show variables a and b is not reference type:

#include <iostream>
#include <type_traits>

int main(){
  auto [a, b] = std::make_tuple(2, 7);
  std::cout << "value:" << std::is_reference_v<decltype(a)> << std::endl;
}

output: value:0

andreasfertig commented 5 months ago

Hello @contestjia,

that's tricky. First, the transformation makes the result no longer being structured binding. Second, structured bindings are special. See eel.is/c++draft/dcl.struct.bind#4:

[snip..] Ti& or Ti&&, where Ui is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise, variables are introduced with unique names ri as follows: S Ui ri = initializer ; Each vi is the name of an lvalue of type Ti that refers to the object bound to ri; the referenced type is Ti.

What C++ Insights shows you is ri. What your code tests is vi which is the object bound to ri. You can see it as you see through the name a directly to the actual member of the tuple in your example. There is no way (at least that I know of) to model that outside the compiler.

Andreas

contestjia commented 5 months ago

Ui is an lvalue reference

Okay, I got it. Thank you so much @andreasfertig