2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___FUNCTIONAL_BIND_H
11 #define _LIBCPP___FUNCTIONAL_BIND_H
14 #include <__functional/invoke.h>
15 #include <__functional/weak_result_type.h>
18 #include <type_traits>
20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21 #pragma GCC system_header
24 _LIBCPP_BEGIN_NAMESPACE_STD
27 struct is_bind_expression
: _If
<
28 _IsSame
<_Tp
, typename __uncvref
<_Tp
>::type
>::value
,
30 is_bind_expression
<typename __uncvref
<_Tp
>::type
>
33 #if _LIBCPP_STD_VER > 14
35 inline constexpr size_t is_bind_expression_v
= is_bind_expression
<_Tp
>::value
;
39 struct is_placeholder
: _If
<
40 _IsSame
<_Tp
, typename __uncvref
<_Tp
>::type
>::value
,
41 integral_constant
<int, 0>,
42 is_placeholder
<typename __uncvref
<_Tp
>::type
>
45 #if _LIBCPP_STD_VER > 14
47 inline constexpr size_t is_placeholder_v
= is_placeholder
<_Tp
>::value
;
50 namespace placeholders
53 template <int _Np
> struct __ph
{};
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
;
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)
79 } // namespace placeholders
82 struct is_placeholder
<placeholders::__ph
<_Np
> >
83 : public integral_constant
<int, _Np
> {};
86 #ifndef _LIBCPP_CXX03_LANG
88 template <class _Tp
, class _Uj
>
89 inline _LIBCPP_INLINE_VISIBILITY
91 __mu(reference_wrapper
<_Tp
> __t
, _Uj
&)
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
...>)
101 return __ti(_VSTD::forward
<_Uj
>(_VSTD::get
<_Indx
>(__uj
))...);
104 template <class _Ti
, class ..._Uj
>
105 inline _LIBCPP_INLINE_VISIBILITY
106 typename __enable_if_t
108 is_bind_expression
<_Ti
>::value
,
109 __invoke_of
<_Ti
&, _Uj
...>
111 __mu(_Ti
& __ti
, tuple
<_Uj
...>& __uj
)
113 typedef typename __make_tuple_indices
<sizeof...(_Uj
)>::type __indices
;
114 return _VSTD::__mu_expand(__ti
, __uj
, __indices());
117 template <bool IsPh
, class _Ti
, class _Uj
>
118 struct __mu_return2
{};
120 template <class _Ti
, class _Uj
>
121 struct __mu_return2
<true, _Ti
, _Uj
>
123 typedef typename tuple_element
<is_placeholder
<_Ti
>::value
- 1, _Uj
>::type type
;
126 template <class _Ti
, class _Uj
>
127 inline _LIBCPP_INLINE_VISIBILITY
130 0 < is_placeholder
<_Ti
>::value
,
131 typename __mu_return2
<0 < is_placeholder
<_Ti
>::value
, _Ti
, _Uj
>::type
133 __mu(_Ti
&, _Uj
& __uj
)
135 const size_t _Indx
= is_placeholder
<_Ti
>::value
- 1;
136 return _VSTD::forward
<typename tuple_element
<_Indx
, _Uj
>::type
>(_VSTD::get
<_Indx
>(__uj
));
139 template <class _Ti
, class _Uj
>
140 inline _LIBCPP_INLINE_VISIBILITY
143 !is_bind_expression
<_Ti
>::value
&&
144 is_placeholder
<_Ti
>::value
== 0 &&
145 !__is_reference_wrapper
<_Ti
>::value
,
148 __mu(_Ti
& __ti
, _Uj
&)
153 template <class _Ti
, bool IsReferenceWrapper
, bool IsBindEx
, bool IsPh
,
155 struct __mu_return_impl
;
157 template <bool _Invokable
, class _Ti
, class ..._Uj
>
158 struct __mu_return_invokable
// false
163 template <class _Ti
, class ..._Uj
>
164 struct __mu_return_invokable
<true, _Ti
, _Uj
...>
166 typedef typename __invoke_of
<_Ti
&, _Uj
...>::type type
;
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
...>
175 template <class _Ti
, class _TupleUj
>
176 struct __mu_return_impl
<_Ti
, false, false, true, _TupleUj
>
178 typedef typename tuple_element
<is_placeholder
<_Ti
>::value
- 1,
179 _TupleUj
>::type
&& type
;
182 template <class _Ti
, class _TupleUj
>
183 struct __mu_return_impl
<_Ti
, true, false, false, _TupleUj
>
185 typedef typename
_Ti::type
& type
;
188 template <class _Ti
, class _TupleUj
>
189 struct __mu_return_impl
<_Ti
, false, false, false, _TupleUj
>
194 template <class _Ti
, class _TupleUj
>
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
,
205 template <class _Fp
, class _BoundArgs
, class _TupleUj
>
206 struct __is_valid_bind_return
208 static const bool value
= false;
211 template <class _Fp
, class ..._BoundArgs
, class _TupleUj
>
212 struct __is_valid_bind_return
<_Fp
, tuple
<_BoundArgs
...>, _TupleUj
>
214 static const bool value
= __invokable
<_Fp
,
215 typename __mu_return
<_BoundArgs
, _TupleUj
>::type
...>::value
;
218 template <class _Fp
, class ..._BoundArgs
, class _TupleUj
>
219 struct __is_valid_bind_return
<_Fp
, const tuple
<_BoundArgs
...>, _TupleUj
>
221 static const bool value
= __invokable
<_Fp
,
222 typename __mu_return
<const _BoundArgs
, _TupleUj
>::type
...>::value
;
225 template <class _Fp
, class _BoundArgs
, class _TupleUj
,
226 bool = __is_valid_bind_return
<_Fp
, _BoundArgs
, _TupleUj
>::value
>
227 struct __bind_return
;
229 template <class _Fp
, class ..._BoundArgs
, class _TupleUj
>
230 struct __bind_return
<_Fp
, tuple
<_BoundArgs
...>, _TupleUj
, true>
232 typedef typename __invoke_of
243 template <class _Fp
, class ..._BoundArgs
, class _TupleUj
>
244 struct __bind_return
<_Fp
, const tuple
<_BoundArgs
...>, _TupleUj
, true>
246 typedef typename __invoke_of
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
...>,
263 return _VSTD::__invoke(__f
, _VSTD::__mu(_VSTD::get
<_Indx
>(__bound_args
), __args
)...);
266 template<class _Fp
, class ..._BoundArgs
>
268 #if _LIBCPP_STD_VER <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES)
269 : public __weak_result_type
<typename decay
<_Fp
>::type
>
273 typedef typename decay
<_Fp
>::type _Fd
;
274 typedef tuple
<typename decay
<_BoundArgs
>::type
...> _Td
;
279 typedef typename __make_tuple_indices
<sizeof...(_BoundArgs
)>::type __indices
;
281 template <class _Gp
, class ..._BA
,
282 class = typename enable_if
284 is_constructible
<_Fd
, _Gp
>::value
&&
285 !is_same
<typename remove_reference
<_Gp
>::type
,
288 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
289 explicit __bind(_Gp
&& __f
, _BA
&& ...__bound_args
)
290 : __f_(_VSTD::forward
<_Gp
>(__f
)),
291 __bound_args_(_VSTD::forward
<_BA
>(__bound_args
)...) {}
293 template <class ..._Args
>
294 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
295 typename __bind_return
<_Fd
, _Td
, tuple
<_Args
&&...> >::type
296 operator()(_Args
&& ...__args
)
298 return _VSTD::__apply_functor(__f_
, __bound_args_
, __indices(),
299 tuple
<_Args
&&...>(_VSTD::forward
<_Args
>(__args
)...));
302 template <class ..._Args
>
303 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
304 typename __bind_return
<const _Fd
, const _Td
, tuple
<_Args
&&...> >::type
305 operator()(_Args
&& ...__args
) const
307 return _VSTD::__apply_functor(__f_
, __bound_args_
, __indices(),
308 tuple
<_Args
&&...>(_VSTD::forward
<_Args
>(__args
)...));
312 template<class _Fp
, class ..._BoundArgs
>
313 struct is_bind_expression
<__bind
<_Fp
, _BoundArgs
...> > : public true_type
{};
315 template<class _Rp
, class _Fp
, class ..._BoundArgs
>
317 : public __bind
<_Fp
, _BoundArgs
...>
319 typedef __bind
<_Fp
, _BoundArgs
...> base
;
320 typedef typename
base::_Fd _Fd
;
321 typedef typename
base::_Td _Td
;
323 typedef _Rp result_type
;
326 template <class _Gp
, class ..._BA
,
327 class = typename enable_if
329 is_constructible
<_Fd
, _Gp
>::value
&&
330 !is_same
<typename remove_reference
<_Gp
>::type
,
333 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
334 explicit __bind_r(_Gp
&& __f
, _BA
&& ...__bound_args
)
335 : base(_VSTD::forward
<_Gp
>(__f
),
336 _VSTD::forward
<_BA
>(__bound_args
)...) {}
338 template <class ..._Args
>
339 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
342 is_convertible
<typename __bind_return
<_Fd
, _Td
, tuple
<_Args
&&...> >::type
,
343 result_type
>::value
|| is_void
<_Rp
>::value
,
346 operator()(_Args
&& ...__args
)
348 typedef __invoke_void_return_wrapper
<_Rp
> _Invoker
;
349 return _Invoker::__call(static_cast<base
&>(*this), _VSTD::forward
<_Args
>(__args
)...);
352 template <class ..._Args
>
353 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
356 is_convertible
<typename __bind_return
<const _Fd
, const _Td
, tuple
<_Args
&&...> >::type
,
357 result_type
>::value
|| is_void
<_Rp
>::value
,
360 operator()(_Args
&& ...__args
) const
362 typedef __invoke_void_return_wrapper
<_Rp
> _Invoker
;
363 return _Invoker::__call(static_cast<base
const&>(*this), _VSTD::forward
<_Args
>(__args
)...);
367 template<class _Rp
, class _Fp
, class ..._BoundArgs
>
368 struct is_bind_expression
<__bind_r
<_Rp
, _Fp
, _BoundArgs
...> > : public true_type
{};
370 template<class _Fp
, class ..._BoundArgs
>
371 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
372 __bind
<_Fp
, _BoundArgs
...>
373 bind(_Fp
&& __f
, _BoundArgs
&&... __bound_args
)
375 typedef __bind
<_Fp
, _BoundArgs
...> type
;
376 return type(_VSTD::forward
<_Fp
>(__f
), _VSTD::forward
<_BoundArgs
>(__bound_args
)...);
379 template<class _Rp
, class _Fp
, class ..._BoundArgs
>
380 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
381 __bind_r
<_Rp
, _Fp
, _BoundArgs
...>
382 bind(_Fp
&& __f
, _BoundArgs
&&... __bound_args
)
384 typedef __bind_r
<_Rp
, _Fp
, _BoundArgs
...> type
;
385 return type(_VSTD::forward
<_Fp
>(__f
), _VSTD::forward
<_BoundArgs
>(__bound_args
)...);
388 #endif // _LIBCPP_CXX03_LANG
390 _LIBCPP_END_NAMESPACE_STD
392 #endif // _LIBCPP___FUNCTIONAL_BIND_H