transform.hpp 23 KB

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