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, typename __uncvref<_Tp>::type>::value, 29 false_type, 30 is_bind_expression<typename __uncvref<_Tp>::type> 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, typename __uncvref<_Tp>::type>::value, 41 integral_constant<int, 0>, 42 is_placeholder<typename __uncvref<_Tp>::type> 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 268 #if _LIBCPP_STD_VER <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES) 269 : public __weak_result_type<typename decay<_Fp>::type> 270 #endif 271 { 272 protected: 273 typedef typename decay<_Fp>::type _Fd; 274 typedef tuple<typename decay<_BoundArgs>::type...> _Td; 275 private: 276 _Fd __f_; 277 _Td __bound_args_; 278 279 typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices; 280 public: 281 template <class _Gp, class ..._BA, 282 class = typename enable_if 283 < 284 is_constructible<_Fd, _Gp>::value && 285 !is_same<typename remove_reference<_Gp>::type, 286 __bind>::value 287 >::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)...) {} 292 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) 297 { 298 return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), 299 tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); 300 } 301 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 306 { 307 return _VSTD::__apply_functor(__f_, __bound_args_, __indices(), 308 tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...)); 309 } 310 }; 311 312 template<class _Fp, class ..._BoundArgs> 313 struct is_bind_expression<__bind<_Fp, _BoundArgs...> > : public true_type {}; 314 315 template<class _Rp, class _Fp, class ..._BoundArgs> 316 class __bind_r 317 : public __bind<_Fp, _BoundArgs...> 318 { 319 typedef __bind<_Fp, _BoundArgs...> base; 320 typedef typename base::_Fd _Fd; 321 typedef typename base::_Td _Td; 322 public: 323 typedef _Rp result_type; 324 325 326 template <class _Gp, class ..._BA, 327 class = typename enable_if 328 < 329 is_constructible<_Fd, _Gp>::value && 330 !is_same<typename remove_reference<_Gp>::type, 331 __bind_r>::value 332 >::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)...) {} 337 338 template <class ..._Args> 339 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 340 typename enable_if 341 < 342 is_convertible<typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type, 343 result_type>::value || is_void<_Rp>::value, 344 result_type 345 >::type 346 operator()(_Args&& ...__args) 347 { 348 typedef __invoke_void_return_wrapper<_Rp> _Invoker; 349 return _Invoker::__call(static_cast<base&>(*this), _VSTD::forward<_Args>(__args)...); 350 } 351 352 template <class ..._Args> 353 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 354 typename enable_if 355 < 356 is_convertible<typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type, 357 result_type>::value || is_void<_Rp>::value, 358 result_type 359 >::type 360 operator()(_Args&& ...__args) const 361 { 362 typedef __invoke_void_return_wrapper<_Rp> _Invoker; 363 return _Invoker::__call(static_cast<base const&>(*this), _VSTD::forward<_Args>(__args)...); 364 } 365 }; 366 367 template<class _Rp, class _Fp, class ..._BoundArgs> 368 struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {}; 369 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) 374 { 375 typedef __bind<_Fp, _BoundArgs...> type; 376 return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); 377 } 378 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) 383 { 384 typedef __bind_r<_Rp, _Fp, _BoundArgs...> type; 385 return type(_VSTD::forward<_Fp>(__f), _VSTD::forward<_BoundArgs>(__bound_args)...); 386 } 387 388 #endif // _LIBCPP_CXX03_LANG 389 390 _LIBCPP_END_NAMESPACE_STD 391 392 #endif // _LIBCPP___FUNCTIONAL_BIND_H 393