-
-
Notifications
You must be signed in to change notification settings - Fork 262
Description
Having a simple code like:
#include <tuple>
int main()
{
std::tuple<int, int> tup{2,5};
auto [a, b] = tup;
}results in following output from cppinsights:
#include <tuple>
int main()
{
std::tuple<int, int> tup = std::tuple<int, int>{2, 5};
std::tuple<int, int> __tup6 = std::tuple<int, int>(tup);
std::tuple_element<0, std::tuple<int, int> >::type & a = std::get<0UL>(__tup6);
std::tuple_element<0, std::tuple<int> >::type & b = std::get<1UL>(__tup6);
}
Even though it looks fine, it's not accurate, because, when __tup6 is not of lvalue reference type, which is the case here, then
xvalue is passed to the get function. You can have a look at a wording here:
https://eel.is/c++draft/dcl.struct.bind#4.sentence-7
In either case, e is an lvalue if the type of the entity e is an lvalue reference and an xvalue otherwise.
here e is our __tup6.
Also std::get has its implementations for lvalue references, rvalue references and const lvalue references, which is why it works correctly.
So the code produced should be in fact:
#include <tuple>
int main()
{
std::tuple<int, int> tup = std::tuple<int, int>{2, 5};
std::tuple<int, int> __tup6 = std::tuple<int, int>(tup);
std::tuple_element<0, std::tuple<int, int> >::type & a = std::get<0UL>(std::move(__tup6));
std::tuple_element<0, std::tuple<int> >::type & b = std::get<1UL>(std::move(__tup6));
}when structured binding is done as auto [...] and stay as it is right now when it's of the form auto& [...].
Also you can have a look at at the code that will not compile, because of the above:
#include <tuple>
struct myStruct{
int a = 1;
int b = 2;
};
template<std::size_t idx>
auto& get(myStruct& str){
if constexpr (idx == 0) return str.a;
else return str.b;
}
namespace std{
template <>
struct tuple_size<myStruct>{
static constexpr std::size_t value = 2;
};
template<>
struct tuple_element<0, myStruct>{
using type = int&;
};
template<>
struct tuple_element<1, myStruct>{
using type = int&;
};
}
int main()
{
myStruct var;
auto [a, b] = var;
}it fails with error:
candidate function template not viable: expects an l-value for 1st argument.