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/invoke.h>
16#include <__functional/unary_function.h>
17#include <__type_traits/integral_constant.h>
18#include <__type_traits/is_same.h>
19#include <__utility/declval.h>
20
21#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22#  pragma GCC system_header
23#endif
24
25_LIBCPP_BEGIN_NAMESPACE_STD
26
27template <class _Tp>
28struct __has_result_type
29{
30private:
31    template <class _Up> static false_type __test(...);
32    template <class _Up> static true_type __test(typename _Up::result_type* = 0);
33public:
34    static const bool value = decltype(__test<_Tp>(0))::value;
35};
36
37// __weak_result_type
38
39template <class _Tp>
40struct __derives_from_unary_function
41{
42private:
43    struct __two {char __lx; char __lxx;};
44    static __two __test(...);
45    template <class _Ap, class _Rp>
46        static __unary_function<_Ap, _Rp>
47        __test(const volatile __unary_function<_Ap, _Rp>*);
48
49public:
50    static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value;
51    typedef decltype(__test((_Tp*)0)) type;
52};
53
54template <class _Tp>
55struct __derives_from_binary_function
56{
57private:
58    struct __two {char __lx; char __lxx;};
59    static __two __test(...);
60    template <class _A1, class _A2, class _Rp>
61        static __binary_function<_A1, _A2, _Rp>
62        __test(const volatile __binary_function<_A1, _A2, _Rp>*);
63
64public:
65    static const bool value = !is_same<decltype(__test((_Tp*)0)), __two>::value;
66    typedef decltype(__test((_Tp*)0)) type;
67};
68
69template <class _Tp, bool = __derives_from_unary_function<_Tp>::value>
70struct __maybe_derive_from_unary_function  // bool is true
71    : public __derives_from_unary_function<_Tp>::type
72{
73};
74
75template <class _Tp>
76struct __maybe_derive_from_unary_function<_Tp, false>
77{
78};
79
80template <class _Tp, bool = __derives_from_binary_function<_Tp>::value>
81struct __maybe_derive_from_binary_function  // bool is true
82    : public __derives_from_binary_function<_Tp>::type
83{
84};
85
86template <class _Tp>
87struct __maybe_derive_from_binary_function<_Tp, false>
88{
89};
90
91template <class _Tp, bool = __has_result_type<_Tp>::value>
92struct __weak_result_type_imp // bool is true
93    : public __maybe_derive_from_unary_function<_Tp>,
94      public __maybe_derive_from_binary_function<_Tp>
95{
96#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
97    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = typename _Tp::result_type;
98#endif
99};
100
101template <class _Tp>
102struct __weak_result_type_imp<_Tp, false>
103    : public __maybe_derive_from_unary_function<_Tp>,
104      public __maybe_derive_from_binary_function<_Tp>
105{
106};
107
108template <class _Tp>
109struct __weak_result_type
110    : public __weak_result_type_imp<_Tp>
111{
112};
113
114// 0 argument case
115
116template <class _Rp>
117struct __weak_result_type<_Rp ()>
118{
119#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
120    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
121#endif
122};
123
124template <class _Rp>
125struct __weak_result_type<_Rp (&)()>
126{
127#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
128    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
129#endif
130};
131
132template <class _Rp>
133struct __weak_result_type<_Rp (*)()>
134{
135#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
136    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
137#endif
138};
139
140// 1 argument case
141
142template <class _Rp, class _A1>
143struct __weak_result_type<_Rp (_A1)>
144    : public __unary_function<_A1, _Rp>
145{
146};
147
148template <class _Rp, class _A1>
149struct __weak_result_type<_Rp (&)(_A1)>
150    : public __unary_function<_A1, _Rp>
151{
152};
153
154template <class _Rp, class _A1>
155struct __weak_result_type<_Rp (*)(_A1)>
156    : public __unary_function<_A1, _Rp>
157{
158};
159
160template <class _Rp, class _Cp>
161struct __weak_result_type<_Rp (_Cp::*)()>
162    : public __unary_function<_Cp*, _Rp>
163{
164};
165
166template <class _Rp, class _Cp>
167struct __weak_result_type<_Rp (_Cp::*)() const>
168    : public __unary_function<const _Cp*, _Rp>
169{
170};
171
172template <class _Rp, class _Cp>
173struct __weak_result_type<_Rp (_Cp::*)() volatile>
174    : public __unary_function<volatile _Cp*, _Rp>
175{
176};
177
178template <class _Rp, class _Cp>
179struct __weak_result_type<_Rp (_Cp::*)() const volatile>
180    : public __unary_function<const volatile _Cp*, _Rp>
181{
182};
183
184// 2 argument case
185
186template <class _Rp, class _A1, class _A2>
187struct __weak_result_type<_Rp (_A1, _A2)>
188    : public __binary_function<_A1, _A2, _Rp>
189{
190};
191
192template <class _Rp, class _A1, class _A2>
193struct __weak_result_type<_Rp (*)(_A1, _A2)>
194    : public __binary_function<_A1, _A2, _Rp>
195{
196};
197
198template <class _Rp, class _A1, class _A2>
199struct __weak_result_type<_Rp (&)(_A1, _A2)>
200    : public __binary_function<_A1, _A2, _Rp>
201{
202};
203
204template <class _Rp, class _Cp, class _A1>
205struct __weak_result_type<_Rp (_Cp::*)(_A1)>
206    : public __binary_function<_Cp*, _A1, _Rp>
207{
208};
209
210template <class _Rp, class _Cp, class _A1>
211struct __weak_result_type<_Rp (_Cp::*)(_A1) const>
212    : public __binary_function<const _Cp*, _A1, _Rp>
213{
214};
215
216template <class _Rp, class _Cp, class _A1>
217struct __weak_result_type<_Rp (_Cp::*)(_A1) volatile>
218    : public __binary_function<volatile _Cp*, _A1, _Rp>
219{
220};
221
222template <class _Rp, class _Cp, class _A1>
223struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile>
224    : public __binary_function<const volatile _Cp*, _A1, _Rp>
225{
226};
227
228// 3 or more arguments
229
230template <class _Rp, class _A1, class _A2, class _A3, class ..._A4>
231struct __weak_result_type<_Rp (_A1, _A2, _A3, _A4...)>
232{
233#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
234    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
235#endif
236};
237
238template <class _Rp, class _A1, class _A2, class _A3, class ..._A4>
239struct __weak_result_type<_Rp (&)(_A1, _A2, _A3, _A4...)>
240{
241#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
242    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
243#endif
244};
245
246template <class _Rp, class _A1, class _A2, class _A3, class ..._A4>
247struct __weak_result_type<_Rp (*)(_A1, _A2, _A3, _A4...)>
248{
249#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
250    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
251#endif
252};
253
254template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
255struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...)>
256{
257#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
258    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
259#endif
260};
261
262template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
263struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const>
264{
265#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
266    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
267#endif
268};
269
270template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
271struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) volatile>
272{
273#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
274    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
275#endif
276};
277
278template <class _Rp, class _Cp, class _A1, class _A2, class ..._A3>
279struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile>
280{
281#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
282    using result_type _LIBCPP_NODEBUG _LIBCPP_DEPRECATED_IN_CXX17 = _Rp;
283#endif
284};
285
286template <class _Tp, class ..._Args>
287struct __invoke_return
288{
289    typedef decltype(_VSTD::__invoke(std::declval<_Tp>(), std::declval<_Args>()...)) type;
290};
291
292_LIBCPP_END_NAMESPACE_STD
293
294#endif // _LIBCPP___FUNCTIONAL_WEAK_RESULT_TYPE_H
295