@@ -30,11 +30,18 @@ namespace std {
30
30
template <typename T> struct remove_reference <T&> { using type = T; };
31
31
template <typename T> struct remove_reference <T&&> { using type = T; };
32
32
33
+ template <typename T> struct is_lvalue_reference { static constexpr bool value = false ; };
34
+ template <typename T> struct is_lvalue_reference <T&> { static constexpr bool value = true ; };
35
+
33
36
template <typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &x) {
34
37
static_assert (T::moveable, " instantiated forward" ); // expected-error {{no member named 'moveable' in 'B'}}
35
38
// expected-error@-1 {{no member named 'moveable' in 'C'}}
36
39
return static_cast <T&&>(x);
37
40
}
41
+ template <typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &&x) {
42
+ static_assert (!is_lvalue_reference<T>::value, " should not forward rval as lval" ); // expected-error {{static_assert failed}}
43
+ return static_cast <T&&>(x);
44
+ }
38
45
39
46
template <typename T> CONSTEXPR const T &as_const (T &x) {
40
47
static_assert (T::moveable, " instantiated as_const" ); // expected-error {{no member named 'moveable' in 'B'}}
@@ -76,6 +83,11 @@ static_assert(f({}), "should be constexpr");
76
83
// expected-note@#call {{}}
77
84
#endif
78
85
86
+ A &forward_rval_as_lval () {
87
+ std::forward<A&&>(A ()); // expected-warning {{const attribute}}
88
+ return std::forward<A&>(A ()); // expected-note {{instantiation of}}
89
+ }
90
+
79
91
struct B {};
80
92
B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
81
93
B &&(*pMoveIfNoexcept)(B&) = &std::move_if_noexcept; // #2 expected-note {{instantiation of}}
0 commit comments