Consider a C++20 program where in function foo there is a structured binding auto [y]. The function returns y, which is converted in object of type A. A can be constructed either from const reference of from rvalue-reference.
#include <tuple>
#include <iostream>
struct A {
A(const int &) { std::cout << "A(const int &) "; }
A(int &&) { std::cout << "A(int &&) "; }
};
A foo() {
auto [y] = std::make_tuple(1);
return y;
}
int main() { foo(); }
Which one of the constructors shall be selected according to C++20 language standard?
Clang selects A(const int &) and GCC selects A(int &&), demo: https://gcc.godbolt.org/z/5q779vE6T
Does one of the compilers not support yet the standard in that respect?
I believe that Clang is correct.
TL;DR: some lvalues can be implicitly moved, but a structured binding is not such a lvalue.
[dcl.struct.bind]/1:
[dcl.struct.bind]/4:
returnstatement if it names an implicitly movable entity:[basic.pre]/3:
So I believe that a structured binding cannot be implicitly moved.
If
ywere an object or reference, then it would be implicitly movable inreturn y;.Edit: C++17 as written specified that structured bindings to tuple members are references. This was corrected by CWG 2313.