// PR c++/101165 - P2266R1 - Simpler implicit move // { dg-do compile { target c++23 } } // Tests from P2266R1. namespace std { template<typename _Tp> struct remove_reference { typedef _Tp type; }; template<typename _Tp> struct remove_reference<_Tp&> { typedef _Tp type; }; template<typename _Tp> struct remove_reference<_Tp&&> { typedef _Tp type; }; template<typename _Tp> constexpr typename std::remove_reference<_Tp>::type&& move(_Tp&& __t) noexcept { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } } template<typename T, typename U> struct same_type { static const bool value = false; }; template<typename T> struct same_type<T, T> { static const bool value = true; }; struct Widget { Widget(Widget&&); }; struct RRefTaker { RRefTaker(Widget&&); }; struct Mutt { operator int*() &&; }; struct Jeff { operator int&() &&; }; struct Ella { operator int() &&; }; Widget one(Widget w) { return w; // OK since C++11 } RRefTaker two(Widget w) { return w; // OK since C++11 + CWG1579 } RRefTaker three(Widget&& w) { return w; // OK since C++20 because P0527 } // Tests that implicit move applies even to functions that return references. Widget&& four(Widget&& w) { return w; // OK since C++23 } // ... or pointers. int* five(Mutt x) { return x; // OK since C++20 because P1155 } int& six(Jeff x) { return x; } int test_ella(Ella e) { return e; } template<class T> T&& seven(T&& x) { return x; } void test_seven(Widget w) { Widget& r = seven(w); Widget&& rr = seven(std::move(w)); } Widget val(); Widget& lref(); Widget&& rref(); decltype(auto) eight() { decltype(auto) x = val(); // OK, x is Widget return x; // OK, return type is Widget, we get copy elision } decltype(auto) nine() { decltype(auto) x = lref(); // OK, x is Widget& return x; // OK, return type is Widget& } decltype(auto) ten() { decltype(auto) x = rref(); // OK, x is Widget&& // This was an error: return type is Widget&&, cannot bind to x. // But in C++23, x is treated as an rvalue. return x; } // Now returns Widget&&, not Widget&. // This is from $ 3.2.1. Interaction with decltype and decltype(auto). decltype(auto) eleven(Widget&& x) { return (x); } static_assert(same_type<decltype(eleven), Widget&& (Widget&&)>::value);