1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
10 | |
11 | // template<class T, class U> |
12 | // concept invocable; |
13 | |
14 | #include <chrono> |
15 | #include <concepts> |
16 | #include <functional> |
17 | #include <memory> |
18 | #include <random> |
19 | #include <type_traits> |
20 | |
21 | template <class R, class... Args> |
22 | constexpr bool check_invocable() { |
23 | constexpr bool result = std::invocable<R(Args...), Args...>; |
24 | static_assert(std::invocable<R(Args...) noexcept, Args...> == result); |
25 | static_assert(std::invocable<R (*)(Args...), Args...> == result); |
26 | static_assert(std::invocable<R (*)(Args...) noexcept, Args...> == result); |
27 | static_assert(std::invocable<R (&)(Args...), Args...> == result); |
28 | static_assert(std::invocable<R (&)(Args...) noexcept, Args...> == result); |
29 | |
30 | return result; |
31 | } |
32 | |
33 | static_assert(check_invocable<void>()); |
34 | static_assert(check_invocable<void, int>()); |
35 | static_assert(check_invocable<void, int&>()); |
36 | static_assert(check_invocable<void, int*, double>()); |
37 | static_assert(check_invocable<int>()); |
38 | static_assert(check_invocable<int, int[]>()); |
39 | |
40 | struct S; |
41 | static_assert(check_invocable<int, int S::*, std::nullptr_t>()); |
42 | static_assert(check_invocable<int, int (S::*)(), int (S::*)(int), int>()); |
43 | static_assert(std::invocable<void (*)(int const&), int&>); |
44 | static_assert(std::invocable<void (*)(int const&), int&&>); |
45 | static_assert(std::invocable<void (*)(int volatile&), int&>); |
46 | static_assert(std::invocable<void (*)(int const volatile&), int&>); |
47 | |
48 | static_assert(!std::invocable<void(), int>); |
49 | static_assert(!std::invocable<void(int)>); |
50 | static_assert(!std::invocable<void(int*), double*>); |
51 | static_assert(!std::invocable<void (*)(int&), double*>); |
52 | static_assert(std::invocable<int S::*, std::unique_ptr<S> >); |
53 | static_assert(std::invocable<int S::*, std::shared_ptr<S> >); |
54 | static_assert(!std::invocable<void (*)(int&&), int&>); |
55 | static_assert(!std::invocable<void (*)(int&&), int const&>); |
56 | |
57 | static_assert(!std::invocable<void>); |
58 | static_assert(!std::invocable<void*>); |
59 | static_assert(!std::invocable<int>); |
60 | static_assert(!std::invocable<int&>); |
61 | static_assert(!std::invocable<int&&>); |
62 | |
63 | namespace function_objects { |
64 | struct function_object { |
65 | void operator()(); |
66 | }; |
67 | static_assert(std::invocable<function_object>); |
68 | static_assert(!std::invocable<function_object const>); |
69 | static_assert(!std::invocable<function_object volatile>); |
70 | static_assert(!std::invocable<function_object const volatile>); |
71 | static_assert(std::invocable<function_object&>); |
72 | static_assert(!std::invocable<function_object const&>); |
73 | static_assert(!std::invocable<function_object volatile&>); |
74 | static_assert(!std::invocable<function_object const volatile&>); |
75 | |
76 | struct const_function_object { |
77 | void operator()(int) const; |
78 | }; |
79 | static_assert(std::invocable<const_function_object, int>); |
80 | static_assert(std::invocable<const_function_object const, int>); |
81 | static_assert(!std::invocable<const_function_object volatile, int>); |
82 | static_assert(!std::invocable<const_function_object const volatile, int>); |
83 | static_assert(std::invocable<const_function_object&, int>); |
84 | static_assert(std::invocable<const_function_object const&, int>); |
85 | static_assert(!std::invocable<const_function_object volatile&, int>); |
86 | static_assert(!std::invocable<const_function_object const volatile&, int>); |
87 | |
88 | struct volatile_function_object { |
89 | void operator()(int, int) volatile; |
90 | }; |
91 | static_assert(std::invocable<volatile_function_object, int, int>); |
92 | static_assert(!std::invocable<volatile_function_object const, int, int>); |
93 | static_assert(std::invocable<volatile_function_object volatile, int, int>); |
94 | static_assert( |
95 | !std::invocable<volatile_function_object const volatile, int, int>); |
96 | static_assert(std::invocable<volatile_function_object&, int, int>); |
97 | static_assert(!std::invocable<volatile_function_object const&, int, int>); |
98 | static_assert(std::invocable<volatile_function_object volatile&, int, int>); |
99 | static_assert( |
100 | !std::invocable<volatile_function_object const volatile&, int, int>); |
101 | |
102 | struct cv_function_object { |
103 | void operator()(int[]) const volatile; |
104 | }; |
105 | static_assert(std::invocable<cv_function_object, int*>); |
106 | static_assert(std::invocable<cv_function_object const, int*>); |
107 | static_assert(std::invocable<cv_function_object volatile, int*>); |
108 | static_assert(std::invocable<cv_function_object const volatile, int*>); |
109 | static_assert(std::invocable<cv_function_object&, int*>); |
110 | static_assert(std::invocable<cv_function_object const&, int*>); |
111 | static_assert(std::invocable<cv_function_object volatile&, int*>); |
112 | static_assert(std::invocable<cv_function_object const volatile&, int*>); |
113 | |
114 | struct lvalue_function_object { |
115 | void operator()() &; |
116 | }; |
117 | static_assert(!std::invocable<lvalue_function_object>); |
118 | static_assert(!std::invocable<lvalue_function_object const>); |
119 | static_assert(!std::invocable<lvalue_function_object volatile>); |
120 | static_assert(!std::invocable<lvalue_function_object const volatile>); |
121 | static_assert(std::invocable<lvalue_function_object&>); |
122 | static_assert(!std::invocable<lvalue_function_object const&>); |
123 | static_assert(!std::invocable<lvalue_function_object volatile&>); |
124 | static_assert(!std::invocable<lvalue_function_object const volatile&>); |
125 | |
126 | struct lvalue_const_function_object { |
127 | void operator()(int) const&; |
128 | }; |
129 | static_assert(std::invocable<lvalue_const_function_object, int>); |
130 | static_assert(std::invocable<lvalue_const_function_object const, int>); |
131 | static_assert(!std::invocable<lvalue_const_function_object volatile, int>); |
132 | static_assert( |
133 | !std::invocable<lvalue_const_function_object const volatile, int>); |
134 | static_assert(std::invocable<lvalue_const_function_object&, int>); |
135 | static_assert(std::invocable<lvalue_const_function_object const&, int>); |
136 | static_assert(!std::invocable<lvalue_const_function_object volatile&, int>); |
137 | static_assert( |
138 | !std::invocable<lvalue_const_function_object const volatile&, int>); |
139 | |
140 | struct lvalue_volatile_function_object { |
141 | void operator()(int, int) volatile&; |
142 | }; |
143 | static_assert(!std::invocable<lvalue_volatile_function_object, int, int>); |
144 | static_assert(!std::invocable<lvalue_volatile_function_object const, int, int>); |
145 | static_assert( |
146 | !std::invocable<lvalue_volatile_function_object volatile, int, int>); |
147 | static_assert( |
148 | !std::invocable<lvalue_volatile_function_object const volatile, int, int>); |
149 | static_assert(std::invocable<lvalue_volatile_function_object&, int, int>); |
150 | static_assert( |
151 | !std::invocable<lvalue_volatile_function_object const&, int, int>); |
152 | static_assert( |
153 | std::invocable<lvalue_volatile_function_object volatile&, int, int>); |
154 | static_assert( |
155 | !std::invocable<lvalue_volatile_function_object const volatile&, int, int>); |
156 | |
157 | struct lvalue_cv_function_object { |
158 | void operator()(int[]) const volatile&; |
159 | }; |
160 | static_assert(!std::invocable<lvalue_cv_function_object, int*>); |
161 | static_assert(!std::invocable<lvalue_cv_function_object const, int*>); |
162 | static_assert(!std::invocable<lvalue_cv_function_object volatile, int*>); |
163 | static_assert(!std::invocable<lvalue_cv_function_object const volatile, int*>); |
164 | static_assert(std::invocable<lvalue_cv_function_object&, int*>); |
165 | static_assert(std::invocable<lvalue_cv_function_object const&, int*>); |
166 | static_assert(std::invocable<lvalue_cv_function_object volatile&, int*>); |
167 | static_assert(std::invocable<lvalue_cv_function_object const volatile&, int*>); |
168 | // |
169 | struct rvalue_function_object { |
170 | void operator()() &&; |
171 | }; |
172 | static_assert(std::invocable<rvalue_function_object>); |
173 | static_assert(!std::invocable<rvalue_function_object const>); |
174 | static_assert(!std::invocable<rvalue_function_object volatile>); |
175 | static_assert(!std::invocable<rvalue_function_object const volatile>); |
176 | static_assert(!std::invocable<rvalue_function_object&>); |
177 | static_assert(!std::invocable<rvalue_function_object const&>); |
178 | static_assert(!std::invocable<rvalue_function_object volatile&>); |
179 | static_assert(!std::invocable<rvalue_function_object const volatile&>); |
180 | |
181 | struct rvalue_const_function_object { |
182 | void operator()(int) const&&; |
183 | }; |
184 | static_assert(std::invocable<rvalue_const_function_object, int>); |
185 | static_assert(std::invocable<rvalue_const_function_object const, int>); |
186 | static_assert(!std::invocable<rvalue_const_function_object volatile, int>); |
187 | static_assert( |
188 | !std::invocable<rvalue_const_function_object const volatile, int>); |
189 | static_assert(!std::invocable<rvalue_const_function_object&, int>); |
190 | static_assert(!std::invocable<rvalue_const_function_object const&, int>); |
191 | static_assert(!std::invocable<rvalue_const_function_object volatile&, int>); |
192 | static_assert( |
193 | !std::invocable<rvalue_const_function_object const volatile&, int>); |
194 | |
195 | struct rvalue_volatile_function_object { |
196 | void operator()(int, int) volatile&&; |
197 | }; |
198 | static_assert(std::invocable<rvalue_volatile_function_object, int, int>); |
199 | static_assert(!std::invocable<rvalue_volatile_function_object const, int, int>); |
200 | static_assert( |
201 | std::invocable<rvalue_volatile_function_object volatile, int, int>); |
202 | static_assert( |
203 | !std::invocable<rvalue_volatile_function_object const volatile, int, int>); |
204 | static_assert(!std::invocable<rvalue_volatile_function_object&, int, int>); |
205 | static_assert( |
206 | !std::invocable<rvalue_volatile_function_object const&, int, int>); |
207 | static_assert( |
208 | !std::invocable<rvalue_volatile_function_object volatile&, int, int>); |
209 | static_assert( |
210 | !std::invocable<rvalue_volatile_function_object const volatile&, int, int>); |
211 | |
212 | struct rvalue_cv_function_object { |
213 | void operator()(int[]) const volatile&&; |
214 | }; |
215 | static_assert(std::invocable<rvalue_cv_function_object, int*>); |
216 | static_assert(std::invocable<rvalue_cv_function_object const, int*>); |
217 | static_assert(std::invocable<rvalue_cv_function_object volatile, int*>); |
218 | static_assert(std::invocable<rvalue_cv_function_object const volatile, int*>); |
219 | static_assert(!std::invocable<rvalue_cv_function_object&, int*>); |
220 | static_assert(!std::invocable<rvalue_cv_function_object const&, int*>); |
221 | static_assert(!std::invocable<rvalue_cv_function_object volatile&, int*>); |
222 | static_assert(!std::invocable<rvalue_cv_function_object const volatile&, int*>); |
223 | |
224 | struct multiple_overloads { |
225 | struct A {}; |
226 | struct B { B(int); }; |
227 | struct AB : A, B {}; |
228 | struct O {}; |
229 | void operator()(A) const; |
230 | void operator()(B) const; |
231 | }; |
232 | static_assert(std::invocable<multiple_overloads, multiple_overloads::A>); |
233 | static_assert(std::invocable<multiple_overloads, multiple_overloads::B>); |
234 | static_assert(std::invocable<multiple_overloads, int>); |
235 | static_assert(!std::invocable<multiple_overloads, multiple_overloads::AB>); |
236 | static_assert(!std::invocable<multiple_overloads, multiple_overloads::O>); |
237 | } // namespace function_objects |
238 | |
239 | namespace pointer_to_member_functions { |
240 | template<class Member, class T, class... Args> |
241 | constexpr bool check_member_is_invocable() |
242 | { |
243 | constexpr bool result = std::invocable<Member, T&&, Args...>; |
244 | using uncv_t = std::remove_cvref_t<T>; |
245 | static_assert(std::invocable<Member, uncv_t*, Args...> == result); |
246 | static_assert(std::invocable<Member, std::unique_ptr<uncv_t>, Args...> == result); |
247 | static_assert(std::invocable<Member, std::reference_wrapper<uncv_t>, Args...> == result); |
248 | static_assert(!std::invocable<Member, std::nullptr_t, Args...>); |
249 | static_assert(!std::invocable<Member, int, Args...>); |
250 | static_assert(!std::invocable<Member, int*, Args...>); |
251 | static_assert(!std::invocable<Member, double*, Args...>); |
252 | struct S2 {}; |
253 | static_assert(!std::invocable<Member, S2*, Args...>); |
254 | return result; |
255 | } |
256 | |
257 | static_assert(check_member_is_invocable<int S::*, S>()); |
258 | static_assert(std::invocable<int S::*, S&>); |
259 | static_assert(std::invocable<int S::*, S const&>); |
260 | static_assert(std::invocable<int S::*, S volatile&>); |
261 | static_assert(std::invocable<int S::*, S const volatile&>); |
262 | static_assert(std::invocable<int S::*, S&&>); |
263 | static_assert(std::invocable<int S::*, S const&&>); |
264 | static_assert(std::invocable<int S::*, S volatile&&>); |
265 | static_assert(std::invocable<int S::*, S const volatile&&>); |
266 | |
267 | static_assert(check_member_is_invocable<int (S::*)(int), S, int>()); |
268 | static_assert(!check_member_is_invocable<int (S::*)(int), S>()); |
269 | using unqualified = void (S::*)(); |
270 | static_assert(std::invocable<unqualified, S&>); |
271 | static_assert(!std::invocable<unqualified, S const&>); |
272 | static_assert(!std::invocable<unqualified, S volatile&>); |
273 | static_assert(!std::invocable<unqualified, S const volatile&>); |
274 | static_assert(std::invocable<unqualified, S&&>); |
275 | static_assert(!std::invocable<unqualified, S const&&>); |
276 | static_assert(!std::invocable<unqualified, S volatile&&>); |
277 | static_assert(!std::invocable<unqualified, S const volatile&&>); |
278 | |
279 | static_assert(check_member_is_invocable<int (S::*)(double) const, S, double>()); |
280 | using const_qualified = void (S::*)() const; |
281 | static_assert(std::invocable<const_qualified, S&>); |
282 | static_assert(std::invocable<const_qualified, S const&>); |
283 | static_assert(!std::invocable<const_qualified, S volatile&>); |
284 | static_assert(!std::invocable<const_qualified, S const volatile&>); |
285 | static_assert(std::invocable<const_qualified, S&&>); |
286 | static_assert(std::invocable<const_qualified, S const&&>); |
287 | static_assert(!std::invocable<const_qualified, S volatile&&>); |
288 | static_assert(!std::invocable<const_qualified, S const volatile&&>); |
289 | |
290 | static_assert( |
291 | check_member_is_invocable<int (S::*)(double[]) volatile, S, double*>()); |
292 | using volatile_qualified = void (S::*)() volatile; |
293 | static_assert(std::invocable<volatile_qualified, S&>); |
294 | static_assert(!std::invocable<volatile_qualified, S const&>); |
295 | static_assert(std::invocable<volatile_qualified, S volatile&>); |
296 | static_assert(!std::invocable<volatile_qualified, S const volatile&>); |
297 | static_assert(std::invocable<volatile_qualified, S&&>); |
298 | static_assert(!std::invocable<volatile_qualified, S const&&>); |
299 | static_assert(std::invocable<volatile_qualified, S volatile&&>); |
300 | static_assert(!std::invocable<volatile_qualified, S const volatile&&>); |
301 | |
302 | static_assert(check_member_is_invocable<int (S::*)(int, S&) const volatile, S, |
303 | int, S&>()); |
304 | using cv_qualified = void (S::*)() const volatile; |
305 | static_assert(std::invocable<cv_qualified, S&>); |
306 | static_assert(std::invocable<cv_qualified, S const&>); |
307 | static_assert(std::invocable<cv_qualified, S volatile&>); |
308 | static_assert(std::invocable<cv_qualified, S const volatile&>); |
309 | static_assert(std::invocable<cv_qualified, S&&>); |
310 | static_assert(std::invocable<cv_qualified, S const&&>); |
311 | static_assert(std::invocable<cv_qualified, S volatile&&>); |
312 | static_assert(std::invocable<cv_qualified, S const volatile&&>); |
313 | |
314 | static_assert(check_member_is_invocable<int (S::*)() &, S&>()); |
315 | using lvalue_qualified = void (S::*)() &; |
316 | static_assert(std::invocable<lvalue_qualified, S&>); |
317 | static_assert(!std::invocable<lvalue_qualified, S const&>); |
318 | static_assert(!std::invocable<lvalue_qualified, S volatile&>); |
319 | static_assert(!std::invocable<lvalue_qualified, S const volatile&>); |
320 | static_assert(!std::invocable<lvalue_qualified, S&&>); |
321 | static_assert(!std::invocable<lvalue_qualified, S const&&>); |
322 | static_assert(!std::invocable<lvalue_qualified, S volatile&&>); |
323 | static_assert(!std::invocable<lvalue_qualified, S const volatile&&>); |
324 | |
325 | static_assert(check_member_is_invocable<int (S::*)() const&, S>()); |
326 | using lvalue_const_qualified = void (S::*)() const&; |
327 | static_assert(std::invocable<lvalue_const_qualified, S&>); |
328 | static_assert(std::invocable<lvalue_const_qualified, S const&>); |
329 | static_assert(!std::invocable<lvalue_const_qualified, S volatile&>); |
330 | static_assert(!std::invocable<lvalue_const_qualified, S const volatile&>); |
331 | static_assert(std::invocable<lvalue_const_qualified, S&&>); |
332 | static_assert(std::invocable<lvalue_const_qualified, S const&&>); |
333 | static_assert(!std::invocable<lvalue_const_qualified, S volatile&&>); |
334 | static_assert(!std::invocable<lvalue_const_qualified, S const volatile&&>); |
335 | |
336 | static_assert(check_member_is_invocable<int (S::*)() volatile&, S&>()); |
337 | using lvalue_volatile_qualified = void (S::*)() volatile&; |
338 | static_assert(std::invocable<lvalue_volatile_qualified, S&>); |
339 | static_assert(!std::invocable<lvalue_volatile_qualified, S const&>); |
340 | static_assert(std::invocable<lvalue_volatile_qualified, S volatile&>); |
341 | static_assert(!std::invocable<lvalue_volatile_qualified, S const volatile&>); |
342 | static_assert(!std::invocable<lvalue_volatile_qualified, S&&>); |
343 | static_assert(!std::invocable<lvalue_volatile_qualified, S const&&>); |
344 | static_assert(!std::invocable<lvalue_volatile_qualified, S volatile&&>); |
345 | static_assert(!std::invocable<lvalue_volatile_qualified, S const volatile&&>); |
346 | |
347 | static_assert(check_member_is_invocable<int (S::*)() const volatile&, S&>()); |
348 | using lvalue_cv_qualified = void (S::*)() const volatile&; |
349 | static_assert(std::invocable<lvalue_cv_qualified, S&>); |
350 | static_assert(std::invocable<lvalue_cv_qualified, S const&>); |
351 | static_assert(std::invocable<lvalue_cv_qualified, S volatile&>); |
352 | static_assert(std::invocable<lvalue_cv_qualified, S const volatile&>); |
353 | static_assert(!std::invocable<lvalue_cv_qualified, S&&>); |
354 | static_assert(!std::invocable<lvalue_cv_qualified, S const&&>); |
355 | static_assert(!std::invocable<lvalue_cv_qualified, S volatile&&>); |
356 | static_assert(!std::invocable<lvalue_cv_qualified, S const volatile&&>); |
357 | |
358 | using rvalue_unqualified = void (S::*)() &&; |
359 | static_assert(!std::invocable<rvalue_unqualified, S&>); |
360 | static_assert(!std::invocable<rvalue_unqualified, S const&>); |
361 | static_assert(!std::invocable<rvalue_unqualified, S volatile&>); |
362 | static_assert(!std::invocable<rvalue_unqualified, S const volatile&>); |
363 | static_assert(std::invocable<rvalue_unqualified, S&&>); |
364 | static_assert(!std::invocable<rvalue_unqualified, S const&&>); |
365 | static_assert(!std::invocable<rvalue_unqualified, S volatile&&>); |
366 | static_assert(!std::invocable<rvalue_unqualified, S const volatile&&>); |
367 | |
368 | using rvalue_const_unqualified = void (S::*)() const&&; |
369 | static_assert(!std::invocable<rvalue_const_unqualified, S&>); |
370 | static_assert(!std::invocable<rvalue_const_unqualified, S const&>); |
371 | static_assert(!std::invocable<rvalue_const_unqualified, S volatile&>); |
372 | static_assert(!std::invocable<rvalue_const_unqualified, S const volatile&>); |
373 | static_assert(std::invocable<rvalue_const_unqualified, S&&>); |
374 | static_assert(std::invocable<rvalue_const_unqualified, S const&&>); |
375 | static_assert(!std::invocable<rvalue_const_unqualified, S volatile&&>); |
376 | static_assert(!std::invocable<rvalue_const_unqualified, S const volatile&&>); |
377 | |
378 | using rvalue_volatile_unqualified = void (S::*)() volatile&&; |
379 | static_assert(!std::invocable<rvalue_volatile_unqualified, S&>); |
380 | static_assert(!std::invocable<rvalue_volatile_unqualified, S const&>); |
381 | static_assert(!std::invocable<rvalue_volatile_unqualified, S volatile&>); |
382 | static_assert(!std::invocable<rvalue_volatile_unqualified, S const volatile&>); |
383 | static_assert(std::invocable<rvalue_volatile_unqualified, S&&>); |
384 | static_assert(!std::invocable<rvalue_volatile_unqualified, S const&&>); |
385 | static_assert(std::invocable<rvalue_volatile_unqualified, S volatile&&>); |
386 | static_assert(!std::invocable<rvalue_volatile_unqualified, S const volatile&&>); |
387 | |
388 | using rvalue_cv_unqualified = void (S::*)() const volatile&&; |
389 | static_assert(!std::invocable<rvalue_cv_unqualified, S&>); |
390 | static_assert(!std::invocable<rvalue_cv_unqualified, S const&>); |
391 | static_assert(!std::invocable<rvalue_cv_unqualified, S volatile&>); |
392 | static_assert(!std::invocable<rvalue_cv_unqualified, S const volatile&>); |
393 | static_assert(std::invocable<rvalue_cv_unqualified, S&&>); |
394 | static_assert(std::invocable<rvalue_cv_unqualified, S const&&>); |
395 | static_assert(std::invocable<rvalue_cv_unqualified, S volatile&&>); |
396 | static_assert(std::invocable<rvalue_cv_unqualified, S const volatile&&>); |
397 | } // namespace pointer_to_member_functions |
398 | |
399 | // std::invocable-specific |
400 | static_assert(std::invocable<std::uniform_int_distribution<>, std::mt19937_64&>); |
401 | |
402 | // Check the concept with closure types |
403 | template<class F, class... Args> |
404 | constexpr bool is_invocable(F, Args&&...) { |
405 | return std::invocable<F, Args...>; |
406 | } |
407 | |
408 | static_assert(is_invocable([] {})); |
409 | static_assert(is_invocable([](int) {}, 0)); |
410 | static_assert(is_invocable([](int) {}, 0L)); |
411 | static_assert(!is_invocable([](int) {}, nullptr)); |
412 | int i = 0; |
413 | static_assert(is_invocable([](int&) {}, i)); |
414 | |