xref: /freebsd/contrib/llvm-project/libcxx/include/__functional/invoke.h (revision 9f44a47fd07924afc035991af15d84e6585dea4f)
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___FUNCTIONAL_INVOKE_H
11 #define _LIBCPP___FUNCTIONAL_INVOKE_H
12 
13 #include <__config>
14 #include <__type_traits/add_lvalue_reference.h>
15 #include <__type_traits/apply_cv.h>
16 #include <__type_traits/conditional.h>
17 #include <__type_traits/decay.h>
18 #include <__type_traits/enable_if.h>
19 #include <__type_traits/integral_constant.h>
20 #include <__type_traits/is_base_of.h>
21 #include <__type_traits/is_core_convertible.h>
22 #include <__type_traits/is_member_function_pointer.h>
23 #include <__type_traits/is_member_object_pointer.h>
24 #include <__type_traits/is_reference_wrapper.h>
25 #include <__type_traits/is_same.h>
26 #include <__type_traits/is_void.h>
27 #include <__type_traits/nat.h>
28 #include <__type_traits/remove_cv.h>
29 #include <__utility/declval.h>
30 #include <__utility/forward.h>
31 
32 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
33 #  pragma GCC system_header
34 #endif
35 
36 // TODO: Disentangle the type traits and std::invoke properly
37 
38 _LIBCPP_BEGIN_NAMESPACE_STD
39 
40 struct __any
41 {
42     __any(...);
43 };
44 
45 template <class _MP, bool _IsMemberFunctionPtr, bool _IsMemberObjectPtr>
46 struct __member_pointer_traits_imp
47 {
48 };
49 
50 template <class _Rp, class _Class, class ..._Param>
51 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false>
52 {
53     typedef _Class _ClassType;
54     typedef _Rp _ReturnType;
55     typedef _Rp (_FnType) (_Param...);
56 };
57 
58 template <class _Rp, class _Class, class ..._Param>
59 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false>
60 {
61     typedef _Class _ClassType;
62     typedef _Rp _ReturnType;
63     typedef _Rp (_FnType) (_Param..., ...);
64 };
65 
66 template <class _Rp, class _Class, class ..._Param>
67 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false>
68 {
69     typedef _Class const _ClassType;
70     typedef _Rp _ReturnType;
71     typedef _Rp (_FnType) (_Param...);
72 };
73 
74 template <class _Rp, class _Class, class ..._Param>
75 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const, true, false>
76 {
77     typedef _Class const _ClassType;
78     typedef _Rp _ReturnType;
79     typedef _Rp (_FnType) (_Param..., ...);
80 };
81 
82 template <class _Rp, class _Class, class ..._Param>
83 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false>
84 {
85     typedef _Class volatile _ClassType;
86     typedef _Rp _ReturnType;
87     typedef _Rp (_FnType) (_Param...);
88 };
89 
90 template <class _Rp, class _Class, class ..._Param>
91 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false>
92 {
93     typedef _Class volatile _ClassType;
94     typedef _Rp _ReturnType;
95     typedef _Rp (_FnType) (_Param..., ...);
96 };
97 
98 template <class _Rp, class _Class, class ..._Param>
99 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false>
100 {
101     typedef _Class const volatile _ClassType;
102     typedef _Rp _ReturnType;
103     typedef _Rp (_FnType) (_Param...);
104 };
105 
106 template <class _Rp, class _Class, class ..._Param>
107 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false>
108 {
109     typedef _Class const volatile _ClassType;
110     typedef _Rp _ReturnType;
111     typedef _Rp (_FnType) (_Param..., ...);
112 };
113 
114 template <class _Rp, class _Class, class ..._Param>
115 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &, true, false>
116 {
117     typedef _Class& _ClassType;
118     typedef _Rp _ReturnType;
119     typedef _Rp (_FnType) (_Param...);
120 };
121 
122 template <class _Rp, class _Class, class ..._Param>
123 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &, true, false>
124 {
125     typedef _Class& _ClassType;
126     typedef _Rp _ReturnType;
127     typedef _Rp (_FnType) (_Param..., ...);
128 };
129 
130 template <class _Rp, class _Class, class ..._Param>
131 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&, true, false>
132 {
133     typedef _Class const& _ClassType;
134     typedef _Rp _ReturnType;
135     typedef _Rp (_FnType) (_Param...);
136 };
137 
138 template <class _Rp, class _Class, class ..._Param>
139 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&, true, false>
140 {
141     typedef _Class const& _ClassType;
142     typedef _Rp _ReturnType;
143     typedef _Rp (_FnType) (_Param..., ...);
144 };
145 
146 template <class _Rp, class _Class, class ..._Param>
147 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false>
148 {
149     typedef _Class volatile& _ClassType;
150     typedef _Rp _ReturnType;
151     typedef _Rp (_FnType) (_Param...);
152 };
153 
154 template <class _Rp, class _Class, class ..._Param>
155 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false>
156 {
157     typedef _Class volatile& _ClassType;
158     typedef _Rp _ReturnType;
159     typedef _Rp (_FnType) (_Param..., ...);
160 };
161 
162 template <class _Rp, class _Class, class ..._Param>
163 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false>
164 {
165     typedef _Class const volatile& _ClassType;
166     typedef _Rp _ReturnType;
167     typedef _Rp (_FnType) (_Param...);
168 };
169 
170 template <class _Rp, class _Class, class ..._Param>
171 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false>
172 {
173     typedef _Class const volatile& _ClassType;
174     typedef _Rp _ReturnType;
175     typedef _Rp (_FnType) (_Param..., ...);
176 };
177 
178 template <class _Rp, class _Class, class ..._Param>
179 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &&, true, false>
180 {
181     typedef _Class&& _ClassType;
182     typedef _Rp _ReturnType;
183     typedef _Rp (_FnType) (_Param...);
184 };
185 
186 template <class _Rp, class _Class, class ..._Param>
187 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &&, true, false>
188 {
189     typedef _Class&& _ClassType;
190     typedef _Rp _ReturnType;
191     typedef _Rp (_FnType) (_Param..., ...);
192 };
193 
194 template <class _Rp, class _Class, class ..._Param>
195 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&&, true, false>
196 {
197     typedef _Class const&& _ClassType;
198     typedef _Rp _ReturnType;
199     typedef _Rp (_FnType) (_Param...);
200 };
201 
202 template <class _Rp, class _Class, class ..._Param>
203 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&&, true, false>
204 {
205     typedef _Class const&& _ClassType;
206     typedef _Rp _ReturnType;
207     typedef _Rp (_FnType) (_Param..., ...);
208 };
209 
210 template <class _Rp, class _Class, class ..._Param>
211 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false>
212 {
213     typedef _Class volatile&& _ClassType;
214     typedef _Rp _ReturnType;
215     typedef _Rp (_FnType) (_Param...);
216 };
217 
218 template <class _Rp, class _Class, class ..._Param>
219 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false>
220 {
221     typedef _Class volatile&& _ClassType;
222     typedef _Rp _ReturnType;
223     typedef _Rp (_FnType) (_Param..., ...);
224 };
225 
226 template <class _Rp, class _Class, class ..._Param>
227 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false>
228 {
229     typedef _Class const volatile&& _ClassType;
230     typedef _Rp _ReturnType;
231     typedef _Rp (_FnType) (_Param...);
232 };
233 
234 template <class _Rp, class _Class, class ..._Param>
235 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false>
236 {
237     typedef _Class const volatile&& _ClassType;
238     typedef _Rp _ReturnType;
239     typedef _Rp (_FnType) (_Param..., ...);
240 };
241 
242 template <class _Rp, class _Class>
243 struct __member_pointer_traits_imp<_Rp _Class::*, false, true>
244 {
245     typedef _Class _ClassType;
246     typedef _Rp _ReturnType;
247 };
248 
249 template <class _MP>
250 struct __member_pointer_traits
251     : public __member_pointer_traits_imp<typename remove_cv<_MP>::type,
252                     is_member_function_pointer<_MP>::value,
253                     is_member_object_pointer<_MP>::value>
254 {
255 //     typedef ... _ClassType;
256 //     typedef ... _ReturnType;
257 //     typedef ... _FnType;
258 };
259 
260 template <class _DecayedFp>
261 struct __member_pointer_class_type {};
262 
263 template <class _Ret, class _ClassType>
264 struct __member_pointer_class_type<_Ret _ClassType::*> {
265   typedef _ClassType type;
266 };
267 
268 template <class _Fp, class _A0,
269          class _DecayFp = typename decay<_Fp>::type,
270          class _DecayA0 = typename decay<_A0>::type,
271          class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
272 using __enable_if_bullet1 = typename enable_if
273     <
274         is_member_function_pointer<_DecayFp>::value
275         && is_base_of<_ClassT, _DecayA0>::value
276     >::type;
277 
278 template <class _Fp, class _A0,
279          class _DecayFp = typename decay<_Fp>::type,
280          class _DecayA0 = typename decay<_A0>::type>
281 using __enable_if_bullet2 = typename enable_if
282     <
283         is_member_function_pointer<_DecayFp>::value
284         && __is_reference_wrapper<_DecayA0>::value
285     >::type;
286 
287 template <class _Fp, class _A0,
288          class _DecayFp = typename decay<_Fp>::type,
289          class _DecayA0 = typename decay<_A0>::type,
290          class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
291 using __enable_if_bullet3 = typename enable_if
292     <
293         is_member_function_pointer<_DecayFp>::value
294         && !is_base_of<_ClassT, _DecayA0>::value
295         && !__is_reference_wrapper<_DecayA0>::value
296     >::type;
297 
298 template <class _Fp, class _A0,
299          class _DecayFp = typename decay<_Fp>::type,
300          class _DecayA0 = typename decay<_A0>::type,
301          class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
302 using __enable_if_bullet4 = typename enable_if
303     <
304         is_member_object_pointer<_DecayFp>::value
305         && is_base_of<_ClassT, _DecayA0>::value
306     >::type;
307 
308 template <class _Fp, class _A0,
309          class _DecayFp = typename decay<_Fp>::type,
310          class _DecayA0 = typename decay<_A0>::type>
311 using __enable_if_bullet5 = typename enable_if
312     <
313         is_member_object_pointer<_DecayFp>::value
314         && __is_reference_wrapper<_DecayA0>::value
315     >::type;
316 
317 template <class _Fp, class _A0,
318          class _DecayFp = typename decay<_Fp>::type,
319          class _DecayA0 = typename decay<_A0>::type,
320          class _ClassT = typename __member_pointer_class_type<_DecayFp>::type>
321 using __enable_if_bullet6 = typename enable_if
322     <
323         is_member_object_pointer<_DecayFp>::value
324         && !is_base_of<_ClassT, _DecayA0>::value
325         && !__is_reference_wrapper<_DecayA0>::value
326     >::type;
327 
328 // __invoke forward declarations
329 
330 // fall back - none of the bullets
331 
332 template <class ..._Args>
333 __nat __invoke(__any, _Args&& ...__args);
334 
335 // bullets 1, 2 and 3
336 
337 template <class _Fp, class _A0, class ..._Args,
338           class = __enable_if_bullet1<_Fp, _A0> >
339 inline _LIBCPP_INLINE_VISIBILITY
340 _LIBCPP_CONSTEXPR decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...))
341 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
342     _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...)))
343     { return           (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); }
344 
345 template <class _Fp, class _A0, class ..._Args,
346           class = __enable_if_bullet2<_Fp, _A0> >
347 inline _LIBCPP_INLINE_VISIBILITY
348 _LIBCPP_CONSTEXPR decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...))
349 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
350     _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...)))
351     { return          (__a0.get().*__f)(static_cast<_Args&&>(__args)...); }
352 
353 template <class _Fp, class _A0, class ..._Args,
354           class = __enable_if_bullet3<_Fp, _A0> >
355 inline _LIBCPP_INLINE_VISIBILITY
356 _LIBCPP_CONSTEXPR decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...))
357 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
358     _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...)))
359     { return          ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); }
360 
361 // bullets 4, 5 and 6
362 
363 template <class _Fp, class _A0,
364           class = __enable_if_bullet4<_Fp, _A0> >
365 inline _LIBCPP_INLINE_VISIBILITY
366 _LIBCPP_CONSTEXPR decltype(std::declval<_A0>().*std::declval<_Fp>())
367 __invoke(_Fp&& __f, _A0&& __a0)
368     _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f))
369     { return          static_cast<_A0&&>(__a0).*__f; }
370 
371 template <class _Fp, class _A0,
372           class = __enable_if_bullet5<_Fp, _A0> >
373 inline _LIBCPP_INLINE_VISIBILITY
374 _LIBCPP_CONSTEXPR decltype(std::declval<_A0>().get().*std::declval<_Fp>())
375 __invoke(_Fp&& __f, _A0&& __a0)
376     _NOEXCEPT_(noexcept(__a0.get().*__f))
377     { return          __a0.get().*__f; }
378 
379 template <class _Fp, class _A0,
380           class = __enable_if_bullet6<_Fp, _A0> >
381 inline _LIBCPP_INLINE_VISIBILITY
382 _LIBCPP_CONSTEXPR decltype((*std::declval<_A0>()).*std::declval<_Fp>())
383 __invoke(_Fp&& __f, _A0&& __a0)
384     _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f))
385     { return          (*static_cast<_A0&&>(__a0)).*__f; }
386 
387 // bullet 7
388 
389 template <class _Fp, class ..._Args>
390 inline _LIBCPP_INLINE_VISIBILITY
391 _LIBCPP_CONSTEXPR decltype(std::declval<_Fp>()(std::declval<_Args>()...))
392 __invoke(_Fp&& __f, _Args&& ...__args)
393     _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...)))
394     { return          static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); }
395 
396 // __invokable
397 template <class _Ret, class _Fp, class ..._Args>
398 struct __invokable_r
399 {
400   template <class _XFp, class ..._XArgs>
401   static decltype(std::__invoke(declval<_XFp>(), declval<_XArgs>()...)) __try_call(int);
402   template <class _XFp, class ..._XArgs>
403   static __nat __try_call(...);
404 
405   // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void,
406   // or incomplete array types as required by the standard.
407   using _Result = decltype(__try_call<_Fp, _Args...>(0));
408 
409   using type = typename conditional<
410       _IsNotSame<_Result, __nat>::value,
411       typename conditional< is_void<_Ret>::value, true_type, __is_core_convertible<_Result, _Ret> >::type,
412       false_type >::type;
413   static const bool value = type::value;
414 };
415 template <class _Fp, class ..._Args>
416 using __invokable = __invokable_r<void, _Fp, _Args...>;
417 
418 template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class ..._Args>
419 struct __nothrow_invokable_r_imp {
420   static const bool value = false;
421 };
422 
423 template <class _Ret, class _Fp, class ..._Args>
424 struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...>
425 {
426     typedef __nothrow_invokable_r_imp _ThisT;
427 
428     template <class _Tp>
429     static void __test_noexcept(_Tp) _NOEXCEPT;
430 
431     static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>(
432         _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...)));
433 };
434 
435 template <class _Ret, class _Fp, class ..._Args>
436 struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...>
437 {
438     static const bool value = noexcept(
439         _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...));
440 };
441 
442 template <class _Ret, class _Fp, class ..._Args>
443 using __nothrow_invokable_r =
444     __nothrow_invokable_r_imp<
445             __invokable_r<_Ret, _Fp, _Args...>::value,
446             is_void<_Ret>::value,
447             _Ret, _Fp, _Args...
448     >;
449 
450 template <class _Fp, class ..._Args>
451 using __nothrow_invokable =
452     __nothrow_invokable_r_imp<
453             __invokable<_Fp, _Args...>::value,
454             true, void, _Fp, _Args...
455     >;
456 
457 template <class _Fp, class ..._Args>
458 struct __invoke_of
459     : public enable_if<
460         __invokable<_Fp, _Args...>::value,
461         typename __invokable_r<void, _Fp, _Args...>::_Result>
462 {
463 };
464 
465 template <class _Ret, bool = is_void<_Ret>::value>
466 struct __invoke_void_return_wrapper
467 {
468     template <class ..._Args>
469     static _Ret __call(_Args&&... __args) {
470         return std::__invoke(std::forward<_Args>(__args)...);
471     }
472 };
473 
474 template <class _Ret>
475 struct __invoke_void_return_wrapper<_Ret, true>
476 {
477     template <class ..._Args>
478     static void __call(_Args&&... __args) {
479         std::__invoke(std::forward<_Args>(__args)...);
480     }
481 };
482 
483 #if _LIBCPP_STD_VER > 14
484 
485 // is_invocable
486 
487 template <class _Fn, class ..._Args>
488 struct _LIBCPP_TEMPLATE_VIS is_invocable
489     : integral_constant<bool, __invokable<_Fn, _Args...>::value> {};
490 
491 template <class _Ret, class _Fn, class ..._Args>
492 struct _LIBCPP_TEMPLATE_VIS is_invocable_r
493     : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
494 
495 template <class _Fn, class ..._Args>
496 inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
497 
498 template <class _Ret, class _Fn, class ..._Args>
499 inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
500 
501 // is_nothrow_invocable
502 
503 template <class _Fn, class ..._Args>
504 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable
505     : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {};
506 
507 template <class _Ret, class _Fn, class ..._Args>
508 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r
509     : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {};
510 
511 template <class _Fn, class ..._Args>
512 inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
513 
514 template <class _Ret, class _Fn, class ..._Args>
515 inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
516 
517 template <class _Fn, class... _Args>
518 struct _LIBCPP_TEMPLATE_VIS invoke_result
519     : __invoke_of<_Fn, _Args...>
520 {
521 };
522 
523 template <class _Fn, class... _Args>
524 using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
525 
526 template <class _Fn, class ..._Args>
527 _LIBCPP_CONSTEXPR_AFTER_CXX17 invoke_result_t<_Fn, _Args...>
528 invoke(_Fn&& __f, _Args&&... __args)
529     noexcept(is_nothrow_invocable_v<_Fn, _Args...>)
530 {
531     return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...);
532 }
533 
534 #endif // _LIBCPP_STD_VER > 14
535 
536 _LIBCPP_END_NAMESPACE_STD
537 
538 #endif // _LIBCPP___FUNCTIONAL_INVOKE_H
539