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.

212 lines
8.4KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2014-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_ALGORITHM_TRANSFORM_HPP
  14. #define RANGES_V3_ALGORITHM_TRANSFORM_HPP
  15. #include <utility>
  16. #include <meta/meta.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/algorithm/result_types.hpp>
  19. #include <range/v3/functional/identity.hpp>
  20. #include <range/v3/functional/invoke.hpp>
  21. #include <range/v3/iterator/concepts.hpp>
  22. #include <range/v3/iterator/traits.hpp>
  23. #include <range/v3/iterator/unreachable_sentinel.hpp>
  24. #include <range/v3/range/access.hpp>
  25. #include <range/v3/range/concepts.hpp>
  26. #include <range/v3/range/dangling.hpp>
  27. #include <range/v3/range/traits.hpp>
  28. #include <range/v3/utility/static_const.hpp>
  29. namespace ranges
  30. {
  31. /// \addtogroup group-algorithms
  32. /// @{
  33. template<typename I, typename O>
  34. using unary_transform_result = detail::in_out_result<I, O>;
  35. template<typename I1, typename I2, typename O>
  36. using binary_transform_result = detail::in1_in2_out_result<I1, I2, O>;
  37. RANGES_BEGIN_NIEBLOID(transform)
  38. // Single-range variant
  39. /// \brief function template \c transform
  40. template<typename I, typename S, typename O, typename F, typename P = identity>
  41. auto RANGES_FUN_NIEBLOID(transform)(
  42. I first, S last, O out, F fun, P proj = P{}) //
  43. ->CPP_ret(unary_transform_result<I, O>)( //
  44. requires input_iterator<I> && sentinel_for<S, I> &&
  45. weakly_incrementable<O> && copy_constructible<F> &&
  46. writable<O, indirect_result_t<F &, projected<I, P>>>)
  47. {
  48. for(; first != last; ++first, ++out)
  49. *out = invoke(fun, invoke(proj, *first));
  50. return {first, out};
  51. }
  52. /// \overload
  53. template<typename Rng, typename O, typename F, typename P = identity>
  54. auto RANGES_FUN_NIEBLOID(transform)(Rng && rng, O out, F fun, P proj = P{}) //
  55. ->CPP_ret(unary_transform_result<safe_iterator_t<Rng>, O>)( //
  56. requires input_range<Rng> && weakly_incrementable<O> &&
  57. copy_constructible<F> &&
  58. writable<O, indirect_result_t<F &, projected<iterator_t<Rng>, P>>>)
  59. {
  60. return (*this)(
  61. begin(rng), end(rng), std::move(out), std::move(fun), std::move(proj));
  62. }
  63. // Double-range variant, 4-iterator version
  64. /// \overload
  65. template<typename I0,
  66. typename S0,
  67. typename I1,
  68. typename S1,
  69. typename O,
  70. typename F,
  71. typename P0 = identity,
  72. typename P1 = identity>
  73. auto RANGES_FUN_NIEBLOID(transform)(I0 begin0,
  74. S0 end0,
  75. I1 begin1,
  76. S1 end1,
  77. O out,
  78. F fun,
  79. P0 proj0 = P0{},
  80. P1 proj1 = P1{}) //
  81. ->CPP_ret(binary_transform_result<I0, I1, O>)( //
  82. requires input_iterator<I0> && sentinel_for<S0, I0> &&
  83. input_iterator<I1> && sentinel_for<S1, I1> && weakly_incrementable<O> &&
  84. copy_constructible<F> &&
  85. writable<O, indirect_result_t<F &, projected<I0, P0>, projected<I1, P1>>>)
  86. {
  87. for(; begin0 != end0 && begin1 != end1; ++begin0, ++begin1, ++out)
  88. *out = invoke(fun, invoke(proj0, *begin0), invoke(proj1, *begin1));
  89. return {begin0, begin1, out};
  90. }
  91. /// \overload
  92. template<typename Rng0,
  93. typename Rng1,
  94. typename O,
  95. typename F,
  96. typename P0 = identity,
  97. typename P1 = identity>
  98. auto RANGES_FUN_NIEBLOID(transform)(
  99. Rng0 && rng0, Rng1 && rng1, O out, F fun, P0 proj0 = P0{}, P1 proj1 = P1{}) //
  100. ->CPP_ret(binary_transform_result<safe_iterator_t<Rng0>,
  101. safe_iterator_t<Rng1>,
  102. O>)( //
  103. requires input_range<Rng0> && input_range<Rng1> &&
  104. weakly_incrementable<O> && copy_constructible<F> &&
  105. writable<O,
  106. indirect_result_t<F &,
  107. projected<iterator_t<Rng0>, P0>,
  108. projected<iterator_t<Rng1>, P1>>>)
  109. {
  110. return (*this)(begin(rng0),
  111. end(rng0),
  112. begin(rng1),
  113. end(rng1),
  114. std::move(out),
  115. std::move(fun),
  116. std::move(proj0),
  117. std::move(proj1));
  118. }
  119. // Double-range variant, 3-iterator version
  120. /// \overload
  121. template<typename I0,
  122. typename S0,
  123. typename I1,
  124. typename O,
  125. typename F,
  126. typename P0 = identity,
  127. typename P1 = identity>
  128. RANGES_DEPRECATED(
  129. "Use the variant of ranges::transform that takes an upper bound "
  130. "for both input ranges")
  131. auto RANGES_FUN_NIEBLOID(transform)(I0 begin0,
  132. S0 end0,
  133. I1 begin1,
  134. O out,
  135. F fun,
  136. P0 proj0 = P0{},
  137. P1 proj1 = P1{}) //
  138. ->CPP_ret(binary_transform_result<I0, I1, O>)( //
  139. requires input_iterator<I0> && sentinel_for<S0, I0> &&
  140. input_iterator<I1> && weakly_incrementable<O> && copy_constructible<F> &&
  141. writable<O, indirect_result_t<F &, projected<I0, P0>, projected<I1, P1>>>)
  142. {
  143. return (*this)(std::move(begin0),
  144. std::move(end0),
  145. std::move(begin1),
  146. unreachable,
  147. std::move(out),
  148. std::move(fun),
  149. std::move(proj0),
  150. std::move(proj1));
  151. }
  152. /// \overload
  153. template<typename Rng0,
  154. typename I1Ref,
  155. typename O,
  156. typename F,
  157. typename P0 = identity,
  158. typename P1 = identity>
  159. RANGES_DEPRECATED(
  160. "Use the variant of ranges::transform that takes an upper bound "
  161. "for both input ranges")
  162. auto RANGES_FUN_NIEBLOID(transform)(Rng0 && rng0,
  163. I1Ref && begin1,
  164. O out,
  165. F fun,
  166. P0 proj0 = P0{},
  167. P1 proj1 = P1{}) //
  168. ->CPP_ret(
  169. binary_transform_result<safe_iterator_t<Rng0>, uncvref_t<I1Ref>, O>)( //
  170. requires input_range<Rng0> && input_iterator<uncvref_t<I1Ref>> &&
  171. weakly_incrementable<O> && copy_constructible<F> &&
  172. writable<O,
  173. indirect_result_t<F &,
  174. projected<iterator_t<Rng0>, P0>,
  175. projected<uncvref_t<I1Ref>, P1>>>)
  176. {
  177. return (*this)(begin(rng0),
  178. end(rng0),
  179. static_cast<I1Ref &&>(begin1),
  180. unreachable,
  181. std::move(out),
  182. std::move(fun),
  183. std::move(proj0),
  184. std::move(proj1));
  185. }
  186. RANGES_END_NIEBLOID(transform)
  187. namespace cpp20
  188. {
  189. using ranges::binary_transform_result;
  190. using ranges::transform;
  191. using ranges::unary_transform_result;
  192. } // namespace cpp20
  193. /// @}
  194. } // namespace ranges
  195. #endif // include guard