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