File indexing completed on 2025-01-18 10:09:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_VIEW_TRANSFORM_HPP
0015 #define RANGES_V3_VIEW_TRANSFORM_HPP
0016
0017 #include <iterator>
0018 #include <type_traits>
0019 #include <utility>
0020
0021 #include <meta/meta.hpp>
0022
0023 #include <range/v3/range_fwd.hpp>
0024
0025 #include <range/v3/algorithm/max.hpp>
0026 #include <range/v3/algorithm/min.hpp>
0027 #include <range/v3/functional/bind_back.hpp>
0028 #include <range/v3/functional/indirect.hpp>
0029 #include <range/v3/functional/invoke.hpp>
0030 #include <range/v3/iterator/operations.hpp>
0031 #include <range/v3/range/access.hpp>
0032 #include <range/v3/range/primitives.hpp>
0033 #include <range/v3/range/traits.hpp>
0034 #include <range/v3/utility/move.hpp>
0035 #include <range/v3/utility/semiregular_box.hpp>
0036 #include <range/v3/utility/static_const.hpp>
0037 #include <range/v3/view/adaptor.hpp>
0038 #include <range/v3/view/all.hpp>
0039 #include <range/v3/view/view.hpp>
0040
0041 #include <range/v3/detail/prologue.hpp>
0042
0043 namespace ranges
0044 {
0045
0046 namespace detail
0047 {
0048 constexpr cardinality transform2_cardinality(cardinality c1, cardinality c2)
0049 {
0050 return c1 >= 0 || c2 >= 0
0051 ? (c1 >= 0 && c2 >= 0 ? (c1 < c2 ? c1 : c2) : finite)
0052 : c1 == finite || c2 == finite
0053 ? finite
0054 : c1 == unknown || c2 == unknown ? unknown : infinite;
0055 }
0056
0057
0058
0059
0060 template(typename Fun, typename Rng)(
0061 concept (iter_transform_1_readable_)(Fun, Rng),
0062 regular_invocable<Fun &, iterator_t<Rng>> AND
0063 regular_invocable<Fun &, copy_tag, iterator_t<Rng>> AND
0064 regular_invocable<Fun &, move_tag, iterator_t<Rng>> AND
0065 common_reference_with<
0066 invoke_result_t<Fun &, iterator_t<Rng>> &&,
0067 invoke_result_t<Fun &, copy_tag, iterator_t<Rng>> &> AND
0068 common_reference_with<
0069 invoke_result_t<Fun &, iterator_t<Rng>> &&,
0070 invoke_result_t<Fun &, move_tag, iterator_t<Rng>> &&> AND
0071 common_reference_with<
0072 invoke_result_t<Fun &, move_tag, iterator_t<Rng>> &&,
0073 invoke_result_t<Fun &, copy_tag, iterator_t<Rng>> const &>
0074 );
0075
0076
0077 template<typename Fun, typename Rng>
0078 CPP_concept iter_transform_1_readable =
0079 CPP_concept_ref(detail::iter_transform_1_readable_, Fun, Rng);
0080
0081
0082
0083 template(typename Fun, typename Rng1, typename Rng2)(
0084 concept (iter_transform_2_readable_)(Fun, Rng1, Rng2),
0085 regular_invocable<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> AND
0086 regular_invocable<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>> AND
0087 regular_invocable<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> AND
0088 common_reference_with<
0089 invoke_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> &&,
0090 invoke_result_t<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>> &> AND
0091 common_reference_with<
0092 invoke_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>> &&,
0093 invoke_result_t<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&> AND
0094 common_reference_with<
0095 invoke_result_t<Fun &, move_tag, iterator_t<Rng1>, iterator_t<Rng2>> &&,
0096 invoke_result_t<Fun &, copy_tag, iterator_t<Rng1>, iterator_t<Rng2>> const &>
0097 );
0098
0099
0100 template<typename Fun, typename Rng1, typename Rng2>
0101 CPP_concept iter_transform_2_readable =
0102 CPP_concept_ref(detail::iter_transform_2_readable_, Fun, Rng1, Rng2);
0103
0104 }
0105
0106
0107
0108
0109 template<typename Rng, typename Fun>
0110 struct iter_transform_view : view_adaptor<iter_transform_view<Rng, Fun>, Rng>
0111 {
0112 private:
0113 friend range_access;
0114 RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Fun> fun_;
0115 template<bool Const>
0116 using use_sentinel_t =
0117 meta::bool_<!common_range<meta::const_if_c<Const, Rng>> ||
0118 single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>>;
0119
0120 template<bool IsConst>
0121 struct adaptor : adaptor_base
0122 {
0123 private:
0124 friend struct adaptor<!IsConst>;
0125 using CRng = meta::const_if_c<IsConst, Rng>;
0126 using fun_ref_ = semiregular_box_ref_or_val_t<Fun, IsConst>;
0127 RANGES_NO_UNIQUE_ADDRESS fun_ref_ fun_;
0128
0129 public:
0130 using value_type =
0131 detail::decay_t<invoke_result_t<Fun &, copy_tag, iterator_t<CRng>>>;
0132 adaptor() = default;
0133 adaptor(fun_ref_ fun)
0134 : fun_(std::move(fun))
0135 {}
0136 template(bool Other)(
0137 requires IsConst AND CPP_NOT(Other))
0138 adaptor(adaptor<Other> that)
0139 : fun_(std::move(that.fun_))
0140 {}
0141
0142
0143 auto CPP_auto_fun(read)(iterator_t<CRng> it)(const)
0144 (
0145 return invoke(fun_, it)
0146 )
0147 auto CPP_auto_fun(iter_move)(iterator_t<CRng> it)(const)
0148 (
0149 return invoke(fun_, move_tag{}, it)
0150 )
0151
0152 };
0153
0154 adaptor<false> begin_adaptor()
0155 {
0156 return {fun_};
0157 }
0158 template(bool Const = true)(
0159 requires Const AND range<meta::const_if_c<Const, Rng>> AND
0160 detail::iter_transform_1_readable<Fun const,
0161 meta::const_if_c<Const, Rng>>)
0162 adaptor<Const> begin_adaptor() const
0163 {
0164 return {fun_};
0165 }
0166 meta::if_<use_sentinel_t<false>, adaptor_base, adaptor<false>> end_adaptor()
0167 {
0168 return {fun_};
0169 }
0170 template(bool Const = true)(
0171 requires Const AND range<meta::const_if_c<Const, Rng>> AND
0172 detail::iter_transform_1_readable<Fun const,
0173 meta::const_if_c<Const, Rng>>)
0174 meta::if_<use_sentinel_t<Const>, adaptor_base, adaptor<Const>> end_adaptor() const
0175 {
0176 return {fun_};
0177 }
0178
0179 public:
0180 iter_transform_view() = default;
0181 iter_transform_view(Rng rng, Fun fun)
0182 : iter_transform_view::view_adaptor{std::move(rng)}
0183 , fun_(std::move(fun))
0184 {}
0185 CPP_auto_member
0186 constexpr auto CPP_fun(size)()(
0187 requires sized_range<Rng>)
0188 {
0189 return ranges::size(this->base());
0190 }
0191 CPP_auto_member
0192 constexpr auto CPP_fun(size)()(const
0193 requires sized_range<Rng const>)
0194 {
0195 return ranges::size(this->base());
0196 }
0197 };
0198
0199 template<typename Rng, typename Fun>
0200 struct transform_view : iter_transform_view<Rng, indirected<Fun>>
0201 {
0202 transform_view() = default;
0203 transform_view(Rng rng, Fun fun)
0204 : iter_transform_view<Rng, indirected<Fun>>{std::move(rng),
0205 indirect(std::move(fun))}
0206 {}
0207 };
0208
0209 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0210 template(typename Rng, typename Fun)(
0211 requires copy_constructible<Fun>)
0212 transform_view(Rng &&, Fun)
0213 -> transform_view<views::all_t<Rng>, Fun>;
0214 #endif
0215
0216 template<typename Rng1, typename Rng2, typename Fun>
0217 struct iter_transform2_view
0218 : view_facade<iter_transform2_view<Rng1, Rng2, Fun>,
0219 detail::transform2_cardinality(range_cardinality<Rng1>::value,
0220 range_cardinality<Rng2>::value)>
0221 {
0222 private:
0223 friend range_access;
0224 RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Fun> fun_;
0225 Rng1 rng1_;
0226 Rng2 rng2_;
0227 using difference_type_ =
0228 common_type_t<range_difference_t<Rng1>, range_difference_t<Rng2>>;
0229
0230 static constexpr cardinality my_cardinality = detail::transform2_cardinality(
0231 range_cardinality<Rng1>::value, range_cardinality<Rng2>::value);
0232
0233 template<bool>
0234 struct cursor;
0235
0236 template<bool Const>
0237 struct sentinel
0238 {
0239 private:
0240 friend struct cursor<Const>;
0241 sentinel_t<meta::const_if_c<Const, Rng1>> end1_;
0242 sentinel_t<meta::const_if_c<Const, Rng2>> end2_;
0243
0244 public:
0245 sentinel() = default;
0246 sentinel(meta::const_if_c<Const, iter_transform2_view> * parent,
0247 decltype(ranges::end))
0248 : end1_(end(parent->rng1_))
0249 , end2_(end(parent->rng2_))
0250 {}
0251 template(bool Other)(
0252 requires Const AND CPP_NOT(Other))
0253 sentinel(sentinel<Other> that)
0254 : end1_(std::move(that.end1_))
0255 , end2_(std::move(that.end2_))
0256 {}
0257 };
0258
0259 template<bool Const>
0260 struct cursor
0261 {
0262 private:
0263 using fun_ref_ = semiregular_box_ref_or_val_t<Fun, Const>;
0264 using R1 = meta::const_if_c<Const, Rng1>;
0265 using R2 = meta::const_if_c<Const, Rng2>;
0266 fun_ref_ fun_;
0267 iterator_t<R1> it1_;
0268 iterator_t<R2> it2_;
0269
0270 public:
0271 using difference_type = difference_type_;
0272 using single_pass = meta::or_c<(bool)single_pass_iterator_<iterator_t<R1>>,
0273 (bool)single_pass_iterator_<iterator_t<R2>>>;
0274 using value_type =
0275 detail::decay_t<invoke_result_t<meta::const_if_c<Const, Fun> &, copy_tag,
0276 iterator_t<R1>, iterator_t<R2>>>;
0277
0278 cursor() = default;
0279 template<typename BeginEndFn>
0280 cursor(meta::const_if_c<Const, iter_transform2_view> * parent,
0281 BeginEndFn begin_end)
0282 : fun_(parent->fun_)
0283 , it1_(begin_end(parent->rng1_))
0284 , it2_(begin_end(parent->rng2_))
0285 {}
0286 template(bool Other)(
0287 requires Const AND CPP_NOT(Other))
0288 cursor(cursor<Other> that)
0289 : fun_(std::move(that.fun_))
0290 , it1_(std::move(that.end1_))
0291 , it2_(std::move(that.end2_))
0292 {}
0293
0294 auto CPP_auto_fun(read)()(const)
0295 (
0296 return invoke(fun_, it1_, it2_)
0297 )
0298
0299 void next()
0300 {
0301 ++it1_;
0302 ++it2_;
0303 }
0304 CPP_member
0305 auto equal(cursor const & that) const
0306 -> CPP_ret(bool)(
0307 requires forward_range<Rng1> && forward_range<Rng2>)
0308 {
0309
0310
0311
0312 return it1_ == that.it1_ || it2_ == that.it2_;
0313 }
0314 bool equal(sentinel<Const> const & s) const
0315 {
0316
0317
0318
0319 return it1_ == s.end1_ || it2_ == s.end2_;
0320 }
0321 CPP_member
0322 auto prev()
0323 -> CPP_ret(void)(
0324 requires bidirectional_range<R1> && bidirectional_range<R2>)
0325 {
0326 --it1_;
0327 --it2_;
0328 }
0329 CPP_member
0330 auto advance(difference_type n) -> CPP_ret(void)(
0331 requires random_access_range<R1> && random_access_range<R2>)
0332 {
0333 ranges::advance(it1_, n);
0334 ranges::advance(it2_, n);
0335 }
0336 CPP_member
0337 auto distance_to(cursor const & that) const
0338 -> CPP_ret(difference_type)(
0339 requires sized_sentinel_for<iterator_t<R1>, iterator_t<R1>> &&
0340 sized_sentinel_for<iterator_t<R2>, iterator_t<R2>>)
0341 {
0342
0343
0344 difference_type d1 = that.it1_ - it1_, d2 = that.it2_ - it2_;
0345 return 0 < d1 ? ranges::min(d1, d2) : ranges::max(d1, d2);
0346 }
0347
0348 auto CPP_auto_fun(move)()(const)
0349 (
0350 return invoke(fun_, move_tag{}, it1_, it2_)
0351 )
0352
0353 };
0354
0355 template<bool Const>
0356 using end_cursor_t = meta::if_c<
0357 common_range<meta::const_if_c<Const, Rng1>> &&
0358 common_range<meta::const_if_c<Const, Rng2>> &&
0359 !single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng1>>> &&
0360 !single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng2>>>,
0361 cursor<Const>, sentinel<Const>>;
0362
0363 cursor<simple_view<Rng1>() && simple_view<Rng2>()> begin_cursor()
0364 {
0365 return {this, ranges::begin};
0366 }
0367 end_cursor_t<simple_view<Rng1>() && simple_view<Rng2>()> end_cursor()
0368 {
0369 return {this, ranges::end};
0370 }
0371 template(bool Const = true)(
0372 requires Const AND range<meta::const_if_c<Const, Rng1>> AND
0373 range<meta::const_if_c<Const, Rng2>> AND
0374 detail::iter_transform_2_readable<
0375 Fun const,
0376 meta::const_if_c<Const, Rng1>,
0377 meta::const_if_c<Const, Rng2>>)
0378 cursor<true> begin_cursor() const
0379 {
0380 return {this, ranges::begin};
0381 }
0382 template(bool Const = true)(
0383 requires Const AND range<meta::const_if_c<Const, Rng1>> AND
0384 range<meta::const_if_c<Const, Rng2>> AND
0385 detail::iter_transform_2_readable<
0386 Fun const,
0387 meta::const_if_c<Const, Rng1>,
0388 meta::const_if_c<Const, Rng2>>)
0389 end_cursor_t<Const> end_cursor() const
0390 {
0391 return {this, ranges::end};
0392 }
0393 template<typename Self>
0394 static constexpr auto size_(Self & self)
0395 {
0396 using size_type = common_type_t<range_size_t<Rng1>, range_size_t<Rng2>>;
0397 return ranges::min(static_cast<size_type>(ranges::size(self.rng1_)),
0398 static_cast<size_type>(ranges::size(self.rng2_)));
0399 }
0400
0401 template<bool B>
0402 using R1 = meta::invoke<detail::dependent_<B>, Rng1>;
0403 template<bool B>
0404 using R2 = meta::invoke<detail::dependent_<B>, Rng2>;
0405
0406 public:
0407 iter_transform2_view() = default;
0408 constexpr iter_transform2_view(Rng1 rng1, Rng2 rng2, Fun fun)
0409 : fun_(std::move(fun))
0410 , rng1_(std::move(rng1))
0411 , rng2_(std::move(rng2))
0412 {}
0413 CPP_member
0414 static constexpr auto size()
0415 -> CPP_ret(std::size_t)(
0416 requires (my_cardinality >= 0))
0417 {
0418 return static_cast<std::size_t>(my_cardinality);
0419 }
0420 template(bool True = true)(
0421 requires (my_cardinality < 0) AND sized_range<Rng1 const> AND
0422 sized_range<Rng2 const> AND
0423 common_with<range_size_t<R1<True>>, range_size_t<R2<True>>>)
0424 constexpr auto size() const
0425 {
0426 return size_(*this);
0427 }
0428 template(bool True = true)(
0429 requires (my_cardinality < 0) AND sized_range<Rng1> AND sized_range<Rng2> AND
0430 common_with<range_size_t<R1<True>>, range_size_t<R2<True>>>)
0431 constexpr auto size()
0432 {
0433 return size_(*this);
0434 }
0435 };
0436
0437 template<typename Rng1, typename Rng2, typename Fun>
0438 struct transform2_view : iter_transform2_view<Rng1, Rng2, indirected<Fun>>
0439 {
0440 transform2_view() = default;
0441 constexpr transform2_view(Rng1 rng1, Rng2 rng2, Fun fun)
0442 : iter_transform2_view<Rng1, Rng2, indirected<Fun>>{std::move(rng1),
0443 std::move(rng2),
0444 indirect(std::move(fun))}
0445 {}
0446 };
0447
0448 namespace views
0449 {
0450 struct iter_transform_base_fn
0451 {
0452 template(typename Rng, typename Fun)(
0453 requires viewable_range<Rng> AND input_range<Rng> AND
0454 copy_constructible<Fun> AND
0455 detail::iter_transform_1_readable<Fun, Rng>)
0456 constexpr iter_transform_view<all_t<Rng>, Fun>
0457 operator()(Rng && rng, Fun fun) const
0458 {
0459 return {all(static_cast<Rng &&>(rng)), std::move(fun)};
0460 }
0461
0462 template(typename Rng1, typename Rng2, typename Fun)(
0463 requires viewable_range<Rng1> AND input_range<Rng1> AND
0464 viewable_range<Rng2> AND input_range<Rng2> AND
0465 copy_constructible<Fun> AND
0466 common_with<range_difference_t<Rng1>, range_difference_t<Rng1>> AND
0467 detail::iter_transform_2_readable<Fun, Rng1, Rng2>)
0468 constexpr iter_transform2_view<all_t<Rng1>, all_t<Rng2>, Fun>
0469 operator()(Rng1 && rng1, Rng2 && rng2, Fun fun) const
0470 {
0471 return {all(static_cast<Rng1 &&>(rng1)),
0472 all(static_cast<Rng2 &&>(rng2)),
0473 std::move(fun)};
0474 }
0475 };
0476
0477 struct iter_transform_fn : iter_transform_base_fn
0478 {
0479 using iter_transform_base_fn::operator();
0480
0481 template<typename Fun>
0482 constexpr auto operator()(Fun fun) const
0483 {
0484 return make_view_closure(
0485 bind_back(iter_transform_base_fn{}, std::move(fun)));
0486 }
0487 };
0488
0489
0490
0491 RANGES_INLINE_VARIABLE(iter_transform_fn, iter_transform)
0492
0493
0494
0495
0496
0497
0498 template(typename Rng, typename Fun)(
0499 concept (transformable_range_)(Rng, Fun),
0500 regular_invocable<Fun &, range_reference_t<Rng>> AND
0501 (!std::is_void<indirect_result_t<Fun &, iterator_t<Rng>>>::value)
0502 );
0503
0504
0505 template<typename Rng, typename Fun>
0506 CPP_concept transformable_range =
0507 viewable_range<Rng> && input_range<Rng> &&
0508 copy_constructible<Fun> &&
0509 CPP_concept_ref(views::transformable_range_, Rng, Fun);
0510
0511
0512
0513 template(typename Rng1, typename Rng2, typename Fun)(
0514 concept (transformable_ranges_)(Rng1, Rng2, Fun),
0515 regular_invocable<Fun &, range_reference_t<Rng1>, range_reference_t<Rng2>> AND
0516 (!std::is_void<
0517 indirect_result_t<Fun &, iterator_t<Rng1>, iterator_t<Rng2>>>::value)
0518 );
0519
0520
0521 template<typename Rng1, typename Rng2, typename Fun>
0522 CPP_concept transformable_ranges =
0523 viewable_range<Rng1> && input_range<Rng1> &&
0524 viewable_range<Rng2> && input_range<Rng2> &&
0525 copy_constructible<Fun> &&
0526 CPP_concept_ref(views::transformable_ranges_, Rng1, Rng2, Fun);
0527
0528
0529 struct transform_base_fn
0530 {
0531 template(typename Rng, typename Fun)(
0532 requires transformable_range<Rng, Fun>)
0533 constexpr transform_view<all_t<Rng>, Fun> operator()(Rng && rng, Fun fun)
0534 const
0535 {
0536 return {all(static_cast<Rng &&>(rng)), std::move(fun)};
0537 }
0538
0539 template(typename Rng1, typename Rng2, typename Fun)(
0540 requires transformable_ranges<Rng1, Rng2, Fun>)
0541 constexpr transform2_view<all_t<Rng1>, all_t<Rng2>, Fun>
0542 operator()(Rng1 && rng1, Rng2 && rng2, Fun fun) const
0543 {
0544 return {all(static_cast<Rng1 &&>(rng1)),
0545 all(static_cast<Rng2 &&>(rng2)),
0546 std::move(fun)};
0547 }
0548 };
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581 struct transform_fn : transform_base_fn
0582 {
0583 using transform_base_fn::operator();
0584
0585 template<typename Fun>
0586 constexpr auto operator()(Fun fun) const
0587 {
0588 return make_view_closure(bind_back(transform_base_fn{}, std::move(fun)));
0589 }
0590 };
0591
0592
0593
0594 RANGES_INLINE_VARIABLE(transform_fn, transform)
0595 }
0596
0597 namespace cpp20
0598 {
0599 namespace views
0600 {
0601 using ranges::views::transform;
0602 }
0603 template(typename Rng, typename F)(
0604 requires input_range<Rng> AND copy_constructible<F> AND view_<Rng> AND
0605 std::is_object<F>::value AND
0606 regular_invocable<F &, iter_reference_t<iterator_t<Rng>>>)
0607 using transform_view = ranges::transform_view<Rng, F>;
0608 }
0609
0610 }
0611
0612 #include <range/v3/detail/epilogue.hpp>
0613
0614 #include <range/v3/detail/satisfy_boost_range.hpp>
0615 RANGES_SATISFY_BOOST_RANGE(::ranges::iter_transform_view)
0616 RANGES_SATISFY_BOOST_RANGE(::ranges::transform_view)
0617
0618 #endif