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