You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

434 lines
16KB

  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_VIEW_ZIP_WITH_HPP
  14. #define RANGES_V3_VIEW_ZIP_WITH_HPP
  15. #include <limits>
  16. #include <tuple>
  17. #include <type_traits>
  18. #include <utility>
  19. #include <meta/meta.hpp>
  20. #include <range/v3/range_fwd.hpp>
  21. #include <range/v3/functional/bind_back.hpp>
  22. #include <range/v3/functional/indirect.hpp>
  23. #include <range/v3/functional/invoke.hpp>
  24. #include <range/v3/iterator/operations.hpp>
  25. #include <range/v3/range/access.hpp>
  26. #include <range/v3/range/concepts.hpp>
  27. #include <range/v3/range/traits.hpp>
  28. #include <range/v3/utility/common_type.hpp>
  29. #include <range/v3/utility/semiregular_box.hpp>
  30. #include <range/v3/utility/static_const.hpp>
  31. #include <range/v3/utility/tuple_algorithm.hpp>
  32. #include <range/v3/view/all.hpp>
  33. #include <range/v3/view/empty.hpp>
  34. #include <range/v3/view/facade.hpp>
  35. namespace ranges
  36. {
  37. /// \cond
  38. namespace detail
  39. {
  40. struct equal_to_
  41. {
  42. template<typename T, typename U>
  43. bool operator()(T const & t, U const & u) const
  44. {
  45. return static_cast<bool>(t == u);
  46. }
  47. };
  48. RANGES_INLINE_VARIABLE(equal_to_, equal_to)
  49. struct dec_
  50. {
  51. template<typename T>
  52. void operator()(T & t) const
  53. {
  54. --t;
  55. }
  56. };
  57. RANGES_INLINE_VARIABLE(dec_, dec)
  58. struct inc_
  59. {
  60. template<typename T>
  61. void operator()(T & t) const
  62. {
  63. ++t;
  64. }
  65. };
  66. RANGES_INLINE_VARIABLE(inc_, inc)
  67. struct _advance_
  68. {
  69. template<typename I, typename Diff>
  70. auto operator()(I & i, Diff n) const -> CPP_ret(void)( //
  71. requires input_or_output_iterator<I> && integer_like_<Diff>)
  72. {
  73. advance(i, static_cast<iter_difference_t<I>>(n));
  74. }
  75. };
  76. RANGES_INLINE_VARIABLE(_advance_, advance_)
  77. struct distance_to_
  78. {
  79. template<typename T>
  80. constexpr auto operator()(T const & t, T const & u) const -> decltype(u - t)
  81. {
  82. return u - t;
  83. }
  84. };
  85. RANGES_INLINE_VARIABLE(distance_to_, distance_to)
  86. struct _min_
  87. {
  88. template<typename T, typename U>
  89. constexpr auto operator()(T const & t, U const & u) const
  90. -> decltype(true ? t : u)
  91. {
  92. return u < t ? u : t;
  93. }
  94. };
  95. RANGES_INLINE_VARIABLE(_min_, min_)
  96. struct _max_
  97. {
  98. template<typename T, typename U>
  99. constexpr auto operator()(T const & t, U const & u) const
  100. -> decltype(true ? u : t)
  101. {
  102. return u < t ? t : u;
  103. }
  104. };
  105. RANGES_INLINE_VARIABLE(_max_, max_)
  106. template<typename State, typename Value>
  107. using zip_cardinality = std::integral_constant<
  108. cardinality, State::value >= 0 || Value::value >= 0
  109. ? (State::value >= 0 && Value::value >= 0
  110. ? min_(State::value, Value::value)
  111. : finite)
  112. : State::value == finite || Value::value == finite
  113. ? finite
  114. : State::value == unknown || Value::value == unknown
  115. ? unknown
  116. : infinite>;
  117. } // namespace detail
  118. /// \endcond
  119. namespace views
  120. {
  121. // clang-format off
  122. CPP_def
  123. (
  124. template(typename Fun, typename ...Rngs)
  125. (concept zippable_with)(Fun, Rngs...),
  126. and_v<input_range<Rngs>...> &&
  127. copy_constructible<Fun> &&
  128. invocable<Fun&, iterator_t<Rngs>...> &&
  129. invocable<Fun&, copy_tag, iterator_t<Rngs>...> &&
  130. invocable<Fun&, move_tag, iterator_t<Rngs>...>
  131. );
  132. // clang-format on
  133. } // namespace views
  134. /// \addtogroup group-views
  135. /// @{
  136. template<typename Fun, typename... Rngs>
  137. struct iter_zip_with_view
  138. : view_facade<iter_zip_with_view<Fun, Rngs...>,
  139. meta::fold<meta::list<range_cardinality<Rngs>...>,
  140. std::integral_constant<cardinality, infinite>,
  141. meta::quote<detail::zip_cardinality>>::value>
  142. {
  143. private:
  144. CPP_assert(sizeof...(Rngs) != 0);
  145. friend range_access;
  146. semiregular_box_t<Fun> fun_;
  147. std::tuple<Rngs...> rngs_;
  148. using difference_type_ = common_type_t<range_difference_t<Rngs>...>;
  149. template<bool Const>
  150. struct cursor;
  151. template<bool Const>
  152. struct sentinel
  153. {
  154. private:
  155. friend struct cursor<Const>;
  156. friend struct sentinel<!Const>;
  157. std::tuple<sentinel_t<meta::const_if_c<Const, Rngs>>...> ends_;
  158. public:
  159. sentinel() = default;
  160. sentinel(detail::ignore_t,
  161. std::tuple<sentinel_t<meta::const_if_c<Const, Rngs>>...> ends)
  162. : ends_(std::move(ends))
  163. {}
  164. CPP_template(bool Other)( //
  165. requires Const && (!Other)) sentinel(sentinel<Other> that)
  166. : ends_(std::move(that.ends_))
  167. {}
  168. };
  169. template<bool Const>
  170. struct cursor
  171. {
  172. private:
  173. friend struct cursor<!Const>;
  174. using fun_ref_ = semiregular_box_ref_or_val_t<Fun, Const>;
  175. fun_ref_ fun_;
  176. std::tuple<iterator_t<meta::const_if_c<Const, Rngs>>...> its_;
  177. public:
  178. using difference_type =
  179. common_type_t<range_difference_t<meta::const_if_c<Const, Rngs>>...>;
  180. using single_pass = meta::or_c<(
  181. bool)single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rngs>>>...>;
  182. using value_type = detail::decay_t<invoke_result_t<
  183. fun_ref_ &, copy_tag, iterator_t<meta::const_if_c<Const, Rngs>>...>>;
  184. cursor() = default;
  185. cursor(fun_ref_ fun,
  186. std::tuple<iterator_t<meta::const_if_c<Const, Rngs>>...> its)
  187. : fun_(std::move(fun))
  188. , its_(std::move(its))
  189. {}
  190. CPP_template(bool Other)( //
  191. requires Const && (!Other)) cursor(cursor<Other> that)
  192. : fun_(std::move(that.fun_))
  193. , its_(std::move(that.its_))
  194. {}
  195. // clang-format off
  196. auto CPP_auto_fun(read)()(const)
  197. (
  198. return tuple_apply(fun_, its_)
  199. )
  200. // clang-format on
  201. void next()
  202. {
  203. tuple_for_each(its_, detail::inc);
  204. }
  205. CPP_member
  206. auto equal(cursor const & that) const -> CPP_ret(bool)( //
  207. requires and_v<
  208. sentinel_for<iterator_t<meta::const_if_c<Const, Rngs>>,
  209. iterator_t<meta::const_if_c<Const, Rngs>>>...>)
  210. {
  211. // By returning true if *any* of the iterators are equal, we allow
  212. // zipped ranges to be of different lengths, stopping when the first
  213. // one reaches the last.
  214. return tuple_foldl(tuple_transform(its_, that.its_, detail::equal_to),
  215. false,
  216. [](bool a, bool b) { return a || b; });
  217. }
  218. bool equal(sentinel<Const> const & s) const
  219. {
  220. // By returning true if *any* of the iterators are equal, we allow
  221. // zipped ranges to be of different lengths, stopping when the first
  222. // one reaches the last.
  223. return tuple_foldl(tuple_transform(its_, s.ends_, detail::equal_to),
  224. false,
  225. [](bool a, bool b) { return a || b; });
  226. }
  227. CPP_member
  228. auto prev() -> CPP_ret(void)( //
  229. requires and_v<bidirectional_range<meta::const_if_c<Const, Rngs>>...>)
  230. {
  231. tuple_for_each(its_, detail::dec);
  232. }
  233. CPP_member
  234. auto advance(difference_type n) -> CPP_ret(void)( //
  235. requires and_v<random_access_range<meta::const_if_c<Const, Rngs>>...>)
  236. {
  237. tuple_for_each(its_, bind_back(detail::advance_, n));
  238. }
  239. CPP_member
  240. auto distance_to(cursor const & that) const -> CPP_ret(difference_type)( //
  241. requires and_v<
  242. sized_sentinel_for<iterator_t<meta::const_if_c<Const, Rngs>>,
  243. iterator_t<meta::const_if_c<Const, Rngs>>>...>)
  244. {
  245. // Return the smallest distance (in magnitude) of any of the iterator
  246. // pairs. This is to accommodate zippers of sequences of different length.
  247. if(0 < std::get<0>(that.its_) - std::get<0>(its_))
  248. return tuple_foldl(
  249. tuple_transform(its_, that.its_, detail::distance_to),
  250. (std::numeric_limits<difference_type>::max)(),
  251. detail::min_);
  252. else
  253. return tuple_foldl(
  254. tuple_transform(its_, that.its_, detail::distance_to),
  255. (std::numeric_limits<difference_type>::min)(),
  256. detail::max_);
  257. }
  258. // clang-format off
  259. template<std::size_t... Is>
  260. auto CPP_auto_fun(move_)(meta::index_sequence<Is...>)(const)
  261. (
  262. return invoke(fun_, move_tag{}, std::get<Is>(its_)...)
  263. )
  264. // clang-format on
  265. auto move() const noexcept(noexcept(std::declval<cursor const &>().move_(
  266. meta::make_index_sequence<sizeof...(Rngs)>{})))
  267. -> decltype(std::declval<cursor const &>().move_(
  268. meta::make_index_sequence<sizeof...(Rngs)>{}))
  269. {
  270. return move_(meta::make_index_sequence<sizeof...(Rngs)>{});
  271. }
  272. };
  273. template<bool Const>
  274. using end_cursor_t =
  275. meta::if_c<concepts::and_v<(bool)common_range<Rngs>...,
  276. !(bool)single_pass_iterator_<iterator_t<Rngs>>...>,
  277. cursor<Const>, sentinel<Const>>;
  278. cursor<false> begin_cursor()
  279. {
  280. return {fun_, tuple_transform(rngs_, ranges::begin)};
  281. }
  282. end_cursor_t<false> end_cursor()
  283. {
  284. return {fun_, tuple_transform(rngs_, ranges::end)};
  285. }
  286. template<bool Const = true>
  287. auto begin_cursor() const -> CPP_ret(cursor<Const>)( //
  288. requires Const && and_v<range<Rngs const>...> &&
  289. views::zippable_with<Fun, meta::if_c<Const, Rngs const>...>)
  290. {
  291. return {fun_, tuple_transform(rngs_, ranges::begin)};
  292. }
  293. template<bool Const = true>
  294. auto end_cursor() const -> CPP_ret(end_cursor_t<Const>)( //
  295. requires Const && and_v<range<Rngs const>...> &&
  296. views::zippable_with<Fun, meta::if_c<Const, Rngs const>...>)
  297. {
  298. return {fun_, tuple_transform(rngs_, ranges::end)};
  299. }
  300. public:
  301. iter_zip_with_view() = default;
  302. explicit iter_zip_with_view(Rngs... rngs)
  303. : fun_(Fun{})
  304. , rngs_{std::move(rngs)...}
  305. {}
  306. explicit iter_zip_with_view(Fun fun, Rngs... rngs)
  307. : fun_(std::move(fun))
  308. , rngs_{std::move(rngs)...}
  309. {}
  310. CPP_member
  311. constexpr auto CPP_fun(size)()(const requires and_v<sized_range<Rngs const>...>)
  312. {
  313. using size_type = common_type_t<range_size_t<Rngs const>...>;
  314. return range_cardinality<iter_zip_with_view>::value >= 0
  315. ? size_type{(
  316. std::size_t)range_cardinality<iter_zip_with_view>::value}
  317. : tuple_foldl(tuple_transform(rngs_,
  318. [](auto && r) -> size_type {
  319. return ranges::size(r);
  320. }),
  321. (std::numeric_limits<size_type>::max)(),
  322. detail::min_);
  323. }
  324. };
  325. template<typename Fun, typename... Rngs>
  326. struct zip_with_view : iter_zip_with_view<indirected<Fun>, Rngs...>
  327. {
  328. CPP_assert(sizeof...(Rngs) != 0);
  329. zip_with_view() = default;
  330. explicit zip_with_view(Rngs... rngs)
  331. : iter_zip_with_view<indirected<Fun>, Rngs...>{{Fun{}}, std::move(rngs)...}
  332. {}
  333. explicit zip_with_view(Fun fun, Rngs... rngs)
  334. : iter_zip_with_view<indirected<Fun>, Rngs...>{{std::move(fun)},
  335. std::move(rngs)...}
  336. {}
  337. };
  338. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  339. CPP_template(typename Fun, typename... Rng)(requires copy_constructible<Fun>)
  340. zip_with_view(Fun, Rng &&...)
  341. ->zip_with_view<Fun, views::all_t<Rng>...>;
  342. #endif
  343. namespace views
  344. {
  345. struct iter_zip_with_fn
  346. {
  347. template<typename... Rngs, typename Fun>
  348. auto operator()(Fun fun, Rngs &&... rngs) const -> CPP_ret(
  349. iter_zip_with_view<Fun, all_t<Rngs>...>)( //
  350. requires and_v<viewable_range<Rngs>...> && zippable_with<Fun, Rngs...> &&
  351. (sizeof...(Rngs) != 0))
  352. {
  353. return iter_zip_with_view<Fun, all_t<Rngs>...>{
  354. std::move(fun), all(static_cast<Rngs &&>(rngs))...};
  355. }
  356. template<typename Fun>
  357. constexpr auto operator()(Fun) const noexcept
  358. -> CPP_ret(empty_view<std::tuple<>>)( //
  359. requires zippable_with<Fun>)
  360. {
  361. return {};
  362. }
  363. };
  364. /// \relates iter_zip_with_fn
  365. /// \ingroup group-views
  366. RANGES_INLINE_VARIABLE(iter_zip_with_fn, iter_zip_with)
  367. struct zip_with_fn
  368. {
  369. template<typename... Rngs, typename Fun>
  370. auto operator()(Fun fun, Rngs &&... rngs) const
  371. -> CPP_ret(zip_with_view<Fun, all_t<Rngs>...>)( //
  372. requires and_v<viewable_range<Rngs>...> &&
  373. and_v<input_range<Rngs>...> && copy_constructible<Fun> &&
  374. invocable<Fun &, range_reference_t<Rngs> &&...> &&
  375. (sizeof...(Rngs) != 0))
  376. {
  377. return zip_with_view<Fun, all_t<Rngs>...>{
  378. std::move(fun), all(static_cast<Rngs &&>(rngs))...};
  379. }
  380. template<typename Fun>
  381. constexpr auto operator()(Fun) const noexcept
  382. -> CPP_ret(empty_view<std::tuple<>>)( //
  383. requires copy_constructible<Fun> && invocable<Fun &>)
  384. {
  385. return {};
  386. }
  387. };
  388. /// \relates zip_with_fn
  389. /// \ingroup group-views
  390. RANGES_INLINE_VARIABLE(zip_with_fn, zip_with)
  391. } // namespace views
  392. /// @}
  393. } // namespace ranges
  394. #include <range/v3/detail/satisfy_boost_range.hpp>
  395. RANGES_SATISFY_BOOST_RANGE(::ranges::iter_zip_with_view)
  396. RANGES_SATISFY_BOOST_RANGE(::ranges::zip_with_view)
  397. #endif