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