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