I have the following example which is fine by g++, but C/E by clang++. I wonder who is right among them?
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "DC" << std::endl;
}
MyClass(const MyClass&) {
std::cout << "CC" << std::endl;
}
MyClass(MyClass&&) {
std::cout << "MC" << std::endl;
}
~MyClass() {
std::cout << "Destruct C" << std::endl;
}
};
template<typename T>
decltype(auto) func4(T&& x) {
return x; // g++ - fine ; clang++ - ERROR
}
int main() {
MyClass mc;
func4(std::move(mc));
return 0;
}
error msg:
$ clang++-12 --std=c++14 ./ex_001_decltype_auto.cpp -o ./ex_001_decltype_auto
./ex_001_decltype_auto.cpp:42:10: error: rvalue reference to type 'MyClass' cannot bind to lvalue of type 'MyClass'
return x;
This is legal since C++23, see P2266R3. GCC 13+ and Clang 13+ both implement it (both accept your code in C++23 mode), while MSVC doesn't yet.
This paper (among other things) extends the implicit move (that happens when returning a local variable that's either not a reference or an rvalue reference) to apply regardless of the return type, while it used to only work when returning non-references.