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.

544 lines
21KB

  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_TRANSFORM_HPP
  14. #define RANGES_V3_VIEW_TRANSFORM_HPP
  15. #include <iterator>
  16. #include <type_traits>
  17. #include <utility>
  18. #include <meta/meta.hpp>
  19. #include <range/v3/range_fwd.hpp>
  20. #include <range/v3/algorithm/max.hpp>
  21. #include <range/v3/algorithm/min.hpp>
  22. #include <range/v3/functional/bind_back.hpp>
  23. #include <range/v3/functional/indirect.hpp>
  24. #include <range/v3/functional/invoke.hpp>
  25. #include <range/v3/iterator/operations.hpp>
  26. #include <range/v3/range/access.hpp>
  27. #include <range/v3/range/primitives.hpp>
  28. #include <range/v3/range/traits.hpp>
  29. #include <range/v3/utility/move.hpp>
  30. #include <range/v3/utility/semiregular_box.hpp>
  31. #include <range/v3/utility/static_const.hpp>
  32. #include <range/v3/view/adaptor.hpp>
  33. #include <range/v3/view/all.hpp>
  34. #include <range/v3/view/view.hpp>
  35. namespace ranges
  36. {
  37. /// \cond
  38. namespace detail
  39. {
  40. constexpr cardinality transform2_cardinality(cardinality c1, cardinality c2)
  41. {
  42. return c1 >= 0 || c2 >= 0
  43. ? (c1 >= 0 && c2 >= 0 ? (c1 < c2 ? c1 : c2) : finite)
  44. : c1 == finite || c2 == finite
  45. ? finite
  46. : c1 == unknown || c2 == unknown ? unknown : infinite;
  47. }
  48. // clang-format off
  49. CPP_def
  50. (
  51. template(typename Fun, typename Rng)
  52. concept iter_transform_1_readable,
  53. regular_invocable<Fun &, iterator_t<Rng>> &&
  54. regular_invocable<Fun &, copy_tag, iterator_t<Rng>> &&
  55. regular_invocable<Fun &, move_tag, iterator_t<Rng>> &&
  56. common_reference_with<
  57. invoke_result_t<Fun &, iterator_t<Rng>> &&,
  58. invoke_result_t<Fun &, copy_tag, iterator_t<Rng>> &> &&
  59. common_reference_with<
  60. invoke_result_t<Fun &, iterator_t<Rng>> &&,
  61. invoke_result_t<Fun &, move_tag, iterator_t<Rng>> &&> &&
  62. common_reference_with<
  63. invoke_result_t<Fun &, move_tag, iterator_t<Rng>> &&,
  64. invoke_result_t<Fun &, copy_tag, iterator_t<Rng>> const &>
  65. );
  66. CPP_def
  67. (
  68. template(typename Fun, typename Rng1, typename Rng2)
  69. concept iter_transform_2_readable,
  70. regular_invocable<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> &&
  71. regular_invocable<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&
  72. regular_invocable<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&
  73. common_reference_with<
  74. invoke_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> &&,
  75. invoke_result_t<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>> &> &&
  76. common_reference_with<
  77. invoke_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> &&,
  78. invoke_result_t<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&> &&
  79. common_reference_with<
  80. invoke_result_t<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&,
  81. invoke_result_t<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>> const &>
  82. );
  83. // clang-format on
  84. } // namespace detail
  85. /// \endcond
  86. /// \addtogroup group-views
  87. /// @{
  88. template<typename Rng, typename Fun>
  89. struct iter_transform_view : view_adaptor<iter_transform_view<Rng, Fun>, Rng>
  90. {
  91. private:
  92. friend range_access;
  93. RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Fun> fun_;
  94. template<bool Const>
  95. using use_sentinel_t =
  96. meta::bool_<!common_range<meta::const_if_c<Const, Rng>> ||
  97. single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>>;
  98. template<bool IsConst>
  99. struct adaptor : adaptor_base
  100. {
  101. private:
  102. friend struct adaptor<!IsConst>;
  103. using CRng = meta::const_if_c<IsConst, Rng>;
  104. using fun_ref_ = semiregular_box_ref_or_val_t<Fun, IsConst>;
  105. fun_ref_ fun_;
  106. public:
  107. using value_type =
  108. detail::decay_t<invoke_result_t<Fun &, copy_tag, iterator_t<CRng>>>;
  109. adaptor() = default;
  110. adaptor(fun_ref_ fun)
  111. : fun_(std::move(fun))
  112. {}
  113. CPP_template(bool Other)( //
  114. requires IsConst && (!Other)) adaptor(adaptor<Other> that)
  115. : fun_(std::move(that.fun_))
  116. {}
  117. // clang-format off
  118. auto CPP_auto_fun(read)(iterator_t<CRng> it)(const)
  119. (
  120. return invoke(fun_, it)
  121. )
  122. auto CPP_auto_fun(iter_move)(iterator_t<CRng> it)(const)
  123. (
  124. return invoke(fun_, move_tag{}, it)
  125. )
  126. // clang-format on
  127. };
  128. adaptor<false> begin_adaptor()
  129. {
  130. return {fun_};
  131. }
  132. template<bool Const = true>
  133. auto begin_adaptor() const -> CPP_ret(adaptor<Const>)( //
  134. requires Const && range<meta::const_if_c<Const, Rng>> &&
  135. detail::iter_transform_1_readable<Fun const,
  136. meta::const_if_c<Const, Rng>>)
  137. {
  138. return {fun_};
  139. }
  140. meta::if_<use_sentinel_t<false>, adaptor_base, adaptor<false>> end_adaptor()
  141. {
  142. return {fun_};
  143. }
  144. template<bool Const = true>
  145. auto end_adaptor() const
  146. -> CPP_ret(meta::if_<use_sentinel_t<Const>, adaptor_base, adaptor<Const>>)( //
  147. requires Const && range<meta::const_if_c<Const, Rng>> &&
  148. detail::iter_transform_1_readable<Fun const,
  149. meta::const_if_c<Const, Rng>>)
  150. {
  151. return {fun_};
  152. }
  153. public:
  154. iter_transform_view() = default;
  155. iter_transform_view(Rng rng, Fun fun)
  156. : iter_transform_view::view_adaptor{std::move(rng)}
  157. , fun_(std::move(fun))
  158. {}
  159. CPP_member
  160. constexpr auto CPP_fun(size)()(requires sized_range<Rng>)
  161. {
  162. return ranges::size(this->base());
  163. }
  164. CPP_member
  165. constexpr auto CPP_fun(size)()(const requires sized_range<Rng const>)
  166. {
  167. return ranges::size(this->base());
  168. }
  169. };
  170. template<typename Rng, typename Fun>
  171. struct transform_view : iter_transform_view<Rng, indirected<Fun>>
  172. {
  173. transform_view() = default;
  174. transform_view(Rng rng, Fun fun)
  175. : iter_transform_view<Rng, indirected<Fun>>{std::move(rng),
  176. indirect(std::move(fun))}
  177. {}
  178. };
  179. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  180. CPP_template(typename Rng, typename Fun)(requires copy_constructible<Fun>)
  181. transform_view(Rng &&, Fun)
  182. ->transform_view<views::all_t<Rng>, Fun>;
  183. #endif
  184. template<typename Rng1, typename Rng2, typename Fun>
  185. struct iter_transform2_view
  186. : view_facade<iter_transform2_view<Rng1, Rng2, Fun>,
  187. detail::transform2_cardinality(range_cardinality<Rng1>::value,
  188. range_cardinality<Rng2>::value)>
  189. {
  190. private:
  191. friend range_access;
  192. RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Fun> fun_;
  193. Rng1 rng1_;
  194. Rng2 rng2_;
  195. using difference_type_ =
  196. common_type_t<range_difference_t<Rng1>, range_difference_t<Rng2>>;
  197. static constexpr cardinality my_cardinality = detail::transform2_cardinality(
  198. range_cardinality<Rng1>::value, range_cardinality<Rng2>::value);
  199. template<bool>
  200. struct cursor;
  201. template<bool Const>
  202. struct sentinel
  203. {
  204. private:
  205. friend struct cursor<Const>;
  206. sentinel_t<meta::const_if_c<Const, Rng1>> end1_;
  207. sentinel_t<meta::const_if_c<Const, Rng2>> end2_;
  208. public:
  209. sentinel() = default;
  210. sentinel(meta::const_if_c<Const, iter_transform2_view> * parent,
  211. decltype(ranges::end))
  212. : end1_(end(parent->rng1_))
  213. , end2_(end(parent->rng2_))
  214. {}
  215. CPP_template(bool Other)( //
  216. requires Const && (!Other)) sentinel(sentinel<Other> that)
  217. : end1_(std::move(that.end1_))
  218. , end2_(std::move(that.end2_))
  219. {}
  220. };
  221. template<bool Const>
  222. struct cursor
  223. {
  224. private:
  225. using fun_ref_ = semiregular_box_ref_or_val_t<Fun, Const>;
  226. using R1 = meta::const_if_c<Const, Rng1>;
  227. using R2 = meta::const_if_c<Const, Rng2>;
  228. fun_ref_ fun_;
  229. iterator_t<R1> it1_;
  230. iterator_t<R2> it2_;
  231. public:
  232. using difference_type = difference_type_;
  233. using single_pass = meta::or_c<(bool)single_pass_iterator_<iterator_t<R1>>,
  234. (bool)single_pass_iterator_<iterator_t<R2>>>;
  235. using value_type =
  236. detail::decay_t<invoke_result_t<meta::const_if_c<Const, Fun> &, copy_tag,
  237. iterator_t<R1>, iterator_t<R2>>>;
  238. cursor() = default;
  239. template<typename BeginEndFn>
  240. cursor(meta::const_if_c<Const, iter_transform2_view> * parent,
  241. BeginEndFn begin_end)
  242. : fun_(parent->fun_)
  243. , it1_(begin_end(parent->rng1_))
  244. , it2_(begin_end(parent->rng2_))
  245. {}
  246. CPP_template(bool Other)( //
  247. requires Const && (!Other)) cursor(cursor<Other> that)
  248. : fun_(std::move(that.fun_))
  249. , it1_(std::move(that.end1_))
  250. , it2_(std::move(that.end2_))
  251. {}
  252. // clang-format off
  253. auto CPP_auto_fun(read)()(const)
  254. (
  255. return invoke(fun_, it1_, it2_)
  256. )
  257. // clang-format on
  258. void next()
  259. {
  260. ++it1_;
  261. ++it2_;
  262. }
  263. CPP_member
  264. auto equal(cursor const & that) const -> CPP_ret(bool)( //
  265. requires forward_range<Rng1> && forward_range<Rng2>)
  266. {
  267. // By returning true if *any* of the iterators are equal, we allow
  268. // transformed ranges to be of different lengths, stopping when the first
  269. // one reaches the last.
  270. return it1_ == that.it1_ || it2_ == that.it2_;
  271. }
  272. bool equal(sentinel<Const> const & s) const
  273. {
  274. // By returning true if *any* of the iterators are equal, we allow
  275. // transformed ranges to be of different lengths, stopping when the first
  276. // one reaches the last.
  277. return it1_ == s.end1_ || it2_ == s.end2_;
  278. }
  279. CPP_member
  280. auto prev() -> CPP_ret(void)( //
  281. requires bidirectional_range<R1> && bidirectional_range<R2>)
  282. {
  283. --it1_;
  284. --it2_;
  285. }
  286. CPP_member
  287. auto advance(difference_type n) -> CPP_ret(void)( //
  288. requires random_access_range<R1> && random_access_range<R2>)
  289. {
  290. ranges::advance(it1_, n);
  291. ranges::advance(it2_, n);
  292. }
  293. CPP_member
  294. auto distance_to(cursor const & that) const -> CPP_ret(difference_type)( //
  295. requires sized_sentinel_for<iterator_t<R1>, iterator_t<R1>> &&
  296. sized_sentinel_for<iterator_t<R2>, iterator_t<R2>>)
  297. {
  298. // Return the smallest distance (in magnitude) of any of the iterator
  299. // pairs. This is to accommodate zippers of sequences of different length.
  300. difference_type d1 = that.it1_ - it1_, d2 = that.it2_ - it2_;
  301. return 0 < d1 ? ranges::min(d1, d2) : ranges::max(d1, d2);
  302. }
  303. // clang-format off
  304. auto CPP_auto_fun(move)()(const)
  305. (
  306. return invoke(fun_, move_tag{}, it1_, it2_)
  307. )
  308. // clang-format on
  309. };
  310. template<bool Const>
  311. using end_cursor_t = meta::if_c<
  312. common_range<meta::const_if_c<Const, Rng1>> &&
  313. common_range<meta::const_if_c<Const, Rng2>> &&
  314. !single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng1>>> &&
  315. !single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng2>>>,
  316. cursor<Const>, sentinel<Const>>;
  317. cursor<simple_view<Rng1>() && simple_view<Rng2>()> begin_cursor()
  318. {
  319. return {this, ranges::begin};
  320. }
  321. end_cursor_t<simple_view<Rng1>() && simple_view<Rng2>()> end_cursor()
  322. {
  323. return {this, ranges::end};
  324. }
  325. template<bool Const = true>
  326. auto begin_cursor() const -> CPP_ret(cursor<true>)( //
  327. requires Const && range<meta::const_if_c<Const, Rng1>> &&
  328. range<meta::const_if_c<Const, Rng2>> && detail::iter_transform_2_readable<
  329. Fun const, meta::const_if_c<Const, Rng1>,
  330. meta::const_if_c<Const, Rng2>>)
  331. {
  332. return {this, ranges::begin};
  333. }
  334. template<bool Const = true>
  335. auto end_cursor() const -> CPP_ret(end_cursor_t<Const>)( //
  336. requires Const && range<meta::const_if_c<Const, Rng1>> &&
  337. range<meta::const_if_c<Const, Rng2>> && detail::iter_transform_2_readable<
  338. Fun const, meta::const_if_c<Const, Rng1>,
  339. meta::const_if_c<Const, Rng2>>)
  340. {
  341. return {this, ranges::end};
  342. }
  343. template<typename Self>
  344. static constexpr auto size_(Self & self)
  345. {
  346. using size_type = common_type_t<range_size_t<Rng1>, range_size_t<Rng2>>;
  347. return ranges::min(static_cast<size_type>(ranges::size(self.rng1_)),
  348. static_cast<size_type>(ranges::size(self.rng2_)));
  349. }
  350. template<bool B>
  351. using R1 = meta::invoke<detail::dependent_<B>, Rng1>;
  352. template<bool B>
  353. using R2 = meta::invoke<detail::dependent_<B>, Rng2>;
  354. public:
  355. iter_transform2_view() = default;
  356. constexpr iter_transform2_view(Rng1 rng1, Rng2 rng2, Fun fun)
  357. : fun_(std::move(fun))
  358. , rng1_(std::move(rng1))
  359. , rng2_(std::move(rng2))
  360. {}
  361. CPP_member
  362. static constexpr auto size() -> CPP_ret(std::size_t)( //
  363. requires(my_cardinality >= 0))
  364. {
  365. return static_cast<std::size_t>(my_cardinality);
  366. }
  367. CPP_template(bool True = true)( //
  368. requires(my_cardinality < 0) && sized_range<Rng1 const> &&
  369. sized_range<Rng2 const> &&
  370. common_with<range_size_t<R1<True>>, range_size_t<R2<True>>>) //
  371. constexpr auto size() const
  372. {
  373. return size_(*this);
  374. }
  375. CPP_template(bool True = true)( //
  376. requires(my_cardinality < 0) && sized_range<Rng1> && sized_range<Rng2> &&
  377. common_with<range_size_t<R1<True>>, range_size_t<R2<True>>>) //
  378. constexpr auto size()
  379. {
  380. return size_(*this);
  381. }
  382. };
  383. template<typename Rng1, typename Rng2, typename Fun>
  384. struct transform2_view : iter_transform2_view<Rng1, Rng2, indirected<Fun>>
  385. {
  386. transform2_view() = default;
  387. constexpr transform2_view(Rng1 rng1, Rng2 rng2, Fun fun)
  388. : iter_transform2_view<Rng1, Rng2, indirected<Fun>>{std::move(rng1),
  389. std::move(rng2),
  390. indirect(std::move(fun))}
  391. {}
  392. };
  393. namespace views
  394. {
  395. struct iter_transform_fn
  396. {
  397. private:
  398. friend view_access;
  399. template<typename Fun>
  400. static constexpr auto bind(iter_transform_fn iter_transform, Fun fun)
  401. {
  402. return make_pipeable(bind_back(iter_transform, std::move(fun)));
  403. }
  404. public:
  405. template<typename Rng, typename Fun>
  406. constexpr auto operator()(Rng && rng, Fun fun) const
  407. -> CPP_ret(iter_transform_view<all_t<Rng>, Fun>)( //
  408. requires viewable_range<Rng> && input_range<Rng> &&
  409. copy_constructible<Fun> &&
  410. detail::iter_transform_1_readable<Fun, Rng>)
  411. {
  412. return {all(static_cast<Rng &&>(rng)), std::move(fun)};
  413. }
  414. template<typename Rng1, typename Rng2, typename Fun>
  415. constexpr auto operator()(Rng1 && rng1, Rng2 && rng2, Fun fun) const
  416. -> CPP_ret(iter_transform2_view<all_t<Rng1>, all_t<Rng2>, Fun>)( //
  417. requires viewable_range<Rng1> && input_range<Rng1> && viewable_range<
  418. Rng2> && input_range<Rng2> && copy_constructible<Fun> &&
  419. common_with<range_difference_t<Rng1>, range_difference_t<Rng1>> &&
  420. detail::iter_transform_2_readable<Fun, Rng1, Rng2>)
  421. {
  422. return {all(static_cast<Rng1 &&>(rng1)),
  423. all(static_cast<Rng2 &&>(rng2)),
  424. std::move(fun)};
  425. }
  426. };
  427. /// \relates iter_transform_fn
  428. /// \ingroup group-views
  429. RANGES_INLINE_VARIABLE(view<iter_transform_fn>, iter_transform)
  430. // Don't forget to update views::for_each whenever this set
  431. // of concepts changes
  432. // clang-format off
  433. CPP_def
  434. (
  435. template(typename Rng, typename Fun)
  436. concept transformable_range,
  437. viewable_range<Rng> && input_range<Rng> &&
  438. copy_constructible<Fun> &&
  439. regular_invocable<Fun &, range_reference_t<Rng>> &&
  440. (!std::is_void<indirect_result_t<Fun &, iterator_t<Rng>>>::value)
  441. );
  442. CPP_def
  443. (
  444. template(typename Rng1, typename Rng2, typename Fun)
  445. concept transformable_ranges,
  446. viewable_range<Rng1> && input_range<Rng1> &&
  447. viewable_range<Rng2> && input_range<Rng2> &&
  448. copy_constructible<Fun> &&
  449. (!std::is_void<
  450. indirect_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>>>::value)
  451. );
  452. // clang-format on
  453. struct transform_fn
  454. {
  455. private:
  456. friend view_access;
  457. template<typename Fun>
  458. static constexpr auto bind(transform_fn transform, Fun fun)
  459. {
  460. return make_pipeable(bind_back(transform, std::move(fun)));
  461. }
  462. public:
  463. template<typename Rng, typename Fun>
  464. constexpr auto operator()(Rng && rng, Fun fun) const
  465. -> CPP_ret(transform_view<all_t<Rng>, Fun>)( //
  466. requires transformable_range<Rng, Fun>)
  467. {
  468. return {all(static_cast<Rng &&>(rng)), std::move(fun)};
  469. }
  470. template<typename Rng1, typename Rng2, typename Fun>
  471. constexpr auto operator()(Rng1 && rng1, Rng2 && rng2, Fun fun) const
  472. -> CPP_ret(transform2_view<all_t<Rng1>, all_t<Rng2>, Fun>)( //
  473. requires transformable_ranges<Rng1, Rng2, Fun>)
  474. {
  475. return {all(static_cast<Rng1 &&>(rng1)),
  476. all(static_cast<Rng2 &&>(rng2)),
  477. std::move(fun)};
  478. }
  479. };
  480. /// \relates transform_fn
  481. /// \ingroup group-views
  482. RANGES_INLINE_VARIABLE(view<transform_fn>, transform)
  483. } // namespace views
  484. namespace cpp20
  485. {
  486. namespace views
  487. {
  488. using ranges::views::transform;
  489. }
  490. CPP_template(typename Rng, typename F)( //
  491. requires input_range<Rng> && copy_constructible<F> && view_<Rng> &&
  492. std::is_object<F>::value &&
  493. regular_invocable<F &, iter_reference_t<iterator_t<Rng>>>) //
  494. using transform_view = ranges::transform_view<Rng, F>;
  495. } // namespace cpp20
  496. /// @}
  497. } // namespace ranges
  498. #include <range/v3/detail/satisfy_boost_range.hpp>
  499. RANGES_SATISFY_BOOST_RANGE(::ranges::iter_transform_view)
  500. RANGES_SATISFY_BOOST_RANGE(::ranges::transform_view)
  501. #endif