blob: f44fd2a061cb82648d54498e6b6c3e5c59edda91 [file] [log] [blame]
// 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);