bind.h 12 KB

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