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_WEAK_RESULT_TYPE_H
11 #define _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H
12 
13 #include <__config>
14 #include <__functional/binary_function.h>
15 #include <__functional/unary_function.h>
16 #include <type_traits>
17 
18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19 #pragma GCC system_header
20 #endif
21 
22 _LIBCPP_BEGIN_NAMESPACE_STD
23 
24 template <class _Tp>
25 struct __has_result_type
26 {
27 private:
28     struct __two {char __lx; char __lxx;};
29     template <class _Up> static __two __test(...);
30     template <class _Up> static char __test(typename _Up::result_type* = 0);
31 public:
32     static const bool value = sizeof(__test<_Tp>(0)) == 1;
33 };
34 
35 // __weak_result_type
36 
37 template <class _Tp>
38 struct __derives_from_unary_function
39 {
40 private:
41     struct __two {char __lx; char __lxx;};
42     static __two __test(...);
43     template <class _Ap, class _Rp>
44         static unary_function<_Ap, _Rp>
45         __test(const volatile unary_function<_Ap, _Rp>*);
46 public:
47     static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value;
48     typedef decltype(__test((_Tp*)0)) type;
49 };
50 
51 template <class _Tp>
52 struct __derives_from_binary_function
53 {
54 private:
55     struct __two {char __lx; char __lxx;};
56     static __two __test(...);
57     template <class _A1, class _A2, class _Rp>
58         static binary_function<_A1, _A2, _Rp>
59         __test(const volatile binary_function<_A1, _A2, _Rp>*);
60 public:
61     static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value;
62     typedef decltype(__test((_Tp*)0)) type;
63 };
64 
65 template <class _Tp, bool = __derives_from_unary_function<_Tp>::value>
66 struct __maybe_derive_from_unary_function  // bool is true
67     : public __derives_from_unary_function<_Tp>::type
68 {
69 };
70 
71 template <class _Tp>
72 struct __maybe_derive_from_unary_function<_Tp, false>
73 {
74 };
75 
76 template <class _Tp, bool = __derives_from_binary_function<_Tp>::value>
77 struct __maybe_derive_from_binary_function  // bool is true
78     : public __derives_from_binary_function<_Tp>::type
79 {
80 };
81 
82 template <class _Tp>
83 struct __maybe_derive_from_binary_function<_Tp, false>
84 {
85 };
86 
87 template <class _Tp, bool = __has_result_type<_Tp>::value>
88 struct __weak_result_type_imp // bool is true
89     : public __maybe_derive_from_unary_function<_Tp>,
90       public __maybe_derive_from_binary_function<_Tp>
91 {
92     typedef _LIBCPP_NODEBUG_TYPE typename _Tp::result_type result_type;
93 };
94 
95 template <class _Tp>
96 struct __weak_result_type_imp<_Tp, false>
97     : public __maybe_derive_from_unary_function<_Tp>,
98       public __maybe_derive_from_binary_function<_Tp>
99 {
100 };
101 
102 template <class _Tp>
103 struct __weak_result_type
104     : public __weak_result_type_imp<_Tp>
105 {
106 };
107 
108 // 0 argument case
109 
110 template <class _Rp>
111 struct __weak_result_type<_Rp ()>
112 {
113     typedef _LIBCPP_NODEBUG_TYPE  _Rp result_type;
114 };
115 
116 template <class _Rp>
117 struct __weak_result_type<_Rp (&)()>
118 {
119     typedef _LIBCPP_NODEBUG_TYPE  _Rp result_type;
120 };
121 
122 template <class _Rp>
123 struct __weak_result_type<_Rp (*)()>
124 {
125     typedef _LIBCPP_NODEBUG_TYPE  _Rp result_type;
126 };
127 
128 // 1 argument case
129 
130 template <class _Rp, class _A1>
131 struct __weak_result_type<_Rp (_A1)>
132     : public unary_function<_A1, _Rp>
133 {
134 };
135 
136 template <class _Rp, class _A1>
137 struct __weak_result_type<_Rp (&)(_A1)>
138     : public unary_function<_A1, _Rp>
139 {
140 };
141 
142 template <class _Rp, class _A1>
143 struct __weak_result_type<_Rp (*)(_A1)>
144     : public unary_function<_A1, _Rp>
145 {
146 };
147 
148 template <class _Rp, class _Cp>
149 struct __weak_result_type<_Rp (_Cp::*)()>
150     : public unary_function<_Cp*, _Rp>
151 {
152 };
153 
154 template <class _Rp, class _Cp>
155 struct __weak_result_type<_Rp (_Cp::*)() const>
156     : public unary_function<const _Cp*, _Rp>
157 {
158 };
159 
160 template <class _Rp, class _Cp>
161 struct __weak_result_type<_Rp (_Cp::*)() volatile>
162     : public unary_function<volatile _Cp*, _Rp>
163 {
164 };
165 
166 template <class _Rp, class _Cp>
167 struct __weak_result_type<_Rp (_Cp::*)() const volatile>
168     : public unary_function<const volatile _Cp*, _Rp>
169 {
170 };
171 
172 // 2 argument case
173 
174 template <class _Rp, class _A1, class _A2>
175 struct __weak_result_type<_Rp (_A1, _A2)>
176     : public binary_function<_A1, _A2, _Rp>
177 {
178 };
179 
180 template <class _Rp, class _A1, class _A2>
181 struct __weak_result_type<_Rp (*)(_A1, _A2)>
182     : public binary_function<_A1, _A2, _Rp>
183 {
184 };
185 
186 template <class _Rp, class _A1, class _A2>
187 struct __weak_result_type<_Rp (&)(_A1, _A2)>
188     : public binary_function<_A1, _A2, _Rp>
189 {
190 };
191 
192 template <class _Rp, class _Cp, class _A1>
193 struct __weak_result_type<_Rp (_Cp::*)(_A1)>
194     : public binary_function<_Cp*, _A1, _Rp>
195 {
196 };
197 
198 template <class _Rp, class _Cp, class _A1>
199 struct __weak_result_type<_Rp (_Cp::*)(_A1) const>
200     : public binary_function<const _Cp*, _A1, _Rp>
201 {
202 };
203 
204 template <class _Rp, class _Cp, class _A1>
205 struct __weak_result_type<_Rp (_Cp::*)(_A1) volatile>
206     : public binary_function<volatile _Cp*, _A1, _Rp>
207 {
208 };
209 
210 template <class _Rp, class _Cp, class _A1>
211 struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile>
212     : public binary_function<const volatile _Cp*, _A1, _Rp>
213 {
214 };
215 
216 
217 #ifndef _LIBCPP_CXX03_LANG
218 // 3 or more arguments
219 
220 template <class _Rp, class _A1, class _A2, class _A3, class ..._A4>
221 struct __weak_result_type<_Rp (_A1, _A2, _A3, _A4...)>
222 {
223     typedef _Rp result_type;
224 };
225 
226 template <class _Rp, class _A1, class _A2, class _A3, class ..._A4>
227 struct __weak_result_type<_Rp (&)(_A1, _A2, _A3, _A4...)>
228 {
229     typedef _Rp result_type;
230 };
231 
232 template <class _Rp, class _A1, class _A2, class _A3, class ..._A4>
233 struct __weak_result_type<_Rp (*)(_A1, _A2, _A3, _A4...)>
234 {
235     typedef _Rp result_type;
236 };
237 
238 template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
239 struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...)>
240 {
241     typedef _Rp result_type;
242 };
243 
244 template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
245 struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const>
246 {
247     typedef _Rp result_type;
248 };
249 
250 template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
251 struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) volatile>
252 {
253     typedef _Rp result_type;
254 };
255 
256 template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
257 struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile>
258 {
259     typedef _Rp result_type;
260 };
261 
262 template <class _Tp, class ..._Args>
263 struct __invoke_return
264 {
265     typedef decltype(_VSTD::__invoke(declval<_Tp>(), declval<_Args>()...)) type;
266 };
267 
268 #else // defined(_LIBCPP_CXX03_LANG)
269 
270 template <class _Ret, class _T1, bool _IsFunc, bool _IsBase>
271 struct __enable_invoke_imp;
272 
273 template <class _Ret, class _T1>
274 struct __enable_invoke_imp<_Ret, _T1, true, true> {
275     typedef _Ret _Bullet1;
276     typedef _Bullet1 type;
277 };
278 
279 template <class _Ret, class _T1>
280 struct __enable_invoke_imp<_Ret, _T1, true, false>  {
281     typedef _Ret _Bullet2;
282     typedef _Bullet2 type;
283 };
284 
285 template <class _Ret, class _T1>
286 struct __enable_invoke_imp<_Ret, _T1, false, true>  {
287     typedef typename add_lvalue_reference<
288                 typename __apply_cv<_T1, _Ret>::type
289             >::type _Bullet3;
290     typedef _Bullet3 type;
291 };
292 
293 template <class _Ret, class _T1>
294 struct __enable_invoke_imp<_Ret, _T1, false, false>  {
295     typedef typename add_lvalue_reference<
296                 typename __apply_cv<decltype(*declval<_T1>()), _Ret>::type
297             >::type _Bullet4;
298     typedef _Bullet4 type;
299 };
300 
301 template <class _Ret, class _T1>
302 struct __enable_invoke_imp<_Ret, _T1*, false, false>  {
303     typedef typename add_lvalue_reference<
304                 typename __apply_cv<_T1, _Ret>::type
305             >::type _Bullet4;
306     typedef _Bullet4  type;
307 };
308 
309 template <class _Fn, class _T1,
310           class _Traits = __member_pointer_traits<_Fn>,
311           class _Ret = typename _Traits::_ReturnType,
312           class _Class = typename _Traits::_ClassType>
313 struct __enable_invoke : __enable_invoke_imp<
314     _Ret, _T1,
315     is_member_function_pointer<_Fn>::value,
316     is_base_of<_Class, typename remove_reference<_T1>::type>::value>
317 {
318 };
319 
320 __nat __invoke(__any, ...);
321 
322 // first bullet
323 
324 template <class _Fn, class _T1>
325 inline _LIBCPP_INLINE_VISIBILITY
326 typename __enable_invoke<_Fn, _T1>::_Bullet1
327 __invoke(_Fn __f, _T1& __t1) {
328     return (__t1.*__f)();
329 }
330 
331 template <class _Fn, class _T1, class _A0>
332 inline _LIBCPP_INLINE_VISIBILITY
333 typename __enable_invoke<_Fn, _T1>::_Bullet1
334 __invoke(_Fn __f, _T1& __t1, _A0& __a0) {
335     return (__t1.*__f)(__a0);
336 }
337 
338 template <class _Fn, class _T1, class _A0, class _A1>
339 inline _LIBCPP_INLINE_VISIBILITY
340 typename __enable_invoke<_Fn, _T1>::_Bullet1
341 __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
342     return (__t1.*__f)(__a0, __a1);
343 }
344 
345 template <class _Fn, class _T1, class _A0, class _A1, class _A2>
346 inline _LIBCPP_INLINE_VISIBILITY
347 typename __enable_invoke<_Fn, _T1>::_Bullet1
348 __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
349     return (__t1.*__f)(__a0, __a1, __a2);
350 }
351 
352 template <class _Fn, class _T1>
353 inline _LIBCPP_INLINE_VISIBILITY
354 typename __enable_invoke<_Fn, _T1>::_Bullet2
355 __invoke(_Fn __f, _T1& __t1) {
356     return ((*__t1).*__f)();
357 }
358 
359 template <class _Fn, class _T1, class _A0>
360 inline _LIBCPP_INLINE_VISIBILITY
361 typename __enable_invoke<_Fn, _T1>::_Bullet2
362 __invoke(_Fn __f, _T1& __t1, _A0& __a0) {
363     return ((*__t1).*__f)(__a0);
364 }
365 
366 template <class _Fn, class _T1, class _A0, class _A1>
367 inline _LIBCPP_INLINE_VISIBILITY
368 typename __enable_invoke<_Fn, _T1>::_Bullet2
369 __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) {
370     return ((*__t1).*__f)(__a0, __a1);
371 }
372 
373 template <class _Fn, class _T1, class _A0, class _A1, class _A2>
374 inline _LIBCPP_INLINE_VISIBILITY
375 typename __enable_invoke<_Fn, _T1>::_Bullet2
376 __invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) {
377     return ((*__t1).*__f)(__a0, __a1, __a2);
378 }
379 
380 template <class _Fn, class _T1>
381 inline _LIBCPP_INLINE_VISIBILITY
382 typename __enable_invoke<_Fn, _T1>::_Bullet3
383 __invoke(_Fn __f, _T1& __t1) {
384     return __t1.*__f;
385 }
386 
387 template <class _Fn, class _T1>
388 inline _LIBCPP_INLINE_VISIBILITY
389 typename __enable_invoke<_Fn, _T1>::_Bullet4
390 __invoke(_Fn __f, _T1& __t1) {
391     return (*__t1).*__f;
392 }
393 
394 // fifth bullet
395 
396 template <class _Fp>
397 inline _LIBCPP_INLINE_VISIBILITY
398 decltype(declval<_Fp&>()())
399 __invoke(_Fp& __f)
400 {
401     return __f();
402 }
403 
404 template <class _Fp, class _A0>
405 inline _LIBCPP_INLINE_VISIBILITY
406 decltype(declval<_Fp&>()(declval<_A0&>()))
407 __invoke(_Fp& __f, _A0& __a0)
408 {
409     return __f(__a0);
410 }
411 
412 template <class _Fp, class _A0, class _A1>
413 inline _LIBCPP_INLINE_VISIBILITY
414 decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>()))
415 __invoke(_Fp& __f, _A0& __a0, _A1& __a1)
416 {
417     return __f(__a0, __a1);
418 }
419 
420 template <class _Fp, class _A0, class _A1, class _A2>
421 inline _LIBCPP_INLINE_VISIBILITY
422 decltype(declval<_Fp&>()(declval<_A0&>(), declval<_A1&>(), declval<_A2&>()))
423 __invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2)
424 {
425     return __f(__a0, __a1, __a2);
426 }
427 
428 template <class _Fp, bool = __has_result_type<__weak_result_type<_Fp> >::value>
429 struct __invoke_return
430 {
431     typedef typename __weak_result_type<_Fp>::result_type type;
432 };
433 
434 template <class _Fp>
435 struct __invoke_return<_Fp, false>
436 {
437     typedef decltype(_VSTD::__invoke(declval<_Fp&>())) type;
438 };
439 
440 template <class _Tp, class _A0>
441 struct __invoke_return0
442 {
443     typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>())) type;
444 };
445 
446 template <class _Rp, class _Tp, class _A0>
447 struct __invoke_return0<_Rp _Tp::*, _A0>
448 {
449     typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type;
450 };
451 
452 template <class _Tp, class _A0, class _A1>
453 struct __invoke_return1
454 {
455     typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(),
456                                                       declval<_A1&>())) type;
457 };
458 
459 template <class _Rp, class _Class, class _A0, class _A1>
460 struct __invoke_return1<_Rp _Class::*, _A0, _A1> {
461     typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type;
462 };
463 
464 template <class _Tp, class _A0, class _A1, class _A2>
465 struct __invoke_return2
466 {
467     typedef decltype(_VSTD::__invoke(declval<_Tp&>(), declval<_A0&>(),
468                                                       declval<_A1&>(),
469                                                       declval<_A2&>())) type;
470 };
471 
472 template <class _Ret, class _Class, class _A0, class _A1, class _A2>
473 struct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> {
474     typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type;
475 };
476 
477 #endif // !defined(_LIBCPP_CXX03_LANG)
478 
479 _LIBCPP_END_NAMESPACE_STD
480 
481 #endif // _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H
482