1 // RUN: %clang_cc1 -std=c++2a -x c++ %s -verify 2 3 static_assert(requires { { 0 }; }); 4 static_assert(requires { { "aaaa" }; }); 5 static_assert(requires { { (0).da }; }); // expected-error{{member reference base type 'int' is not a structure or union}} 6 7 void foo() {} 8 static_assert(requires { { foo() }; }); 9 10 // Substitution failure in expression 11 12 struct A {}; 13 struct B { 14 B operator+(const B &other) const { return other; } 15 }; 16 struct C { 17 C operator+(C &other) const { return other; } 18 }; 19 20 template<typename T> requires requires (T a, const T& b) { { a + b }; } // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}} expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}} 21 struct r1 {}; 22 23 using r1i1 = r1<int>; 24 using r1i2 = r1<A>; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}} 25 using r1i3 = r1<B>; 26 using r1i4 = r1<C>; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}} 27 28 struct D { void foo() {} }; 29 30 template<typename T> requires requires (T a) { { a.foo() }; } // expected-note{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}} expected-note{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}} expected-note{{because 'a.foo()' would be invalid: 'this' argument to member function 'foo' has type 'const D', but function is not marked const}} 31 struct r2 {}; 32 33 using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} 34 using r2i2 = r2<A>; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}} 35 using r2i3 = r2<D>; 36 using r2i4 = r2<const D>; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}} 37 38 template<typename T> requires requires { { sizeof(T) }; } // expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}} 39 struct r3 {}; 40 41 using r3i1 = r3<int>; 42 using r3i2 = r3<A>; 43 using r3i3 = r3<A &>; 44 using r3i4 = r3<void>; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}} 45 using r3i4 = r3<class nonexistent>; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}} 46 47 // Non-dependent expressions 48 49 template<typename T> requires requires (T t) { { 0 }; { "a" }; { (void)'a' }; } 50 struct r4 {}; 51 52 using r4i1 = r4<int>; 53 using r4i2 = r4<int[10]>; 54 using r4i3 = r4<int(int)>; 55 56 // Noexcept requirement 57 void maythrow() { } 58 static_assert(!requires { { maythrow() } noexcept; }); 59 static_assert(requires { { 1 } noexcept; }); 60 61 struct E { void operator++(int) noexcept; }; 62 struct F { void operator++(int); }; 63 64 template<typename T> requires requires (T t) { { t++ } noexcept; } // expected-note{{because 't ++' may throw an exception}} 65 struct r5 {}; 66 67 using r5i1 = r5<int>; 68 using r5i2 = r5<E>; 69 using r5i2 = r5<F>; // expected-error{{constraints not satisfied for class template 'r5' [with T = F]}} 70 71 template<typename T> requires requires (T t) { { t.foo() } noexcept; } // expected-note{{because 't.foo()' would be invalid: no member named 'foo' in 'E'}} 72 struct r6 {}; 73 74 using r6i = r6<E>; // expected-error{{constraints not satisfied for class template 'r6' [with T = E]}} 75 76 template<typename T, typename U> 77 constexpr bool is_same_v = false; 78 79 template<typename T> 80 constexpr bool is_same_v<T, T> = true; 81 82 template<typename T> struct remove_reference { using type = T; }; 83 template<typename T> struct remove_reference<T&> { using type = T; }; 84 85 template<typename T, typename U> 86 concept Same = is_same_v<T, U>; 87 88 template<typename T> 89 concept Large = sizeof(typename remove_reference<T>::type) >= 4; 90 // expected-note@-1{{because 'sizeof(typename remove_reference<short &>::type) >= 4' (2 >= 4) evaluated to false}} 91 92 template<typename T> requires requires (T t) { { t } -> Large; } // expected-note{{because 'short &' does not satisfy 'Large':}} 93 struct r7 {}; 94 95 using r7i1 = r7<int>; 96 using r7i2 = r7<short>; // expected-error{{constraints not satisfied for class template 'r7' [with T = short]}} 97 98 template<typename T> requires requires (T t) { { t } -> Same<T&>; } 99 struct r8 {}; 100 101 using r8i1 = r8<int>; 102 using r8i2 = r8<short*>; 103 104 // Substitution failure in type constraint 105 106 template<typename T> requires requires (T t) { { t } -> Same<typename T::type&>; } 107 // expected-note@-1{{because 'Same<expr-type, typename T::type &>' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} 108 struct r9 {}; 109 110 struct M { using type = M; }; 111 112 using r9i1 = r9<M>; 113 using r9i2 = r9<int>; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}} 114 115 // Substitution failure in both expression and return type requirement 116 117 template<typename T> requires requires (T t) { { t.foo() } -> Same<typename T::type>; } // expected-note{{because 't.foo()' would be invalid: member reference base type 'int' is not a structure or union}} 118 struct r10 {}; 119 120 using r10i = r10<int>; // expected-error{{constraints not satisfied for class template 'r10' [with T = int]}} 121 122 // Non-type concept in type constraint 123 124 template<int T> 125 concept IsEven = (T % 2) == 0; 126 127 template<typename T> requires requires (T t) { { t } -> IsEven; } // expected-error{{concept named in type constraint is not a type concept}} 128 struct r11 {}; 129 130 // Value categories 131 132 template<auto a = 0> 133 requires requires (int b) { 134 { a } -> Same<int>; 135 { b } -> Same<int&>; 136 { 0 } -> Same<int>; 137 { static_cast<int&&>(a) } -> Same<int&&>; 138 } void f1() {} 139 template void f1<>(); 140 141 // C++ [expr.prim.req.compound] Example 142 namespace std_example { 143 template<typename T> concept C1 = 144 requires(T x) { 145 {x++}; 146 }; 147 148 template<typename T, typename U> constexpr bool is_same_v = false; 149 template<typename T> constexpr bool is_same_v<T, T> = true; 150 151 template<typename T, typename U> concept same_as = is_same_v<T, U>; 152 // expected-note@-1 {{because 'is_same_v<int, int *>' evaluated to false}} 153 154 static_assert(C1<int>); 155 static_assert(C1<int*>); 156 template<C1 T> struct C1_check {}; 157 using c1c1 = C1_check<int>; 158 using c1c2 = C1_check<int[10]>; 159 160 template<typename T> concept C2 = 161 requires(T x) { 162 {*x} -> same_as<typename T::inner>; 163 // expected-note@-1{{because type constraint 'same_as<int, typename T2::inner>' was not satisfied:}} 164 // expected-note@-2{{because '*x' would be invalid: indirection requires pointer operand ('int' invalid)}} 165 }; 166 167 struct T1 { 168 using inner = int; 169 inner operator *() { return 0; } 170 }; 171 struct T2 { 172 using inner = int *; 173 int operator *() { return 0; } 174 }; 175 static_assert(C2<T1>); 176 template<C2 T> struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'std_example::T2' does not satisfy 'C2'}} 177 using c2c1 = C2_check<int>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = int]}} 178 using c2c2 = C2_check<T2>; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::T2]}} 179 180 template<typename T> 181 void g(T t) noexcept(sizeof(T) == 1) {} 182 183 template<typename T> concept C5 = 184 requires(T x) { 185 {g(x)} noexcept; // expected-note{{because 'g(x)' may throw an exception}} 186 }; 187 188 static_assert(C5<char>); 189 template<C5 T> struct C5_check {}; // expected-note{{because 'short' does not satisfy 'C5'}} 190 using c5 = C5_check<short>; // expected-error{{constraints not satisfied for class template 'C5_check' [with T = short]}} 191 } 192