150
|
1 // RUN: %clang_cc1 -std=c++2a -x c++ %s -verify -Wno-unused-value
|
|
2
|
|
3 template<typename T, typename U>
|
|
4 constexpr bool is_same_v = false;
|
|
5
|
|
6 template<typename T>
|
|
7 constexpr bool is_same_v<T, T> = true;
|
|
8
|
|
9 // We use a hack in this file to make the compiler print out the requires
|
|
10 // expression after it has been instantiated - we put false_v<requires {...}> as
|
|
11 // the requires clause of a class template, then instantiate the template.
|
|
12 // The requirement will not be satisfied, and the explaining diagnostic will
|
|
13 // print out false_v<requires {...}> in its raw form (the false_v serves to
|
|
14 // prevent the diagnostic from elaborating on why the requires expr wasn't
|
|
15 // satisfied).
|
|
16
|
|
17 template<bool v>
|
|
18 constexpr bool false_v = false;
|
|
19
|
|
20 template<typename... Ts>
|
|
21 using void_t = void;
|
|
22
|
|
23 // Check that requires parameters are instantiated correctly.
|
|
24
|
|
25 template<typename T> requires
|
|
26 false_v<requires (T t) { requires is_same_v<decltype(t), int>; }>
|
|
27 // expected-note@-1 {{because 'false_v<requires (int t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}
|
|
28 // expected-note@-2 {{because 'false_v<requires (char t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}
|
|
29 struct r1 {};
|
|
30
|
|
31 using r1i1 = r1<int>; // expected-error {{constraints not satisfied for class template 'r1' [with T = int]}}
|
|
32 using r1i2 = r1<char>; // expected-error {{constraints not satisfied for class template 'r1' [with T = char]}}
|
|
33
|
|
34 // Check that parameter packs work.
|
|
35
|
|
36 template<typename... Ts> requires
|
|
37 false_v<requires (Ts... ts) {requires ((sizeof(ts) == 2) && ...);}>
|
|
38 // expected-note@-1 {{because 'false_v<requires (short ts, unsigned short ts) { requires (sizeof (ts) == 2) && (sizeof (ts) == 2); }>'}}
|
|
39 // expected-note@-2 {{because 'false_v<requires (short ts) { requires (sizeof (ts) == 2); }>' evaluated to false}}
|
|
40 struct r2 {};
|
|
41
|
|
42 using r2i1 = r2<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short, unsigned short>]}}
|
|
43 using r2i2 = r2<short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short>]}}
|
|
44
|
|
45 template<typename... Ts> requires
|
|
46 false_v<(requires (Ts ts) {requires sizeof(ts) != 0;} && ...)>
|
|
47 // expected-note@-1 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; } && requires (unsigned short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}
|
|
48 // expected-note@-2 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}
|
|
49 struct r3 {};
|
|
50
|
|
51 using r3i1 = r3<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short, unsigned short>]}}
|
|
52 using r3i2 = r3<short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short>]}}
|
|
53
|
|
54 template<typename T>
|
|
55 struct identity { using type = T; };
|
|
56
|
|
57 namespace type_requirement {
|
|
58 struct A {};
|
|
59
|
|
60 // check that nested name specifier is instantiated correctly.
|
|
61 template<typename T> requires false_v<requires { typename T::type; }> // expected-note{{because 'false_v<requires { typename identity<int>::type; }>' evaluated to false}}
|
|
62 struct r1 {};
|
|
63
|
|
64 using r1i = r1<identity<int>>; // expected-error{{constraints not satisfied for class template 'r1' [with T = identity<int>]}}
|
|
65
|
|
66 // check that template argument list is instantiated correctly.
|
|
67 template<typename T>
|
|
68 struct contains_template {
|
|
69 template<typename U> requires is_same_v<contains_template<T>, U>
|
|
70 using temp = int;
|
|
71 };
|
|
72
|
|
73 template<typename T> requires
|
|
74 false_v<requires { typename T::template temp<T>; }>
|
|
75 // expected-note@-1 {{because 'false_v<requires { typename contains_template<int>::temp<contains_template<int> >; }>' evaluated to false}}
|
|
76 // expected-note@-2 {{because 'false_v<requires { typename contains_template<short>::temp<contains_template<short> >; }>' evaluated to false}}
|
|
77 struct r2 {};
|
|
78
|
|
79 using r2i1 = r2<contains_template<int>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<int>]}}
|
|
80 using r2i2 = r2<contains_template<short>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<short>]}}
|
|
81
|
|
82 // substitution error occurs, then requires expr is instantiated again
|
|
83
|
|
84 template<typename T>
|
|
85 struct a {
|
|
86 template<typename U> requires (requires { typename T::a::a; }, false)
|
|
87 // expected-note@-1{{because 'requires { <<error-type>>; } , false' evaluated to false}}
|
|
88 struct r {};
|
|
89 };
|
|
90
|
|
91 using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
|
|
92
|
|
93 // Parameter pack inside expr
|
|
94 template<typename... Ts> requires
|
|
95 false_v<(requires { typename Ts::type; } && ...)>
|
|
96 // expected-note@-1 {{because 'false_v<requires { typename identity<short>::type; } && requires { typename identity<int>::type; } && requires { <<error-type>>; }>' evaluated to false}}
|
|
97 struct r5 {};
|
|
98
|
|
99 using r5i = r5<identity<short>, identity<int>, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <identity<short>, identity<int>, short>]}}
|
|
100 template<typename... Ts> requires
|
|
101 false_v<(requires { typename void_t<Ts>; } && ...)> // expected-note{{because 'false_v<requires { typename void_t<int>; } && requires { typename void_t<short>; }>' evaluated to false}}
|
|
102 struct r6 {};
|
|
103
|
|
104 using r6i = r6<int, short>; // expected-error{{constraints not satisfied for class template 'r6' [with Ts = <int, short>]}}
|
|
105
|
|
106 template<typename... Ts> requires
|
|
107 false_v<(requires { typename Ts::template aaa<Ts>; } && ...)>
|
|
108 // expected-note@-1 {{because 'false_v<requires { <<error-type>>; } && requires { <<error-type>>; }>' evaluated to false}}
|
|
109 struct r7 {};
|
|
110
|
|
111 using r7i = r7<int, A>; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = <int, type_requirement::A>]}}
|
|
112 }
|
|
113
|
|
114 namespace expr_requirement {
|
|
115 // check that compound/simple requirements are instantiated correctly.
|
|
116
|
|
117 template<typename T> requires false_v<requires { sizeof(T); { sizeof(T) }; }>
|
|
118 // expected-note@-1 {{because 'false_v<requires { sizeof(int); { sizeof(int) }; }>' evaluated to false}}
|
|
119 // expected-note@-2 {{because 'false_v<requires { <<error-expression>>; { sizeof(T) }; }>' evaluated to false}}
|
|
120 struct r1 {};
|
|
121
|
|
122 using r1i1 = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
|
|
123 using r1i2 = r1<void>; // expected-error{{constraints not satisfied for class template 'r1' [with T = void]}}
|
|
124
|
|
125 // substitution error occurs in expr, then expr is instantiated again.
|
|
126
|
|
127 template<typename T>
|
|
128 struct a {
|
|
129 template<typename U> requires (requires { sizeof(T::a); }, false) // expected-note{{because 'requires { <<error-expression>>; } , false' evaluated to false}}
|
|
130 struct r {};
|
|
131 };
|
|
132
|
|
133 using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
|
|
134
|
|
135 // check that the return-type-requirement is instantiated correctly.
|
|
136
|
|
137 template<typename T, typename U = int>
|
|
138 concept C1 = is_same_v<T, U>;
|
|
139
|
|
140 template<typename T> requires false_v<requires(T t) { { t } -> C1<T>; }>
|
|
141 // expected-note@-1 {{because 'false_v<requires (int t) { { t } -> C1<int>; }>' evaluated to false}}
|
|
142 // expected-note@-2 {{because 'false_v<requires (double t) { { t } -> C1<double>; }>' evaluated to false}}
|
|
143 struct r2 {};
|
|
144
|
|
145 using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}
|
|
146 using r2i2 = r2<double>; // expected-error{{constraints not satisfied for class template 'r2' [with T = double]}}
|
|
147
|
|
148
|
|
149 // substitution error occurs in return type requirement, then requires expr is
|
|
150 // instantiated again.
|
|
151
|
|
152 template<typename T>
|
|
153 struct b {
|
|
154 template<typename U> requires (requires { { 0 } -> C1<typename T::a>; }, false) // expected-note{{because 'requires { { 0 } -> <<error-type>>; } , false' evaluated to false}}
|
|
155 struct r {};
|
|
156 };
|
|
157
|
|
158 using bri = b<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
|
|
159
|
|
160
|
|
161 template<typename... Ts> requires
|
|
162 false_v<(requires { { 0 } noexcept -> C1<Ts>; } && ...)>
|
|
163 // expected-note@-1 {{because 'false_v<requires { { 0 } noexcept -> C1<int>; } && requires { { 0 } noexcept -> C1<unsigned int>; }>' evaluated to false}}
|
|
164 struct r3 {};
|
|
165
|
|
166 using r3i = r3<int, unsigned int>; // expected-error{{constraints not satisfied for class template 'r3' [with Ts = <int, unsigned int>]}}
|
|
167 }
|
|
168
|
|
169 namespace nested_requirement {
|
|
170 // check that constraint expression is instantiated correctly
|
|
171 template<typename T> requires false_v<requires { requires sizeof(T) == 2; }> // expected-note{{because 'false_v<requires { requires sizeof(int) == 2; }>' evaluated to false}}
|
|
172 struct r1 {};
|
|
173
|
|
174 using r1i = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
|
|
175
|
|
176 // substitution error occurs in expr, then expr is instantiated again.
|
|
177 template<typename T>
|
|
178 struct a {
|
|
179 template<typename U> requires
|
|
180 (requires { requires sizeof(T::a) == 0; }, false) // expected-note{{because 'requires { requires <<error-expression>>; } , false' evaluated to false}}
|
|
181 struct r {};
|
|
182 };
|
|
183
|
|
184 using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
|
|
185
|
|
186 // Parameter pack inside expr
|
|
187 template<typename... Ts> requires
|
|
188 false_v<(requires { requires sizeof(Ts) == 0; } && ...)>
|
|
189 // expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; } && requires { requires sizeof(short) == 0; }>' evaluated to false}}
|
|
190 struct r2 {};
|
|
191
|
|
192 using r2i = r2<int, short>; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = <int, short>]}}
|
|
193 }
|
|
194
|
|
195 // Parameter pack inside multiple requirements
|
|
196 template<typename... Ts> requires
|
|
197 false_v<(requires { requires sizeof(Ts) == 0; sizeof(Ts); } && ...)>
|
|
198 // expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; sizeof(Ts); } && requires { requires sizeof(short) == 0; sizeof(Ts); }>' evaluated to false}}
|
|
199 struct r4 {};
|
|
200
|
|
201 using r4i = r4<int, short>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int, short>]}}
|
|
202
|
|
203 template<typename... Ts> requires
|
|
204 false_v<(requires(Ts t) { requires sizeof(t) == 0; t++; } && ...)>
|
|
205 // expected-note@-1 {{because 'false_v<requires (int t) { requires sizeof (t) == 0; t++; } && requires (short t) { requires sizeof (t) == 0; t++; }>' evaluated to false}}
|
|
206 struct r5 {};
|
|
207
|
|
208 using r5i = r5<int, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <int, short>]}}
|
|
209
|
|
210 template<typename T> requires
|
|
211 false_v<(requires(T t) { T{t}; })> // T{t} creates an "UnevaluatedList" context.
|
|
212 // expected-note@-1 {{because 'false_v<(requires (int t) { int{t}; })>' evaluated to false}}
|
|
213 struct r6 {};
|
|
214
|
|
215 using r6i = r6<int>;
|
|
216 // expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}}
|