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_BIND_H |
11 | #define _LIBCPP___FUNCTIONAL_BIND_H |
12 | |
13 | #include <__config> |
14 | #include <__functional/invoke.h> |
15 | #include <__functional/weak_result_type.h> |
16 | #include <__fwd/functional.h> |
17 | #include <__type_traits/decay.h> |
18 | #include <__type_traits/is_reference_wrapper.h> |
19 | #include <__type_traits/is_void.h> |
20 | #include <cstddef> |
21 | #include <tuple> |
22 | |
23 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
24 | # pragma GCC system_header |
25 | #endif |
26 | |
27 | _LIBCPP_BEGIN_NAMESPACE_STD |
28 | |
29 | template <class _Tp> |
30 | struct is_bind_expression |
31 | : _If< _IsSame<_Tp, __remove_cvref_t<_Tp> >::value, false_type, is_bind_expression<__remove_cvref_t<_Tp> > > {}; |
32 | |
33 | #if _LIBCPP_STD_VER >= 17 |
34 | template <class _Tp> |
35 | inline constexpr bool is_bind_expression_v = is_bind_expression<_Tp>::value; |
36 | #endif |
37 | |
38 | template <class _Tp> |
39 | struct is_placeholder |
40 | : _If< _IsSame<_Tp, __remove_cvref_t<_Tp> >::value, |
41 | integral_constant<int, 0>, |
42 | is_placeholder<__remove_cvref_t<_Tp> > > {}; |
43 | |
44 | #if _LIBCPP_STD_VER >= 17 |
45 | template <class _Tp> |
46 | inline constexpr int is_placeholder_v = is_placeholder<_Tp>::value; |
47 | #endif |
48 | |
49 | namespace placeholders { |
50 | |
51 | template <int _Np> |
52 | struct __ph {}; |
53 | |
54 | // C++17 recommends that we implement placeholders as `inline constexpr`, but allows |
55 | // implementing them as `extern <implementation-defined>`. Libc++ implements them as |
56 | // `extern const` in all standard modes to avoid an ABI break in C++03: making them |
57 | // `inline constexpr` requires removing their definition in the shared library to |
58 | // avoid ODR violations, which is an ABI break. |
59 | // |
60 | // In practice, since placeholders are empty, `extern const` is almost impossible |
61 | // to distinguish from `inline constexpr` from a usage stand point. |
62 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<1> _1; |
63 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<2> _2; |
64 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<3> _3; |
65 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<4> _4; |
66 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<5> _5; |
67 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<6> _6; |
68 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<7> _7; |
69 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<8> _8; |
70 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<9> _9; |
71 | _LIBCPP_EXPORTED_FROM_ABI extern const __ph<10> _10; |
72 | |
73 | } // namespace placeholders |
74 | |
75 | template <int _Np> |
76 | struct is_placeholder<placeholders::__ph<_Np> > : public integral_constant<int, _Np> {}; |
77 | |
78 | #ifndef _LIBCPP_CXX03_LANG |
79 | |
80 | template <class _Tp, class _Uj> |
81 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __mu(reference_wrapper<_Tp> __t, _Uj&) { |
82 | return __t.get(); |
83 | } |
84 | |
85 | template <class _Ti, class... _Uj, size_t... _Indx> |
86 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<_Ti&, _Uj...>::type |
87 | __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) { |
88 | return __ti(std::forward<_Uj>(std::get<_Indx>(__uj))...); |
89 | } |
90 | |
91 | template <class _Ti, class... _Uj, __enable_if_t<is_bind_expression<_Ti>::value, int> = 0> |
92 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<_Ti&, _Uj...>::type |
93 | __mu(_Ti& __ti, tuple<_Uj...>& __uj) { |
94 | typedef typename __make_tuple_indices<sizeof...(_Uj)>::type __indices; |
95 | return std::__mu_expand(__ti, __uj, __indices()); |
96 | } |
97 | |
98 | template <bool _IsPh, class _Ti, class _Uj> |
99 | struct __mu_return2 {}; |
100 | |
101 | template <class _Ti, class _Uj> |
102 | struct __mu_return2<true, _Ti, _Uj> { |
103 | typedef typename tuple_element<is_placeholder<_Ti>::value - 1, _Uj>::type type; |
104 | }; |
105 | |
106 | template <class _Ti, class _Uj, __enable_if_t<0 < is_placeholder<_Ti>::value, int> = 0> |
107 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 |
108 | typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type |
109 | __mu(_Ti&, _Uj& __uj) { |
110 | const size_t __indx = is_placeholder<_Ti>::value - 1; |
111 | return std::forward<typename tuple_element<__indx, _Uj>::type>(std::get<__indx>(__uj)); |
112 | } |
113 | |
114 | template <class _Ti, |
115 | class _Uj, |
116 | __enable_if_t<!is_bind_expression<_Ti>::value && is_placeholder<_Ti>::value == 0 && |
117 | !__is_reference_wrapper<_Ti>::value, |
118 | int> = 0> |
119 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Ti& __mu(_Ti& __ti, _Uj&) { |
120 | return __ti; |
121 | } |
122 | |
123 | template <class _Ti, bool _IsReferenceWrapper, bool _IsBindEx, bool _IsPh, class _TupleUj> |
124 | struct __mu_return_impl; |
125 | |
126 | template <bool _Invokable, class _Ti, class... _Uj> |
127 | struct __mu_return_invokable // false |
128 | { |
129 | typedef __nat type; |
130 | }; |
131 | |
132 | template <class _Ti, class... _Uj> |
133 | struct __mu_return_invokable<true, _Ti, _Uj...> { |
134 | typedef typename __invoke_of<_Ti&, _Uj...>::type type; |
135 | }; |
136 | |
137 | template <class _Ti, class... _Uj> |
138 | struct __mu_return_impl<_Ti, false, true, false, tuple<_Uj...> > |
139 | : public __mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...> {}; |
140 | |
141 | template <class _Ti, class _TupleUj> |
142 | struct __mu_return_impl<_Ti, false, false, true, _TupleUj> { |
143 | typedef typename tuple_element<is_placeholder<_Ti>::value - 1, _TupleUj>::type&& type; |
144 | }; |
145 | |
146 | template <class _Ti, class _TupleUj> |
147 | struct __mu_return_impl<_Ti, true, false, false, _TupleUj> { |
148 | typedef typename _Ti::type& type; |
149 | }; |
150 | |
151 | template <class _Ti, class _TupleUj> |
152 | struct __mu_return_impl<_Ti, false, false, false, _TupleUj> { |
153 | typedef _Ti& type; |
154 | }; |
155 | |
156 | template <class _Ti, class _TupleUj> |
157 | struct __mu_return |
158 | : public __mu_return_impl< |
159 | _Ti, |
160 | __is_reference_wrapper<_Ti>::value, |
161 | is_bind_expression<_Ti>::value, |
162 | 0 < is_placeholder<_Ti>::value && is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value, |
163 | _TupleUj> {}; |
164 | |
165 | template <class _Fp, class _BoundArgs, class _TupleUj> |
166 | struct __is_valid_bind_return { |
167 | static const bool value = false; |
168 | }; |
169 | |
170 | template <class _Fp, class... _BoundArgs, class _TupleUj> |
171 | struct __is_valid_bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj> { |
172 | static const bool value = __invokable<_Fp, typename __mu_return<_BoundArgs, _TupleUj>::type...>::value; |
173 | }; |
174 | |
175 | template <class _Fp, class... _BoundArgs, class _TupleUj> |
176 | struct __is_valid_bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj> { |
177 | static const bool value = __invokable<_Fp, typename __mu_return<const _BoundArgs, _TupleUj>::type...>::value; |
178 | }; |
179 | |
180 | template <class _Fp, class _BoundArgs, class _TupleUj, bool = __is_valid_bind_return<_Fp, _BoundArgs, _TupleUj>::value> |
181 | struct __bind_return; |
182 | |
183 | template <class _Fp, class... _BoundArgs, class _TupleUj> |
184 | struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true> { |
185 | typedef typename __invoke_of< _Fp&, typename __mu_return< _BoundArgs, _TupleUj >::type... >::type type; |
186 | }; |
187 | |
188 | template <class _Fp, class... _BoundArgs, class _TupleUj> |
189 | struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> { |
190 | typedef typename __invoke_of< _Fp&, typename __mu_return< const _BoundArgs, _TupleUj >::type... >::type type; |
191 | }; |
192 | |
193 | template <class _Fp, class _BoundArgs, size_t... _Indx, class _Args> |
194 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fp, _BoundArgs, _Args>::type |
195 | __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _Args&& __args) { |
196 | return std::__invoke(__f, std::__mu(std::get<_Indx>(__bound_args), __args)...); |
197 | } |
198 | |
199 | template <class _Fp, class... _BoundArgs> |
200 | class __bind : public __weak_result_type<__decay_t<_Fp> > { |
201 | protected: |
202 | using _Fd = __decay_t<_Fp>; |
203 | typedef tuple<__decay_t<_BoundArgs>...> _Td; |
204 | |
205 | private: |
206 | _Fd __f_; |
207 | _Td __bound_args_; |
208 | |
209 | typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices; |
210 | |
211 | public: |
212 | template < |
213 | class _Gp, |
214 | class... _BA, |
215 | __enable_if_t<is_constructible<_Fd, _Gp>::value && !is_same<__libcpp_remove_reference_t<_Gp>, __bind>::value, |
216 | int> = 0> |
217 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bind(_Gp&& __f, _BA&&... __bound_args) |
218 | : __f_(std::forward<_Gp>(__f)), __bound_args_(std::forward<_BA>(__bound_args)...) {} |
219 | |
220 | template <class... _Args> |
221 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type |
222 | operator()(_Args&&... __args) { |
223 | return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); |
224 | } |
225 | |
226 | template <class... _Args> |
227 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 |
228 | typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type |
229 | operator()(_Args&&... __args) const { |
230 | return std::__apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(std::forward<_Args>(__args)...)); |
231 | } |
232 | }; |
233 | |
234 | template <class _Fp, class... _BoundArgs> |
235 | struct is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; |
236 | |
237 | template <class _Rp, class _Fp, class... _BoundArgs> |
238 | class __bind_r : public __bind<_Fp, _BoundArgs...> { |
239 | typedef __bind<_Fp, _BoundArgs...> base; |
240 | typedef typename base::_Fd _Fd; |
241 | typedef typename base::_Td _Td; |
242 | |
243 | public: |
244 | typedef _Rp result_type; |
245 | |
246 | template < |
247 | class _Gp, |
248 | class... _BA, |
249 | __enable_if_t<is_constructible<_Fd, _Gp>::value && !is_same<__libcpp_remove_reference_t<_Gp>, __bind_r>::value, |
250 | int> = 0> |
251 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bind_r(_Gp&& __f, _BA&&... __bound_args) |
252 | : base(std::forward<_Gp>(__f), std::forward<_BA>(__bound_args)...) {} |
253 | |
254 | template < |
255 | class... _Args, |
256 | __enable_if_t<is_convertible<typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type, result_type>::value || |
257 | is_void<_Rp>::value, |
258 | int> = 0> |
259 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 result_type operator()(_Args&&... __args) { |
260 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; |
261 | return _Invoker::__call(static_cast<base&>(*this), std::forward<_Args>(__args)...); |
262 | } |
263 | |
264 | template <class... _Args, |
265 | __enable_if_t<is_convertible<typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type, |
266 | result_type>::value || |
267 | is_void<_Rp>::value, |
268 | int> = 0> |
269 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 result_type operator()(_Args&&... __args) const { |
270 | typedef __invoke_void_return_wrapper<_Rp> _Invoker; |
271 | return _Invoker::__call(static_cast<base const&>(*this), std::forward<_Args>(__args)...); |
272 | } |
273 | }; |
274 | |
275 | template <class _Rp, class _Fp, class... _BoundArgs> |
276 | struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; |
277 | |
278 | template <class _Fp, class... _BoundArgs> |
279 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind<_Fp, _BoundArgs...> |
280 | bind(_Fp&& __f, _BoundArgs&&... __bound_args) { |
281 | typedef __bind<_Fp, _BoundArgs...> type; |
282 | return type(std::forward<_Fp>(__f), std::forward<_BoundArgs>(__bound_args)...); |
283 | } |
284 | |
285 | template <class _Rp, class _Fp, class... _BoundArgs> |
286 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind_r<_Rp, _Fp, _BoundArgs...> |
287 | bind(_Fp&& __f, _BoundArgs&&... __bound_args) { |
288 | typedef __bind_r<_Rp, _Fp, _BoundArgs...> type; |
289 | return type(std::forward<_Fp>(__f), std::forward<_BoundArgs>(__bound_args)...); |
290 | } |
291 | |
292 | #endif // _LIBCPP_CXX03_LANG |
293 | |
294 | _LIBCPP_END_NAMESPACE_STD |
295 | |
296 | #endif // _LIBCPP___FUNCTIONAL_BIND_H |
297 | |