Search code examples
c++g++clang++

g++ ok but clang no: return rvalue to lvalue


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;

Solution

  • 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.