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___TYPE_TRAITS_INVOKE_H
11 #define _LIBCPP___TYPE_TRAITS_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 _LIBCPP_BEGIN_NAMESPACE_STD
37 
38 struct __any {
39   __any(...);
40 };
41 
42 template <class _MP, bool _IsMemberFunctionPtr, bool _IsMemberObjectPtr>
43 struct __member_pointer_traits_imp {};
44 
45 template <class _Rp, class _Class, class... _Param>
46 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false> {
47   typedef _Class _ClassType;
48   typedef _Rp _ReturnType;
49   typedef _Rp(_FnType)(_Param...);
50 };
51 
52 template <class _Rp, class _Class, class... _Param>
53 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false> {
54   typedef _Class _ClassType;
55   typedef _Rp _ReturnType;
56   typedef _Rp(_FnType)(_Param..., ...);
57 };
58 
59 template <class _Rp, class _Class, class... _Param>
60 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false> {
61   typedef _Class const _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   typedef _Class const _ClassType;
69   typedef _Rp _ReturnType;
70   typedef _Rp(_FnType)(_Param..., ...);
71 };
72 
73 template <class _Rp, class _Class, class... _Param>
74 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false> {
75   typedef _Class volatile _ClassType;
76   typedef _Rp _ReturnType;
77   typedef _Rp(_FnType)(_Param...);
78 };
79 
80 template <class _Rp, class _Class, class... _Param>
81 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false> {
82   typedef _Class volatile _ClassType;
83   typedef _Rp _ReturnType;
84   typedef _Rp(_FnType)(_Param..., ...);
85 };
86 
87 template <class _Rp, class _Class, class... _Param>
88 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false> {
89   typedef _Class const volatile _ClassType;
90   typedef _Rp _ReturnType;
91   typedef _Rp(_FnType)(_Param...);
92 };
93 
94 template <class _Rp, class _Class, class... _Param>
95 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false> {
96   typedef _Class const volatile _ClassType;
97   typedef _Rp _ReturnType;
98   typedef _Rp(_FnType)(_Param..., ...);
99 };
100 
101 template <class _Rp, class _Class, class... _Param>
102 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...)&, true, false> {
103   typedef _Class& _ClassType;
104   typedef _Rp _ReturnType;
105   typedef _Rp(_FnType)(_Param...);
106 };
107 
108 template <class _Rp, class _Class, class... _Param>
109 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...)&, true, false> {
110   typedef _Class& _ClassType;
111   typedef _Rp _ReturnType;
112   typedef _Rp(_FnType)(_Param..., ...);
113 };
114 
115 template <class _Rp, class _Class, class... _Param>
116 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&, true, false> {
117   typedef _Class const& _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..., ...) const&, true, false> {
124   typedef _Class const& _ClassType;
125   typedef _Rp _ReturnType;
126   typedef _Rp(_FnType)(_Param..., ...);
127 };
128 
129 template <class _Rp, class _Class, class... _Param>
130 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false> {
131   typedef _Class volatile& _ClassType;
132   typedef _Rp _ReturnType;
133   typedef _Rp(_FnType)(_Param...);
134 };
135 
136 template <class _Rp, class _Class, class... _Param>
137 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false> {
138   typedef _Class volatile& _ClassType;
139   typedef _Rp _ReturnType;
140   typedef _Rp(_FnType)(_Param..., ...);
141 };
142 
143 template <class _Rp, class _Class, class... _Param>
144 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false> {
145   typedef _Class const volatile& _ClassType;
146   typedef _Rp _ReturnType;
147   typedef _Rp(_FnType)(_Param...);
148 };
149 
150 template <class _Rp, class _Class, class... _Param>
151 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false> {
152   typedef _Class const volatile& _ClassType;
153   typedef _Rp _ReturnType;
154   typedef _Rp(_FnType)(_Param..., ...);
155 };
156 
157 template <class _Rp, class _Class, class... _Param>
158 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...)&&, true, false> {
159   typedef _Class&& _ClassType;
160   typedef _Rp _ReturnType;
161   typedef _Rp(_FnType)(_Param...);
162 };
163 
164 template <class _Rp, class _Class, class... _Param>
165 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...)&&, true, false> {
166   typedef _Class&& _ClassType;
167   typedef _Rp _ReturnType;
168   typedef _Rp(_FnType)(_Param..., ...);
169 };
170 
171 template <class _Rp, class _Class, class... _Param>
172 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&&, true, false> {
173   typedef _Class const&& _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..., ...) const&&, true, false> {
180   typedef _Class const&& _ClassType;
181   typedef _Rp _ReturnType;
182   typedef _Rp(_FnType)(_Param..., ...);
183 };
184 
185 template <class _Rp, class _Class, class... _Param>
186 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false> {
187   typedef _Class volatile&& _ClassType;
188   typedef _Rp _ReturnType;
189   typedef _Rp(_FnType)(_Param...);
190 };
191 
192 template <class _Rp, class _Class, class... _Param>
193 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false> {
194   typedef _Class volatile&& _ClassType;
195   typedef _Rp _ReturnType;
196   typedef _Rp(_FnType)(_Param..., ...);
197 };
198 
199 template <class _Rp, class _Class, class... _Param>
200 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false> {
201   typedef _Class const volatile&& _ClassType;
202   typedef _Rp _ReturnType;
203   typedef _Rp(_FnType)(_Param...);
204 };
205 
206 template <class _Rp, class _Class, class... _Param>
207 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false> {
208   typedef _Class const volatile&& _ClassType;
209   typedef _Rp _ReturnType;
210   typedef _Rp(_FnType)(_Param..., ...);
211 };
212 
213 template <class _Rp, class _Class>
214 struct __member_pointer_traits_imp<_Rp _Class::*, false, true> {
215   typedef _Class _ClassType;
216   typedef _Rp _ReturnType;
217 };
218 
219 template <class _MP>
220 struct __member_pointer_traits
221     : public __member_pointer_traits_imp<__remove_cv_t<_MP>,
222                                          is_member_function_pointer<_MP>::value,
223                                          is_member_object_pointer<_MP>::value> {
224   //     typedef ... _ClassType;
225   //     typedef ... _ReturnType;
226   //     typedef ... _FnType;
227 };
228 
229 template <class _DecayedFp>
230 struct __member_pointer_class_type {};
231 
232 template <class _Ret, class _ClassType>
233 struct __member_pointer_class_type<_Ret _ClassType::*> {
234   typedef _ClassType type;
235 };
236 
237 template <class _Fp,
238           class _A0,
239           class _DecayFp = __decay_t<_Fp>,
240           class _DecayA0 = __decay_t<_A0>,
241           class _ClassT  = typename __member_pointer_class_type<_DecayFp>::type>
242 using __enable_if_bullet1 =
243     __enable_if_t<is_member_function_pointer<_DecayFp>::value &&
244                   (is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value)>;
245 
246 template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> >
247 using __enable_if_bullet2 =
248     __enable_if_t<is_member_function_pointer<_DecayFp>::value && __is_reference_wrapper<_DecayA0>::value>;
249 
250 template <class _Fp,
251           class _A0,
252           class _DecayFp = __decay_t<_Fp>,
253           class _DecayA0 = __decay_t<_A0>,
254           class _ClassT  = typename __member_pointer_class_type<_DecayFp>::type>
255 using __enable_if_bullet3 =
256     __enable_if_t<is_member_function_pointer<_DecayFp>::value &&
257                   !(is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value) &&
258                   !__is_reference_wrapper<_DecayA0>::value>;
259 
260 template <class _Fp,
261           class _A0,
262           class _DecayFp = __decay_t<_Fp>,
263           class _DecayA0 = __decay_t<_A0>,
264           class _ClassT  = typename __member_pointer_class_type<_DecayFp>::type>
265 using __enable_if_bullet4 =
266     __enable_if_t<is_member_object_pointer<_DecayFp>::value &&
267                   (is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value)>;
268 
269 template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> >
270 using __enable_if_bullet5 =
271     __enable_if_t<is_member_object_pointer<_DecayFp>::value && __is_reference_wrapper<_DecayA0>::value>;
272 
273 template <class _Fp,
274           class _A0,
275           class _DecayFp = __decay_t<_Fp>,
276           class _DecayA0 = __decay_t<_A0>,
277           class _ClassT  = typename __member_pointer_class_type<_DecayFp>::type>
278 using __enable_if_bullet6 =
279     __enable_if_t<is_member_object_pointer<_DecayFp>::value &&
280                   !(is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value) &&
281                   !__is_reference_wrapper<_DecayA0>::value>;
282 
283 // __invoke forward declarations
284 
285 // fall back - none of the bullets
286 
287 template <class... _Args>
288 __nat __invoke(__any, _Args&&... __args);
289 
290 // bullets 1, 2 and 3
291 
292 // clang-format off
293 template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet1<_Fp, _A0> >
294 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
295 decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...))
296 __invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args)
297     _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...)))
298                { return (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); }
299 
300 template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet2<_Fp, _A0> >
301 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
302 decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...))
303 __invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args)
304     _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...)))
305                { return (__a0.get().*__f)(static_cast<_Args&&>(__args)...); }
306 
307 template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet3<_Fp, _A0> >
308 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
309 decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...))
310 __invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args)
311     _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...)))
312                { return ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); }
313 
314 // bullets 4, 5 and 6
315 
316 template <class _Fp, class _A0, class = __enable_if_bullet4<_Fp, _A0> >
317 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
318 decltype(std::declval<_A0>().*std::declval<_Fp>())
319 __invoke(_Fp&& __f, _A0&& __a0)
320     _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f))
321                { return static_cast<_A0&&>(__a0).*__f; }
322 
323 template <class _Fp, class _A0, class = __enable_if_bullet5<_Fp, _A0> >
324 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
325 decltype(std::declval<_A0>().get().*std::declval<_Fp>())
326 __invoke(_Fp&& __f, _A0&& __a0)
327     _NOEXCEPT_(noexcept(__a0.get().*__f))
328                { return __a0.get().*__f; }
329 
330 template <class _Fp, class _A0, class = __enable_if_bullet6<_Fp, _A0> >
331 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
332 decltype((*std::declval<_A0>()).*std::declval<_Fp>())
333 __invoke(_Fp&& __f, _A0&& __a0)
334     _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f))
335                { return (*static_cast<_A0&&>(__a0)).*__f; }
336 
337 // bullet 7
338 
339 template <class _Fp, class... _Args>
340 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
341 decltype(std::declval<_Fp>()(std::declval<_Args>()...))
342 __invoke(_Fp&& __f, _Args&&... __args)
343     _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...)))
344                { return static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); }
345 // clang-format on
346 
347 // __invokable
348 template <class _Ret, class _Fp, class... _Args>
349 struct __invokable_r {
350   template <class _XFp, class... _XArgs>
351   static decltype(std::__invoke(std::declval<_XFp>(), std::declval<_XArgs>()...)) __try_call(int);
352   template <class _XFp, class... _XArgs>
353   static __nat __try_call(...);
354 
355   // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void,
356   // or incomplete array types as required by the standard.
357   using _Result = decltype(__try_call<_Fp, _Args...>(0));
358 
359   using type              = __conditional_t<_IsNotSame<_Result, __nat>::value,
360                                __conditional_t<is_void<_Ret>::value, true_type, __is_core_convertible<_Result, _Ret> >,
361                                false_type>;
362   static const bool value = type::value;
363 };
364 template <class _Fp, class... _Args>
365 using __invokable = __invokable_r<void, _Fp, _Args...>;
366 
367 template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class... _Args>
368 struct __nothrow_invokable_r_imp {
369   static const bool value = false;
370 };
371 
372 template <class _Ret, class _Fp, class... _Args>
373 struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...> {
374   typedef __nothrow_invokable_r_imp _ThisT;
375 
376   template <class _Tp>
377   static void __test_noexcept(_Tp) _NOEXCEPT;
378 
379 #ifdef _LIBCPP_CXX03_LANG
380   static const bool value = false;
381 #else
382   static const bool value =
383       noexcept(_ThisT::__test_noexcept<_Ret>(std::__invoke(std::declval<_Fp>(), std::declval<_Args>()...)));
384 #endif
385 };
386 
387 template <class _Ret, class _Fp, class... _Args>
388 struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...> {
389 #ifdef _LIBCPP_CXX03_LANG
390   static const bool value = false;
391 #else
392   static const bool value = noexcept(std::__invoke(std::declval<_Fp>(), std::declval<_Args>()...));
393 #endif
394 };
395 
396 template <class _Ret, class _Fp, class... _Args>
397 using __nothrow_invokable_r =
398     __nothrow_invokable_r_imp<__invokable_r<_Ret, _Fp, _Args...>::value, is_void<_Ret>::value, _Ret, _Fp, _Args...>;
399 
400 template <class _Fp, class... _Args>
401 using __nothrow_invokable = __nothrow_invokable_r_imp<__invokable<_Fp, _Args...>::value, true, void, _Fp, _Args...>;
402 
403 template <class _Fp, class... _Args>
404 struct __invoke_of
405     : public enable_if<__invokable<_Fp, _Args...>::value, typename __invokable_r<void, _Fp, _Args...>::_Result> {};
406 
407 template <class _Ret, bool = is_void<_Ret>::value>
408 struct __invoke_void_return_wrapper {
409   template <class... _Args>
410   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static _Ret __call(_Args&&... __args) {
411     return std::__invoke(std::forward<_Args>(__args)...);
412   }
413 };
414 
415 template <class _Ret>
416 struct __invoke_void_return_wrapper<_Ret, true> {
417   template <class... _Args>
418   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __call(_Args&&... __args) {
419     std::__invoke(std::forward<_Args>(__args)...);
420   }
421 };
422 
423 #if _LIBCPP_STD_VER >= 17
424 
425 // is_invocable
426 
427 template <class _Fn, class... _Args>
428 struct _LIBCPP_TEMPLATE_VIS is_invocable : integral_constant<bool, __invokable<_Fn, _Args...>::value> {};
429 
430 template <class _Ret, class _Fn, class... _Args>
431 struct _LIBCPP_TEMPLATE_VIS is_invocable_r : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
432 
433 template <class _Fn, class... _Args>
434 inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
435 
436 template <class _Ret, class _Fn, class... _Args>
437 inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
438 
439 // is_nothrow_invocable
440 
441 template <class _Fn, class... _Args>
442 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {
443 };
444 
445 template <class _Ret, class _Fn, class... _Args>
446 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r
447     : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {};
448 
449 template <class _Fn, class... _Args>
450 inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
451 
452 template <class _Ret, class _Fn, class... _Args>
453 inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
454 
455 template <class _Fn, class... _Args>
456 struct _LIBCPP_TEMPLATE_VIS invoke_result : __invoke_of<_Fn, _Args...> {};
457 
458 template <class _Fn, class... _Args>
459 using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
460 
461 #endif // _LIBCPP_STD_VER >= 17
462 
463 _LIBCPP_END_NAMESPACE_STD
464 
465 #endif // _LIBCPP___TYPE_TRAITS_INVOKE_H
466