common_tuple.hpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_UTILITY_COMMON_TUPLE_HPP
  14. #define RANGES_V3_UTILITY_COMMON_TUPLE_HPP
  15. #include <utility>
  16. #include <meta/meta.hpp>
  17. #include <concepts/concepts.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/detail/adl_get.hpp>
  20. #include <range/v3/functional/bind.hpp>
  21. #include <range/v3/functional/reference_wrapper.hpp>
  22. #include <range/v3/utility/common_type.hpp>
  23. #include <range/v3/utility/tuple_algorithm.hpp>
  24. #include <range/v3/detail/prologue.hpp>
  25. namespace ranges
  26. {
  27. /// \cond
  28. namespace detail
  29. {
  30. template<typename... Us, typename Tup, std::size_t... Is>
  31. std::tuple<Us...> to_std_tuple(Tup && tup, meta::index_sequence<Is...>)
  32. {
  33. return std::tuple<Us...>{adl_get<Is>(static_cast<Tup &&>(tup))...};
  34. }
  35. #ifdef RANGES_WORKAROUND_MSVC_786312
  36. template<std::size_t, typename...>
  37. struct args_;
  38. template<typename, typename>
  39. inline constexpr bool argstructible = false;
  40. template<std::size_t N, typename... Ts, typename... Us>
  41. inline constexpr bool argstructible<args_<N, Ts...>, args_<N, Us...>> =
  42. (META_IS_CONSTRUCTIBLE(Ts, Us) && ...);
  43. template<typename, typename>
  44. inline constexpr bool argsignable = false;
  45. template<std::size_t N, typename... Ts, typename... Us>
  46. inline constexpr bool argsignable<args_<N, Ts...>, args_<N, Us...>> =
  47. (std::is_assignable_v<Ts &, Us> && ...);
  48. #endif // RANGES_WORKAROUND_MSVC_786312
  49. template<std::size_t N, typename... Ts>
  50. struct args_
  51. {
  52. template<typename... Us>
  53. args_(args_<N, Us...>, meta::if_c<
  54. #ifdef RANGES_WORKAROUND_MSVC_786312
  55. argstructible<args_, args_<N, Us...>>
  56. #else // ^^^ workaround / no workaround vvv
  57. meta::and_c<META_IS_CONSTRUCTIBLE(Ts,
  58. Us)...>::value
  59. #endif // RANGES_WORKAROUND_MSVC_786312
  60. > * = nullptr)
  61. {}
  62. template<typename... Us>
  63. meta::if_c<
  64. #ifdef RANGES_WORKAROUND_MSVC_786312
  65. argsignable<args_, args_<N, Us...>>,
  66. #else // ^^^ workaround / no workaround vvv
  67. meta::and_c<std::is_assignable<Ts &, Us>::value...>::value,
  68. #endif // RANGES_WORKAROUND_MSVC_786312
  69. args_ &>
  70. operator=(args_<N, Us...>)
  71. {
  72. return *this;
  73. }
  74. };
  75. template<typename... Ts>
  76. using args = args_<sizeof...(Ts), Ts...>;
  77. template<typename... Ts>
  78. using rargs = args_<sizeof...(Ts), Ts &...>;
  79. } // namespace detail
  80. /// \endcond
  81. template<typename... Ts>
  82. struct common_tuple : _tuple_wrapper_::forward_tuple_interface<std::tuple<Ts...>>
  83. {
  84. private:
  85. template<typename That, std::size_t... Is>
  86. common_tuple(That && that, meta::index_sequence<Is...>)
  87. : common_tuple::forward_tuple_interface{
  88. detail::adl_get<Is>(static_cast<That &&>(that))...}
  89. {}
  90. struct element_assign_
  91. {
  92. template<typename T, typename U>
  93. int operator()(T & t, U && u) const
  94. {
  95. t = static_cast<U &&>(u);
  96. return 0;
  97. }
  98. };
  99. public:
  100. // Construction
  101. CPP_member
  102. CPP_ctor(common_tuple)()( //
  103. noexcept( //
  104. meta::and_c<std::is_nothrow_default_constructible<Ts>::value...>::value)
  105. requires default_constructible<std::tuple<Ts...>>)
  106. : common_tuple::forward_tuple_interface{}
  107. {}
  108. template(typename... Us)(
  109. requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
  110. explicit common_tuple(Us &&... us) //
  111. noexcept(meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value)
  112. : common_tuple::forward_tuple_interface{static_cast<Us &&>(us)...}
  113. {}
  114. template(typename... Us)(
  115. requires constructible_from<detail::args<Ts...>, detail::rargs<Us...>>)
  116. common_tuple(std::tuple<Us...> & that) //
  117. noexcept(
  118. meta::and_c<std::is_nothrow_constructible<Ts, Us &>::value...>::value) //
  119. : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
  120. {}
  121. template(typename... Us)(
  122. requires constructible_from<detail::args<Ts...>, detail::rargs<Us const...>>)
  123. common_tuple(std::tuple<Us...> const & that) //
  124. noexcept(meta::and_c<
  125. std::is_nothrow_constructible<Ts, Us const &>::value...>::value) //
  126. : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
  127. {}
  128. template(typename... Us)(
  129. requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
  130. common_tuple(std::tuple<Us...> && that) //
  131. noexcept(
  132. meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value) //
  133. : common_tuple(std::move(that), meta::make_index_sequence<sizeof...(Ts)>{})
  134. {}
  135. template(typename... Us)(
  136. requires constructible_from<detail::args<Ts...>, detail::rargs<Us...>>)
  137. common_tuple(common_tuple<Us...> & that) //
  138. noexcept(
  139. meta::and_c<std::is_nothrow_constructible<Ts, Us &>::value...>::value) //
  140. : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
  141. {}
  142. template(typename... Us)(
  143. requires constructible_from<detail::args<Ts...>, detail::rargs<Us const...>>)
  144. common_tuple(common_tuple<Us...> const & that) //
  145. noexcept(meta::and_c<
  146. std::is_nothrow_constructible<Ts, Us const &>::value...>::value) //
  147. : common_tuple(that, meta::make_index_sequence<sizeof...(Ts)>{})
  148. {}
  149. template(typename... Us)(
  150. requires constructible_from<detail::args<Ts...>, detail::args<Us...>>)
  151. common_tuple(common_tuple<Us...> && that) //
  152. noexcept(
  153. meta::and_c<std::is_nothrow_constructible<Ts, Us>::value...>::value) //
  154. : common_tuple(std::move(that), meta::make_index_sequence<sizeof...(Ts)>{})
  155. {}
  156. std::tuple<Ts...> & base() noexcept
  157. {
  158. return *this;
  159. }
  160. std::tuple<Ts...> const & base() const noexcept
  161. {
  162. return *this;
  163. }
  164. // Assignment
  165. template(typename... Us)(
  166. requires std::is_assignable<detail::args<Ts...> &,
  167. detail::rargs<Us...>>::value) //
  168. common_tuple & operator=(std::tuple<Us...> & that) noexcept(
  169. meta::and_c<std::is_nothrow_assignable<Ts &, Us &>::value...>::value)
  170. {
  171. (void)tuple_transform(base(), that, element_assign_{});
  172. return *this;
  173. }
  174. template(typename... Us)(
  175. requires std::is_assignable<detail::args<Ts...> &,
  176. detail::rargs<Us const...>>::value) //
  177. common_tuple & operator=(std::tuple<Us...> const & that) noexcept(
  178. meta::and_c<std::is_nothrow_assignable<Ts &, Us const &>::value...>::value)
  179. {
  180. (void)tuple_transform(base(), that, element_assign_{});
  181. return *this;
  182. }
  183. template(typename... Us)(
  184. requires std::is_assignable<detail::args<Ts...> &,
  185. detail::args<Us...>>::value) //
  186. common_tuple & operator=(std::tuple<Us...> && that) noexcept(
  187. meta::and_c<std::is_nothrow_assignable<Ts &, Us>::value...>::value)
  188. {
  189. (void)tuple_transform(base(), std::move(that), element_assign_{});
  190. return *this;
  191. }
  192. template(typename... Us)(
  193. requires std::is_assignable<detail::args<Ts const...> &,
  194. detail::rargs<Us...>>::value)
  195. common_tuple const & operator=(std::tuple<Us...> & that) const noexcept(
  196. meta::and_c<std::is_nothrow_assignable<Ts const &, Us &>::value...>::value)
  197. {
  198. (void)tuple_transform(base(), that, element_assign_{});
  199. return *this;
  200. }
  201. template(typename... Us)(
  202. requires std::is_assignable<detail::args<Ts const...> &,
  203. detail::rargs<Us const...>>::value)
  204. common_tuple const & operator=(std::tuple<Us...> const & that) const
  205. noexcept(meta::and_c<
  206. std::is_nothrow_assignable<Ts const &, Us const &>::value...>::value)
  207. {
  208. (void)tuple_transform(base(), that, element_assign_{});
  209. return *this;
  210. }
  211. template(typename... Us)(
  212. requires std::is_assignable<detail::args<Ts const...> &,
  213. detail::args<Us...>>::value)
  214. common_tuple const & operator=(std::tuple<Us...> && that) const noexcept(
  215. meta::and_c<std::is_nothrow_assignable<Ts const &, Us &&>::value...>::value)
  216. {
  217. (void)tuple_transform(base(), std::move(that), element_assign_{});
  218. return *this;
  219. }
  220. // Conversion
  221. template(typename... Us)(
  222. requires constructible_from<detail::args<Us...>, detail::rargs<Ts...>>)
  223. operator std::tuple<Us...>() & noexcept(
  224. meta::and_c<std::is_nothrow_constructible<Us, Ts &>::value...>::value)
  225. {
  226. return detail::to_std_tuple<Us...>(
  227. *this, meta::make_index_sequence<sizeof...(Ts)>{});
  228. }
  229. template(typename... Us)(
  230. requires constructible_from<detail::args<Us...>,
  231. detail::rargs<Ts const...>>)
  232. operator std::tuple<Us...>() const & noexcept(
  233. meta::and_c<std::is_nothrow_constructible<Us, Ts const &>::value...>::value)
  234. {
  235. return detail::to_std_tuple<Us...>(
  236. *this, meta::make_index_sequence<sizeof...(Ts)>{});
  237. }
  238. template(typename... Us)(
  239. requires constructible_from<detail::args<Us...>, detail::args<Ts...>>)
  240. operator std::tuple<Us...>() &&
  241. noexcept(meta::and_c<std::is_nothrow_constructible<Us, Ts>::value...>::value)
  242. {
  243. return detail::to_std_tuple<Us...>(
  244. std::move(*this), meta::make_index_sequence<sizeof...(Ts)>{});
  245. }
  246. };
  247. // Logical operators
  248. #define LOGICAL_OP(OP, CONCEPT) \
  249. template(typename... Ts, typename... Us)( \
  250. requires and_v<CONCEPT<Ts, Us>...>) \
  251. bool operator OP(common_tuple<Ts...> const & a, common_tuple<Us...> const & b) \
  252. { \
  253. return a.base() OP b.base(); \
  254. } \
  255. template(typename... Ts, typename... Us)( \
  256. requires and_v<CONCEPT<Ts, Us>...>) \
  257. bool operator OP(std::tuple<Ts...> const & a, common_tuple<Us...> const & b) \
  258. { \
  259. return a OP b.base(); \
  260. } \
  261. template(typename... Ts, typename... Us)( \
  262. requires and_v<CONCEPT<Ts, Us>...>) \
  263. bool operator OP(common_tuple<Ts...> const & a, std::tuple<Us...> const & b) \
  264. { \
  265. return a.base() OP b; \
  266. } \
  267. /**/
  268. LOGICAL_OP(==, equality_comparable_with)
  269. LOGICAL_OP(!=, equality_comparable_with)
  270. LOGICAL_OP(<, totally_ordered_with)
  271. LOGICAL_OP(<=, totally_ordered_with)
  272. LOGICAL_OP(>, totally_ordered_with)
  273. LOGICAL_OP(>=, totally_ordered_with)
  274. #undef LOGICAL_OP
  275. struct make_common_tuple_fn
  276. {
  277. template<typename... Args>
  278. common_tuple<bind_element_t<Args>...> operator()(Args &&... args) const noexcept(
  279. meta::and_c<std::is_nothrow_constructible<
  280. bind_element_t<Args>, unwrap_reference_t<Args>>::value...>::value)
  281. {
  282. return common_tuple<bind_element_t<Args>...>{
  283. unwrap_reference(static_cast<Args &&>(args))...};
  284. }
  285. };
  286. /// \ingroup group-utility
  287. /// \sa `make_common_tuple_fn`
  288. RANGES_INLINE_VARIABLE(make_common_tuple_fn, make_common_tuple)
  289. template<typename F, typename S>
  290. struct common_pair : std::pair<F, S>
  291. {
  292. private:
  293. std::pair<F, S> const & base() const noexcept
  294. {
  295. return *this;
  296. }
  297. public:
  298. // Construction
  299. CPP_member
  300. CPP_ctor(common_pair)()( //
  301. noexcept(std::is_nothrow_default_constructible<F>::value && //
  302. std::is_nothrow_default_constructible<S>::value) //
  303. requires default_constructible<F> && default_constructible<S>)
  304. : std::pair<F, S>{}
  305. {}
  306. template(typename F2, typename S2)(
  307. requires constructible_from<F, F2> AND constructible_from<S, S2>)
  308. common_pair(F2 && f2, S2 && s2) //
  309. noexcept(std::is_nothrow_constructible<F, F2>::value &&
  310. std::is_nothrow_constructible<S, S2>::value) //
  311. : std::pair<F, S>{static_cast<F2 &&>(f2), static_cast<S2 &&>(s2)}
  312. {}
  313. template(typename F2, typename S2)(
  314. requires constructible_from<F, F2 &> AND constructible_from<S, S2 &>)
  315. common_pair(std::pair<F2, S2> & that) //
  316. noexcept(std::is_nothrow_constructible<F, F2 &>::value &&
  317. std::is_nothrow_constructible<S, S2 &>::value) //
  318. : std::pair<F, S>{that.first, that.second}
  319. {}
  320. template(typename F2, typename S2)(
  321. requires constructible_from<F, F2 const &> AND
  322. constructible_from<S, S2 const &>)
  323. common_pair(std::pair<F2, S2> const & that) //
  324. noexcept(std::is_nothrow_constructible<F, F2 const &>::value &&
  325. std::is_nothrow_constructible<S, S2 const &>::value) //
  326. : std::pair<F, S>{that.first, that.second}
  327. {}
  328. template(typename F2, typename S2)(
  329. requires constructible_from<F, F2> AND constructible_from<S, S2>)
  330. common_pair(std::pair<F2, S2> && that) //
  331. noexcept(std::is_nothrow_constructible<F, F2>::value &&
  332. std::is_nothrow_constructible<S, S2>::value) //
  333. : std::pair<F, S>{std::forward<F2>(that.first), std::forward<S2>(that.second)}
  334. {}
  335. // Conversion
  336. template(typename F2, typename S2)(
  337. requires constructible_from<F2, F &> AND constructible_from<S2, S &>)
  338. operator std::pair<F2, S2>() & //
  339. noexcept(std::is_nothrow_constructible<F2, F &>::value &&
  340. std::is_nothrow_constructible<S2, S &>::value)
  341. {
  342. return {this->first, this->second};
  343. }
  344. template(typename F2, typename S2)(
  345. requires constructible_from<F2, F const &> AND
  346. constructible_from<S2, S const &>)
  347. operator std::pair<F2, S2>() const & //
  348. noexcept(std::is_nothrow_constructible<F2, F const &>::value &&
  349. std::is_nothrow_constructible<S2, S const &>::value)
  350. {
  351. return {this->first, this->second};
  352. }
  353. template(typename F2, typename S2)(
  354. requires constructible_from<F2, F> AND constructible_from<S2, S>)
  355. operator std::pair<F2, S2>() &&
  356. noexcept(std::is_nothrow_constructible<F2, F>::value &&
  357. std::is_nothrow_constructible<S2, S>::value)
  358. {
  359. return {std::forward<F>(this->first), std::forward<S>(this->second)};
  360. }
  361. // Assignment
  362. template(typename F2, typename S2)(
  363. requires assignable_from<F &, F2 &> AND assignable_from<S &, S2 &>)
  364. common_pair & operator=(std::pair<F2, S2> & that) //
  365. noexcept(std::is_nothrow_assignable<F &, F2 &>::value &&
  366. std::is_nothrow_assignable<S &, S2 &>::value)
  367. {
  368. this->first = that.first;
  369. this->second = that.second;
  370. return *this;
  371. }
  372. template(typename F2, typename S2)(
  373. requires assignable_from<F &, F2 const &> AND
  374. assignable_from<S &, S2 const &>)
  375. common_pair & operator=(std::pair<F2, S2> const & that) //
  376. noexcept(std::is_nothrow_assignable<F &, F2 const &>::value &&
  377. std::is_nothrow_assignable<S &, S2 const &>::value)
  378. {
  379. this->first = that.first;
  380. this->second = that.second;
  381. return *this;
  382. }
  383. template(typename F2, typename S2)(
  384. requires assignable_from<F &, F2> AND assignable_from<S &, S2>)
  385. common_pair & operator=(std::pair<F2, S2> && that) //
  386. noexcept(std::is_nothrow_assignable<F &, F2>::value &&
  387. std::is_nothrow_assignable<S &, S2>::value)
  388. {
  389. this->first = static_cast<F2 &&>(that.first);
  390. this->second = static_cast<S2 &&>(that.second);
  391. return *this;
  392. }
  393. template(typename F2, typename S2)(
  394. requires assignable_from<F const &, F2 &> AND
  395. assignable_from<S const &, S2 &>)
  396. common_pair const & operator=(std::pair<F2, S2> & that) const //
  397. noexcept(std::is_nothrow_assignable<F const &, F2 &>::value &&
  398. std::is_nothrow_assignable<S const &, S2 &>::value)
  399. {
  400. this->first = that.first;
  401. this->second = that.second;
  402. return *this;
  403. }
  404. template(typename F2, typename S2)(
  405. requires assignable_from<F const &, F2 const &> AND
  406. assignable_from<S const &, S2 const &>)
  407. common_pair const & operator=(std::pair<F2, S2> const & that) const //
  408. noexcept(std::is_nothrow_assignable<F const &, F2 const &>::value &&
  409. std::is_nothrow_assignable<S const &, S2 const &>::value)
  410. {
  411. this->first = that.first;
  412. this->second = that.second;
  413. return *this;
  414. }
  415. template(typename F2, typename S2)(
  416. requires assignable_from<F const &, F2> AND assignable_from<S const &, S2>)
  417. common_pair const & operator=(std::pair<F2, S2> && that) const //
  418. noexcept(std::is_nothrow_assignable<F const &, F2 &&>::value &&
  419. std::is_nothrow_assignable<S const &, S2 &&>::value)
  420. {
  421. this->first = static_cast<F2 &&>(that.first);
  422. this->second = static_cast<S2 &&>(that.second);
  423. return *this;
  424. }
  425. };
  426. // Logical operators
  427. template(typename F1, typename S1, typename F2, typename S2)(
  428. requires equality_comparable_with<F1, F2> AND equality_comparable_with<S1, S2>)
  429. bool operator==(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b)
  430. {
  431. return a.first == b.first && a.second == b.second;
  432. }
  433. template(typename F1, typename S1, typename F2, typename S2)(
  434. requires equality_comparable_with<F1, F2> AND equality_comparable_with<S1, S2>)
  435. bool operator==(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b)
  436. {
  437. return a.first == b.first && a.second == b.second;
  438. }
  439. template(typename F1, typename S1, typename F2, typename S2)(
  440. requires equality_comparable_with<F1, F2> AND equality_comparable_with<S1, S2>)
  441. bool operator==(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b)
  442. {
  443. return a.first == b.first && a.second == b.second;
  444. }
  445. template(typename F1, typename S1, typename F2, typename S2)(
  446. requires totally_ordered_with<F1, F2> AND totally_ordered_with<S1, S2>)
  447. bool operator<(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b)
  448. {
  449. return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
  450. }
  451. template(typename F1, typename S1, typename F2, typename S2)(
  452. requires totally_ordered_with<F1, F2> AND totally_ordered_with<S1, S2>)
  453. bool operator<(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b)
  454. {
  455. return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
  456. }
  457. template(typename F1, typename S1, typename F2, typename S2)(
  458. requires totally_ordered_with<F1, F2> AND totally_ordered_with<S1, S2>)
  459. bool operator<(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b)
  460. {
  461. return a.first < b.first || (!(b.first < a.first) && a.second < b.second);
  462. }
  463. #define LOGICAL_OP(OP, CONCEPT, RET) \
  464. template(typename F1, typename S1, typename F2, typename S2)( \
  465. requires CONCEPT<F1, F2> AND CONCEPT<S1, S2>) \
  466. bool operator OP(common_pair<F1, S1> const & a, common_pair<F2, S2> const & b) \
  467. { \
  468. return RET; \
  469. } \
  470. template(typename F1, typename S1, typename F2, typename S2)( \
  471. requires CONCEPT<F1, F2> AND CONCEPT<S1, S2>) \
  472. bool operator OP(std::pair<F1, S1> const & a, common_pair<F2, S2> const & b) \
  473. { \
  474. return RET; \
  475. } \
  476. template(typename F1, typename S1, typename F2, typename S2)( \
  477. requires CONCEPT<F1, F2> AND CONCEPT<S1, S2>) \
  478. bool operator OP(common_pair<F1, S1> const & a, std::pair<F2, S2> const & b) \
  479. { \
  480. return RET; \
  481. } \
  482. /**/
  483. LOGICAL_OP(!=, equality_comparable_with, !(a == b))
  484. LOGICAL_OP(<=, totally_ordered_with, !(b < a))
  485. LOGICAL_OP(>, totally_ordered_with, (b < a))
  486. LOGICAL_OP(>=, totally_ordered_with, !(a < b))
  487. #undef LOGICAL_OP
  488. struct make_common_pair_fn
  489. {
  490. template<typename First, typename Second, typename F = bind_element_t<First>,
  491. typename S = bind_element_t<Second>>
  492. common_pair<F, S> operator()(First && f, Second && s) const //
  493. noexcept(std::is_nothrow_constructible<F, unwrap_reference_t<First>>::value &&
  494. std::is_nothrow_constructible<F, unwrap_reference_t<Second>>::value)
  495. {
  496. return {unwrap_reference(static_cast<First &&>(f)),
  497. unwrap_reference(static_cast<Second &&>(s))};
  498. }
  499. };
  500. /// \ingroup group-utility
  501. /// \sa `make_common_pair_fn`
  502. RANGES_INLINE_VARIABLE(make_common_pair_fn, make_common_pair)
  503. /// \cond
  504. namespace detail
  505. {
  506. template<typename, typename, typename, typename = void>
  507. struct common_type_tuple_like
  508. {};
  509. template<template<typename...> class T0, typename... Ts,
  510. template<typename...> class T1, typename... Us, typename TupleLike>
  511. struct common_type_tuple_like<T0<Ts...>, T1<Us...>, TupleLike,
  512. meta::if_c<sizeof...(Ts) == sizeof...(Us)>>
  513. : meta::lazy::let<
  514. meta::lazy::invoke<TupleLike, meta::lazy::_t<common_type<Ts, Us>>...>>
  515. {};
  516. template<typename, typename, typename, typename = void>
  517. struct common_ref_tuple_like
  518. {};
  519. template<template<typename...> class T0, typename... Ts,
  520. template<typename...> class T1, typename... Us, typename TupleLike>
  521. struct common_ref_tuple_like<T0<Ts...>, T1<Us...>, TupleLike,
  522. meta::if_c<sizeof...(Ts) == sizeof...(Us)>>
  523. : meta::lazy::let<meta::lazy::invoke<
  524. TupleLike, meta::lazy::_t<common_reference<Ts, Us>>...>>
  525. {};
  526. } // namespace detail
  527. /// \endcond
  528. } // namespace ranges
  529. /// \cond
  530. namespace concepts
  531. {
  532. // common_type for pairs
  533. template<typename F1, typename S1, typename F2, typename S2>
  534. struct common_type<std::pair<F1, S1>, ranges::common_pair<F2, S2>>
  535. : ranges::detail::common_type_tuple_like<
  536. std::pair<F1, S1>, ranges::common_pair<F2, S2>,
  537. meta::quote<ranges::common_pair>>
  538. {};
  539. template<typename F1, typename S1, typename F2, typename S2>
  540. struct common_type<ranges::common_pair<F1, S1>, std::pair<F2, S2>>
  541. : ranges::detail::common_type_tuple_like<
  542. ranges::common_pair<F1, S1>, std::pair<F2, S2>,
  543. meta::quote<ranges::common_pair>>
  544. {};
  545. template<typename F1, typename S1, typename F2, typename S2>
  546. struct common_type<ranges::common_pair<F1, S1>, ranges::common_pair<F2, S2>>
  547. : ranges::detail::common_type_tuple_like<ranges::common_pair<F1, S1>,
  548. ranges::common_pair<F2, S2>,
  549. meta::quote<ranges::common_pair>>
  550. {};
  551. // common_type for tuples
  552. template<typename... Ts, typename... Us>
  553. struct common_type<ranges::common_tuple<Ts...>, std::tuple<Us...>>
  554. : ranges::detail::common_type_tuple_like<
  555. ranges::common_tuple<Ts...>, std::tuple<Us...>,
  556. meta::quote<ranges::common_tuple>>
  557. {};
  558. template<typename... Ts, typename... Us>
  559. struct common_type<std::tuple<Ts...>, ranges::common_tuple<Us...>>
  560. : ranges::detail::common_type_tuple_like<
  561. std::tuple<Ts...>, ranges::common_tuple<Us...>,
  562. meta::quote<ranges::common_tuple>>
  563. {};
  564. template<typename... Ts, typename... Us>
  565. struct common_type<ranges::common_tuple<Ts...>, ranges::common_tuple<Us...>>
  566. : ranges::detail::common_type_tuple_like<ranges::common_tuple<Ts...>,
  567. ranges::common_tuple<Us...>,
  568. meta::quote<ranges::common_tuple>>
  569. {};
  570. // common reference for pairs
  571. template<typename F1, typename S1, typename F2, typename S2,
  572. template<typename> class Qual1, template<typename> class Qual2>
  573. struct basic_common_reference<ranges::common_pair<F1, S1>, std::pair<F2, S2>, Qual1,
  574. Qual2>
  575. : ranges::detail::common_ref_tuple_like<
  576. ranges::common_pair<Qual1<F1>, Qual1<S1>>, std::pair<Qual2<F2>, Qual2<S2>>,
  577. meta::quote<ranges::common_pair>>
  578. {};
  579. template<typename F1, typename S1, typename F2, typename S2,
  580. template<typename> class Qual1, template<typename> class Qual2>
  581. struct basic_common_reference<std::pair<F1, S1>, ranges::common_pair<F2, S2>, Qual1,
  582. Qual2>
  583. : ranges::detail::common_ref_tuple_like<
  584. std::pair<Qual1<F1>, Qual1<S1>>, ranges::common_pair<Qual2<F2>, Qual2<S2>>,
  585. meta::quote<ranges::common_pair>>
  586. {};
  587. template<typename F1, typename S1, typename F2, typename S2,
  588. template<typename> class Qual1, template<typename> class Qual2>
  589. struct basic_common_reference<ranges::common_pair<F1, S1>,
  590. ranges::common_pair<F2, S2>, Qual1, Qual2>
  591. : ranges::detail::common_ref_tuple_like<ranges::common_pair<Qual1<F1>, Qual1<S1>>,
  592. ranges::common_pair<Qual2<F2>, Qual2<S2>>,
  593. meta::quote<ranges::common_pair>>
  594. {};
  595. // common reference for tuples
  596. template<typename... Ts, typename... Us, template<typename> class Qual1,
  597. template<typename> class Qual2>
  598. struct basic_common_reference<ranges::common_tuple<Ts...>, std::tuple<Us...>, Qual1,
  599. Qual2>
  600. : ranges::detail::common_ref_tuple_like<
  601. ranges::common_tuple<Qual1<Ts>...>, std::tuple<Qual2<Us>...>,
  602. meta::quote<ranges::common_tuple>>
  603. {};
  604. template<typename... Ts, typename... Us, template<typename> class Qual1,
  605. template<typename> class Qual2>
  606. struct basic_common_reference<std::tuple<Ts...>, ranges::common_tuple<Us...>, Qual1,
  607. Qual2>
  608. : ranges::detail::common_ref_tuple_like<
  609. std::tuple<Qual1<Ts>...>, ranges::common_tuple<Qual2<Us>...>,
  610. meta::quote<ranges::common_tuple>>
  611. {};
  612. template<typename... Ts, typename... Us, template<typename> class Qual1,
  613. template<typename> class Qual2>
  614. struct basic_common_reference<ranges::common_tuple<Ts...>,
  615. ranges::common_tuple<Us...>, Qual1, Qual2>
  616. : ranges::detail::common_ref_tuple_like<ranges::common_tuple<Qual1<Ts>...>,
  617. ranges::common_tuple<Qual2<Us>...>,
  618. meta::quote<ranges::common_tuple>>
  619. {};
  620. } // namespace concepts
  621. /// \endcond
  622. RANGES_DIAGNOSTIC_PUSH
  623. RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
  624. RANGES_BEGIN_NAMESPACE_STD
  625. template<typename First, typename Second>
  626. struct tuple_size<::ranges::common_pair<First, Second>>
  627. : std::integral_constant<size_t, 2>
  628. {};
  629. template<typename First, typename Second>
  630. struct tuple_element<0, ::ranges::common_pair<First, Second>>
  631. {
  632. using type = First;
  633. };
  634. template<typename First, typename Second>
  635. struct tuple_element<1, ::ranges::common_pair<First, Second>>
  636. {
  637. using type = Second;
  638. };
  639. template<typename... Ts>
  640. struct tuple_size<::ranges::common_tuple<Ts...>>
  641. : std::integral_constant<size_t, sizeof...(Ts)>
  642. {};
  643. template<size_t N, typename... Ts>
  644. struct tuple_element<N, ::ranges::common_tuple<Ts...>>
  645. : tuple_element<N, tuple<Ts...>>
  646. {};
  647. #if RANGES_CXX_VER > RANGES_CXX_STD_17
  648. RANGES_BEGIN_NAMESPACE_VERSION
  649. template<typename...>
  650. struct common_type;
  651. // common_type for pairs
  652. template<typename F1, typename S1, typename F2, typename S2>
  653. struct common_type<std::pair<F1, S1>, ::ranges::common_pair<F2, S2>>
  654. : ::ranges::detail::common_type_tuple_like<
  655. std::pair<F1, S1>, ::ranges::common_pair<F2, S2>,
  656. ::meta::quote<::ranges::common_pair>>
  657. {};
  658. template<typename F1, typename S1, typename F2, typename S2>
  659. struct common_type<::ranges::common_pair<F1, S1>, std::pair<F2, S2>>
  660. : ::ranges::detail::common_type_tuple_like<
  661. ::ranges::common_pair<F1, S1>, std::pair<F2, S2>,
  662. ::meta::quote<::ranges::common_pair>>
  663. {};
  664. template<typename F1, typename S1, typename F2, typename S2>
  665. struct common_type<::ranges::common_pair<F1, S1>, ::ranges::common_pair<F2, S2>>
  666. : ::ranges::detail::common_type_tuple_like<::ranges::common_pair<F1, S1>,
  667. ::ranges::common_pair<F2, S2>,
  668. ::meta::quote<::ranges::common_pair>>
  669. {};
  670. // common_type for tuples
  671. template<typename... Ts, typename... Us>
  672. struct common_type<::ranges::common_tuple<Ts...>, std::tuple<Us...>>
  673. : ::ranges::detail::common_type_tuple_like<
  674. ::ranges::common_tuple<Ts...>, std::tuple<Us...>,
  675. ::meta::quote<::ranges::common_tuple>>
  676. {};
  677. template<typename... Ts, typename... Us>
  678. struct common_type<std::tuple<Ts...>, ::ranges::common_tuple<Us...>>
  679. : ::ranges::detail::common_type_tuple_like<
  680. std::tuple<Ts...>, ::ranges::common_tuple<Us...>,
  681. ::meta::quote<::ranges::common_tuple>>
  682. {};
  683. template<typename... Ts, typename... Us>
  684. struct common_type<::ranges::common_tuple<Ts...>, ::ranges::common_tuple<Us...>>
  685. : ::ranges::detail::common_type_tuple_like<::ranges::common_tuple<Ts...>,
  686. ::ranges::common_tuple<Us...>,
  687. ::meta::quote<::ranges::common_tuple>>
  688. {};
  689. template<typename, typename, template<typename> class, template<typename> class>
  690. struct basic_common_reference;
  691. // common reference for pairs
  692. template<typename F1, typename S1, typename F2, typename S2,
  693. template<typename> class Qual1, template<typename> class Qual2>
  694. struct basic_common_reference<::ranges::common_pair<F1, S1>, std::pair<F2, S2>, Qual1,
  695. Qual2>
  696. : ::ranges::detail::common_ref_tuple_like<
  697. ::ranges::common_pair<Qual1<F1>, Qual1<S1>>, std::pair<Qual2<F2>, Qual2<S2>>,
  698. ::meta::quote<::ranges::common_pair>>
  699. {};
  700. template<typename F1, typename S1, typename F2, typename S2,
  701. template<typename> class Qual1, template<typename> class Qual2>
  702. struct basic_common_reference<std::pair<F1, S1>, ::ranges::common_pair<F2, S2>, Qual1,
  703. Qual2>
  704. : ::ranges::detail::common_ref_tuple_like<
  705. std::pair<Qual1<F1>, Qual1<S1>>, ::ranges::common_pair<Qual2<F2>, Qual2<S2>>,
  706. ::meta::quote<::ranges::common_pair>>
  707. {};
  708. template<typename F1, typename S1, typename F2, typename S2,
  709. template<typename> class Qual1, template<typename> class Qual2>
  710. struct basic_common_reference<::ranges::common_pair<F1, S1>,
  711. ::ranges::common_pair<F2, S2>, Qual1, Qual2>
  712. : ::ranges::detail::common_ref_tuple_like<::ranges::common_pair<Qual1<F1>, Qual1<S1>>,
  713. ::ranges::common_pair<Qual2<F2>, Qual2<S2>>,
  714. ::meta::quote<::ranges::common_pair>>
  715. {};
  716. // common reference for tuples
  717. template<typename... Ts, typename... Us, template<typename> class Qual1,
  718. template<typename> class Qual2>
  719. struct basic_common_reference<::ranges::common_tuple<Ts...>, std::tuple<Us...>, Qual1,
  720. Qual2>
  721. : ::ranges::detail::common_ref_tuple_like<
  722. ::ranges::common_tuple<Qual1<Ts>...>, std::tuple<Qual2<Us>...>,
  723. ::meta::quote<::ranges::common_tuple>>
  724. {};
  725. template<typename... Ts, typename... Us, template<typename> class Qual1,
  726. template<typename> class Qual2>
  727. struct basic_common_reference<std::tuple<Ts...>, ::ranges::common_tuple<Us...>, Qual1,
  728. Qual2>
  729. : ::ranges::detail::common_ref_tuple_like<
  730. std::tuple<Qual1<Ts>...>, ::ranges::common_tuple<Qual2<Us>...>,
  731. ::meta::quote<::ranges::common_tuple>>
  732. {};
  733. template<typename... Ts, typename... Us, template<typename> class Qual1,
  734. template<typename> class Qual2>
  735. struct basic_common_reference<::ranges::common_tuple<Ts...>,
  736. ::ranges::common_tuple<Us...>, Qual1, Qual2>
  737. : ::ranges::detail::common_ref_tuple_like<::ranges::common_tuple<Qual1<Ts>...>,
  738. ::ranges::common_tuple<Qual2<Us>...>,
  739. ::meta::quote<::ranges::common_tuple>>
  740. {};
  741. RANGES_END_NAMESPACE_VERSION
  742. #endif // RANGES_CXX_VER > RANGES_CXX_STD_17
  743. RANGES_END_NAMESPACE_STD
  744. RANGES_DIAGNOSTIC_POP
  745. #include <range/v3/detail/epilogue.hpp>
  746. #endif