xref: /freebsd/contrib/llvm-project/libcxx/include/__functional/bind.h (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
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 <cstddef>
17 #include <tuple>
18 #include <type_traits>
19 
20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21 #  pragma GCC system_header
22 #endif
23 
24 _LIBCPP_BEGIN_NAMESPACE_STD
25 
26 template<class _Tp>
27 struct is_bind_expression : _If<
28     _IsSame<_Tp, __remove_cvref_t<_Tp> >::value,
29     false_type,
30     is_bind_expression<__remove_cvref_t<_Tp> >
31 > {};
32 
33 #if _LIBCPP_STD_VER > 14
34 template <class _Tp>
35 inline constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value;
36 #endif
37 
38 template<class _Tp>
39 struct is_placeholder : _If<
40     _IsSame<_Tp, __remove_cvref_t<_Tp> >::value,
41     integral_constant<int, 0>,
42     is_placeholder<__remove_cvref_t<_Tp> >
43 > {};
44 
45 #if _LIBCPP_STD_VER > 14
46 template <class _Tp>
47 inline constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value;
48 #endif
49 
50 namespace placeholders
51 {
52 
53 template <int _Np> struct __ph {};
54 
55 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
56 _LIBCPP_FUNC_VIS extern const __ph<1>   _1;
57 _LIBCPP_FUNC_VIS extern const __ph<2>   _2;
58 _LIBCPP_FUNC_VIS extern const __ph<3>   _3;
59 _LIBCPP_FUNC_VIS extern const __ph<4>   _4;
60 _LIBCPP_FUNC_VIS extern const __ph<5>   _5;
61 _LIBCPP_FUNC_VIS extern const __ph<6>   _6;
62 _LIBCPP_FUNC_VIS extern const __ph<7>   _7;
63 _LIBCPP_FUNC_VIS extern const __ph<8>   _8;
64 _LIBCPP_FUNC_VIS extern const __ph<9>   _9;
65 _LIBCPP_FUNC_VIS extern const __ph<10> _10;
66 #else
67 /* inline */ constexpr __ph<1>   _1{};
68 /* inline */ constexpr __ph<2>   _2{};
69 /* inline */ constexpr __ph<3>   _3{};
70 /* inline */ constexpr __ph<4>   _4{};
71 /* inline */ constexpr __ph<5>   _5{};
72 /* inline */ constexpr __ph<6>   _6{};
73 /* inline */ constexpr __ph<7>   _7{};
74 /* inline */ constexpr __ph<8>   _8{};
75 /* inline */ constexpr __ph<9>   _9{};
76 /* inline */ constexpr __ph<10> _10{};
77 #endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
78 
79 } // namespace placeholders
80 
81 template<int _Np>
82 struct is_placeholder<placeholders::__ph<_Np> >
83     : public integral_constant<int, _Np> {};
84 
85 
86 #ifndef _LIBCPP_CXX03_LANG
87 
88 template <class _Tp, class _Uj>
89 inline _LIBCPP_INLINE_VISIBILITY
90 _Tp&
91 __mu(reference_wrapper<_Tp> __t, _Uj&)
92 {
93     return __t.get();
94 }
95 
96 template <class _Ti, class ..._Uj, size_t ..._Indx>
97 inline _LIBCPP_INLINE_VISIBILITY
98 typename __invoke_of<_Ti&, _Uj...>::type
99 __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>)
100 {
101     return __ti(_VSTD::forward<_Uj>(_VSTD::get<_Indx>(__uj))...);
102 }
103 
104 template <class _Ti, class ..._Uj>
105 inline _LIBCPP_INLINE_VISIBILITY
106 typename __enable_if_t
107 <
108     is_bind_expression<_Ti>::value,
109     __invoke_of<_Ti&, _Uj...>
110 >::type
111 __mu(_Ti& __ti, tuple<_Uj...>& __uj)
112 {
113     typedef typename __make_tuple_indices<sizeof...(_Uj)>::type __indices;
114     return _VSTD::__mu_expand(__ti, __uj, __indices());
115 }
116 
117 template <bool IsPh, class _Ti, class _Uj>
118 struct __mu_return2 {};
119 
120 template <class _Ti, class _Uj>
121 struct __mu_return2<true, _Ti, _Uj>
122 {
123     typedef typename tuple_element<is_placeholder<_Ti>::value - 1, _Uj>::type type;
124 };
125 
126 template <class _Ti, class _Uj>
127 inline _LIBCPP_INLINE_VISIBILITY
128 typename enable_if
129 <
130     0 < is_placeholder<_Ti>::value,
131     typename __mu_return2<0 < is_placeholder<_Ti>::value, _Ti, _Uj>::type
132 >::type
133 __mu(_Ti&, _Uj& __uj)
134 {
135     const size_t _Indx = is_placeholder<_Ti>::value - 1;
136     return _VSTD::forward<typename tuple_element<_Indx, _Uj>::type>(_VSTD::get<_Indx>(__uj));
137 }
138 
139 template <class _Ti, class _Uj>
140 inline _LIBCPP_INLINE_VISIBILITY
141 typename enable_if
142 <
143     !is_bind_expression<_Ti>::value &&
144     is_placeholder<_Ti>::value == 0 &&
145     !__is_reference_wrapper<_Ti>::value,
146     _Ti&
147 >::type
148 __mu(_Ti& __ti, _Uj&)
149 {
150     return __ti;
151 }
152 
153 template <class _Ti, bool IsReferenceWrapper, bool IsBindEx, bool IsPh,
154           class _TupleUj>
155 struct __mu_return_impl;
156 
157 template <bool _Invokable, class _Ti, class ..._Uj>
158 struct __mu_return_invokable  // false
159 {
160     typedef __nat type;
161 };
162 
163 template <class _Ti, class ..._Uj>
164 struct __mu_return_invokable<true, _Ti, _Uj...>
165 {
166     typedef typename __invoke_of<_Ti&, _Uj...>::type type;
167 };
168 
169 template <class _Ti, class ..._Uj>
170 struct __mu_return_impl<_Ti, false, true, false, tuple<_Uj...> >
171     : public __mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...>
172 {
173 };
174 
175 template <class _Ti, class _TupleUj>
176 struct __mu_return_impl<_Ti, false, false, true, _TupleUj>
177 {
178     typedef typename tuple_element<is_placeholder<_Ti>::value - 1,
179                                    _TupleUj>::type&& type;
180 };
181 
182 template <class _Ti, class _TupleUj>
183 struct __mu_return_impl<_Ti, true, false, false, _TupleUj>
184 {
185     typedef typename _Ti::type& type;
186 };
187 
188 template <class _Ti, class _TupleUj>
189 struct __mu_return_impl<_Ti, false, false, false, _TupleUj>
190 {
191     typedef _Ti& type;
192 };
193 
194 template <class _Ti, class _TupleUj>
195 struct __mu_return
196     : public __mu_return_impl<_Ti,
197                               __is_reference_wrapper<_Ti>::value,
198                               is_bind_expression<_Ti>::value,
199                               0 < is_placeholder<_Ti>::value &&
200                               is_placeholder<_Ti>::value <= tuple_size<_TupleUj>::value,
201                               _TupleUj>
202 {
203 };
204 
205 template <class _Fp, class _BoundArgs, class _TupleUj>
206 struct __is_valid_bind_return
207 {
208     static const bool value = false;
209 };
210 
211 template <class _Fp, class ..._BoundArgs, class _TupleUj>
212 struct __is_valid_bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj>
213 {
214     static const bool value = __invokable<_Fp,
215                     typename __mu_return<_BoundArgs, _TupleUj>::type...>::value;
216 };
217 
218 template <class _Fp, class ..._BoundArgs, class _TupleUj>
219 struct __is_valid_bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj>
220 {
221     static const bool value = __invokable<_Fp,
222                     typename __mu_return<const _BoundArgs, _TupleUj>::type...>::value;
223 };
224 
225 template <class _Fp, class _BoundArgs, class _TupleUj,
226           bool = __is_valid_bind_return<_Fp, _BoundArgs, _TupleUj>::value>
227 struct __bind_return;
228 
229 template <class _Fp, class ..._BoundArgs, class _TupleUj>
230 struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true>
231 {
232     typedef typename __invoke_of
233     <
234         _Fp&,
235         typename __mu_return
236         <
237             _BoundArgs,
238             _TupleUj
239         >::type...
240     >::type type;
241 };
242 
243 template <class _Fp, class ..._BoundArgs, class _TupleUj>
244 struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true>
245 {
246     typedef typename __invoke_of
247     <
248         _Fp&,
249         typename __mu_return
250         <
251             const _BoundArgs,
252             _TupleUj
253         >::type...
254     >::type type;
255 };
256 
257 template <class _Fp, class _BoundArgs, size_t ..._Indx, class _Args>
258 inline _LIBCPP_INLINE_VISIBILITY
259 typename __bind_return<_Fp, _BoundArgs, _Args>::type
260 __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>,
261                 _Args&& __args)
262 {
263     return _VSTD::__invoke(__f, _VSTD::__mu(_VSTD::get<_Indx>(__bound_args), __args)...);
264 }
265 
266 template<class _Fp, class ..._BoundArgs>
267 class __bind : public __weak_result_type<typename decay<_Fp>::type>
268 {
269 protected:
270     typedef typename decay<_Fp>::type _Fd;
271     typedef tuple<typename decay<_BoundArgs>::type...> _Td;
272 private:
273     _Fd __f_;
274     _Td __bound_args_;
275 
276     typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices;
277 public:
278     template <class _Gp, class ..._BA,
279               class = typename enable_if
280                                <
281                                   is_constructible<_Fd, _Gp>::value &&
282                                   !is_same<__libcpp_remove_reference_t<_Gp>,
283                                            __bind>::value
284                                >::type>
285       _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
286       explicit __bind(_Gp&& __f, _BA&& ...__bound_args)
287         : __f_(_VSTD::forward<_Gp>(__f)),
288           __bound_args_(_VSTD::forward<_BA>(__bound_args)...) {}
289 
290     template <class ..._Args>
291         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
292         typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
293         operator()(_Args&& ...__args)
294         {
295             return _VSTD::__apply_functor(__f_, __bound_args_, __indices(),
296                                   tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
297         }
298 
299     template <class ..._Args>
300         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
301         typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type
302         operator()(_Args&& ...__args) const
303         {
304             return _VSTD::__apply_functor(__f_, __bound_args_, __indices(),
305                                    tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
306         }
307 };
308 
309 template<class _Fp, class ..._BoundArgs>
310 struct is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {};
311 
312 template<class _Rp, class _Fp, class ..._BoundArgs>
313 class __bind_r
314     : public __bind<_Fp, _BoundArgs...>
315 {
316     typedef __bind<_Fp, _BoundArgs...> base;
317     typedef typename base::_Fd _Fd;
318     typedef typename base::_Td _Td;
319 public:
320     typedef _Rp result_type;
321 
322 
323     template <class _Gp, class ..._BA,
324               class = typename enable_if
325                                <
326                                   is_constructible<_Fd, _Gp>::value &&
327                                   !is_same<__libcpp_remove_reference_t<_Gp>,
328                                            __bind_r>::value
329                                >::type>
330       _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
331       explicit __bind_r(_Gp&& __f, _BA&& ...__bound_args)
332         : base(_VSTD::forward<_Gp>(__f),
333                _VSTD::forward<_BA>(__bound_args)...) {}
334 
335     template <class ..._Args>
336         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
337         typename enable_if
338         <
339             is_convertible<typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type,
340                            result_type>::value || is_void<_Rp>::value,
341             result_type
342         >::type
343         operator()(_Args&& ...__args)
344         {
345             typedef __invoke_void_return_wrapper<_Rp> _Invoker;
346             return _Invoker::__call(static_cast<base&>(*this), _VSTD::forward<_Args>(__args)...);
347         }
348 
349     template <class ..._Args>
350         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
351         typename enable_if
352         <
353             is_convertible<typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type,
354                            result_type>::value || is_void<_Rp>::value,
355             result_type
356         >::type
357         operator()(_Args&& ...__args) const
358         {
359             typedef __invoke_void_return_wrapper<_Rp> _Invoker;
360             return _Invoker::__call(static_cast<base const&>(*this), _VSTD::forward<_Args>(__args)...);
361         }
362 };
363 
364 template<class _Rp, class _Fp, class ..._BoundArgs>
365 struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {};
366 
367 template<class _Fp, class ..._BoundArgs>
368 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
369 __bind<_Fp, _BoundArgs...>
370 bind(_Fp&& __f, _BoundArgs&&... __bound_args)
371 {
372     typedef __bind<_Fp, _BoundArgs...> type;
373     return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...);
374 }
375 
376 template<class _Rp, class _Fp, class ..._BoundArgs>
377 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
378 __bind_r<_Rp, _Fp, _BoundArgs...>
379 bind(_Fp&& __f, _BoundArgs&&... __bound_args)
380 {
381     typedef __bind_r<_Rp, _Fp, _BoundArgs...> type;
382     return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...);
383 }
384 
385 #endif // _LIBCPP_CXX03_LANG
386 
387 _LIBCPP_END_NAMESPACE_STD
388 
389 #endif // _LIBCPP___FUNCTIONAL_BIND_H
390