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