Warning, file /include/range/v3/view/adaptor.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef RANGES_V3_VIEW_ADAPTOR_HPP
0014 #define RANGES_V3_VIEW_ADAPTOR_HPP
0015
0016 #include <meta/meta.hpp>
0017
0018 #include <concepts/concepts.hpp>
0019
0020 #include <range/v3/range_fwd.hpp>
0021
0022 #include <range/v3/iterator/concepts.hpp>
0023 #include <range/v3/iterator/operations.hpp>
0024 #include <range/v3/iterator/traits.hpp>
0025 #include <range/v3/range/primitives.hpp>
0026 #include <range/v3/range/traits.hpp>
0027 #include <range/v3/utility/compressed_pair.hpp>
0028 #include <range/v3/view/all.hpp>
0029 #include <range/v3/view/facade.hpp>
0030
0031 #include <range/v3/detail/prologue.hpp>
0032
0033 namespace ranges
0034 {
0035
0036 namespace detail
0037 {
0038 template<typename Derived>
0039 using begin_adaptor_t = detail::decay_t<decltype(
0040 range_access::begin_adaptor(std::declval<Derived &>()))>;
0041
0042 template<typename Derived>
0043 using end_adaptor_t = detail::decay_t<decltype(
0044 range_access::end_adaptor(std::declval<Derived &>()))>;
0045
0046 template<typename Derived>
0047 using adapted_iterator_t = detail::decay_t<decltype(
0048 std::declval<begin_adaptor_t<Derived>>().begin(std::declval<Derived &>()))>;
0049
0050 template<typename Derived>
0051 using adapted_sentinel_t = detail::decay_t<decltype(
0052 std::declval<end_adaptor_t<Derived>>().end(std::declval<Derived &>()))>;
0053
0054 struct adaptor_base_current_mem_fn
0055 {};
0056
0057 template<typename BaseIter, typename Adapt>
0058 constexpr int which_adaptor_value_(priority_tag<0>)
0059 {
0060 return 0;
0061 }
0062 template<typename BaseIter, typename Adapt>
0063 constexpr always_<int, decltype(Adapt::read(std::declval<BaseIter const &>(),
0064 adaptor_base_current_mem_fn{}))>
0065 which_adaptor_value_(priority_tag<1>)
0066 {
0067 return 1;
0068 }
0069 template<typename BaseIter, typename Adapt>
0070 constexpr always_<int, typename Adapt::value_type>
0071 which_adaptor_value_(priority_tag<2>)
0072 {
0073 return 2;
0074 }
0075
0076 template<typename BaseIter, typename Adapt,
0077 int = detail::which_adaptor_value_<BaseIter, Adapt>(priority_tag<2>{})>
0078 struct adaptor_value_type_
0079 {
0080 compressed_pair<BaseIter, Adapt> data_;
0081 };
0082 template<typename BaseIter, typename Adapt>
0083 struct adaptor_value_type_<BaseIter, Adapt, 1>
0084 {
0085 using value_type = iter_value_t<BaseIter>;
0086 compressed_pair<BaseIter, Adapt> data_;
0087 };
0088 template<typename BaseIter, typename Adapt>
0089 struct adaptor_value_type_<BaseIter, Adapt, 2>
0090 {
0091 #ifdef RANGES_WORKAROUND_MSVC_688606
0092 using value_type = typename indirectly_readable_traits<Adapt>::value_type;
0093 #else
0094 using value_type = typename Adapt::value_type;
0095 #endif
0096 compressed_pair<BaseIter, Adapt> data_;
0097 };
0098 }
0099
0100
0101
0102
0103 template<typename BaseIt, typename Adapt>
0104 struct adaptor_cursor;
0105
0106 template<typename BaseSent, typename Adapt>
0107 struct base_adaptor_sentinel;
0108
0109 struct adaptor_base
0110 {
0111 adaptor_base() = default;
0112 adaptor_base(adaptor_base &&) = default;
0113 adaptor_base(adaptor_base const &) = default;
0114 adaptor_base & operator=(adaptor_base &&) = default;
0115 adaptor_base & operator=(adaptor_base const &) = default;
0116
0117 adaptor_base(detail::ignore_t, detail::ignore_t = {}, detail::ignore_t = {})
0118 {}
0119
0120 template<typename Rng>
0121 static constexpr auto CPP_auto_fun(begin)(Rng &rng)
0122 (
0123 return ranges::begin(rng.base())
0124 )
0125 template<typename Rng>
0126 static constexpr auto CPP_auto_fun(end)(Rng &rng)
0127 (
0128 return ranges::end(rng.base())
0129 )
0130
0131 template(typename I)(
0132 requires equality_comparable<I>)
0133 static bool equal(I const & it0, I const & it1)
0134 {
0135 return it0 == it1;
0136 }
0137 template(typename I)(
0138 requires input_or_output_iterator<I>)
0139 static iter_reference_t<I> read(I const & it,
0140 detail::adaptor_base_current_mem_fn = {})
0141 noexcept(noexcept(iter_reference_t<I>(*it)))
0142 {
0143 return *it;
0144 }
0145 template(typename I)(
0146 requires input_or_output_iterator<I>)
0147 static void next(I & it)
0148 {
0149 ++it;
0150 }
0151 template(typename I)(
0152 requires bidirectional_iterator<I>)
0153 static void prev(I & it)
0154 {
0155 --it;
0156 }
0157 template(typename I)(
0158 requires random_access_iterator<I>)
0159 static void advance(I & it, iter_difference_t<I> n)
0160 {
0161 it += n;
0162 }
0163 template(typename I)(
0164 requires sized_sentinel_for<I, I>)
0165 static iter_difference_t<I> distance_to(I const & it0, I const & it1)
0166 {
0167 return it1 - it0;
0168 }
0169 template(typename I, typename S)(
0170 requires sentinel_for<S, I>)
0171 static constexpr bool empty(I const & it, S const & last)
0172 {
0173 return it == last;
0174 }
0175 };
0176
0177
0178
0179 template<typename BaseSent, typename Adapt>
0180 struct base_adaptor_sentinel
0181 {
0182 private:
0183 template<typename, typename>
0184 friend struct adaptor_cursor;
0185 RANGES_NO_UNIQUE_ADDRESS compressed_pair<BaseSent, Adapt> data_;
0186
0187 public:
0188 base_adaptor_sentinel() = default;
0189 base_adaptor_sentinel(BaseSent sent, Adapt adapt)
0190 : data_{std::move(sent), std::move(adapt)}
0191 {}
0192
0193
0194
0195 BaseSent base() const
0196 {
0197 return data_.first();
0198 }
0199
0200 protected:
0201
0202 Adapt & get()
0203 {
0204 return data_.second();
0205 }
0206 Adapt const & get() const
0207 {
0208 return data_.second();
0209 }
0210 };
0211
0212
0213 namespace detail
0214 {
0215 template<typename BaseSent, typename Adapt>
0216 meta::id<base_adaptor_sentinel<BaseSent, Adapt>> base_adaptor_sentinel_2_(long);
0217
0218 template<typename BaseSent, typename Adapt>
0219 meta::id<typename Adapt::template mixin<base_adaptor_sentinel<BaseSent, Adapt>>>
0220 base_adaptor_sentinel_2_(int);
0221
0222 template<typename BaseSent, typename Adapt>
0223 struct base_adaptor_sentinel_
0224 : decltype(base_adaptor_sentinel_2_<BaseSent, Adapt>(42))
0225 {};
0226
0227 template<typename BaseSent, typename Adapt>
0228 using adaptor_sentinel_ = meta::_t<base_adaptor_sentinel_<BaseSent, Adapt>>;
0229 }
0230
0231
0232 template<typename BaseSent, typename Adapt>
0233 struct adaptor_sentinel : detail::adaptor_sentinel_<BaseSent, Adapt>
0234 {
0235 using detail::adaptor_sentinel_<BaseSent, Adapt>::adaptor_sentinel_;
0236 };
0237
0238
0239
0240 template<typename BaseIter, typename Adapt>
0241 struct adaptor_cursor : private detail::adaptor_value_type_<BaseIter, Adapt>
0242 {
0243 private:
0244 friend range_access;
0245 template<typename, typename>
0246 friend struct adaptor_cursor;
0247 using base_t = detail::adaptor_value_type_<BaseIter, Adapt>;
0248 using single_pass = meta::bool_<(bool)range_access::single_pass_t<Adapt>() ||
0249 (bool)single_pass_iterator_<BaseIter>>;
0250
0251 struct basic_adaptor_mixin : basic_mixin<adaptor_cursor>
0252 {
0253 basic_adaptor_mixin() = default;
0254 #ifndef _MSC_VER
0255 using basic_mixin<adaptor_cursor>::basic_mixin;
0256 #else
0257 constexpr explicit basic_adaptor_mixin(adaptor_cursor && cur)
0258 : basic_mixin<adaptor_cursor>(static_cast<adaptor_cursor &&>(cur))
0259 {}
0260 constexpr explicit basic_adaptor_mixin(adaptor_cursor const & cur)
0261 : basic_mixin<adaptor_cursor>(cur)
0262 {}
0263 #endif
0264
0265
0266 BaseIter base() const
0267 {
0268 return basic_adaptor_mixin::basic_mixin::get().data_.first();
0269 }
0270
0271 protected:
0272
0273 Adapt & get()
0274 {
0275 return basic_adaptor_mixin::basic_mixin::get().data_.second();
0276 }
0277 const Adapt & get() const
0278 {
0279 return basic_adaptor_mixin::basic_mixin::get().data_.second();
0280 }
0281 };
0282
0283 template<typename Adapt_>
0284 static meta::id<basic_adaptor_mixin> basic_adaptor_mixin_2_(long);
0285
0286 template<typename Adapt_>
0287 static meta::id<typename Adapt_::template mixin<basic_adaptor_mixin>>
0288 basic_adaptor_mixin_2_(int);
0289
0290 using mixin = meta::_t<decltype(basic_adaptor_mixin_2_<Adapt>(42))>;
0291
0292 template<typename A = Adapt, typename R = decltype(std::declval<A const &>().read(
0293 std::declval<BaseIter const &>()))>
0294 R read() const noexcept(
0295 noexcept(std::declval<A const &>().read(std::declval<BaseIter const &>())))
0296 {
0297 using V = range_access::cursor_value_t<adaptor_cursor>;
0298 static_assert(common_reference_with<R &&, V &>,
0299 "In your adaptor, you've specified a value type that does not "
0300 "share a common reference type with the return type of read.");
0301 return this->data_.second().read(this->data_.first());
0302 }
0303 template<typename A = Adapt, typename = decltype(std::declval<A &>().next(
0304 std::declval<BaseIter &>()))>
0305 void next()
0306 {
0307 this->data_.second().next(this->data_.first());
0308 }
0309 template<typename A = Adapt,
0310 typename = decltype(std::declval<A const &>().equal(
0311 std::declval<BaseIter const &>(), std::declval<BaseIter const &>(),
0312 std::declval<A const &>()))>
0313 bool equal_(adaptor_cursor const & that, int) const
0314 {
0315 return this->data_.second().equal(
0316 this->data_.first(), that.data_.first(), that.data_.second());
0317 }
0318 template<typename A = Adapt,
0319 typename = decltype(std::declval<A const &>().equal(
0320 std::declval<BaseIter const &>(), std::declval<BaseIter const &>()))>
0321 bool equal_(adaptor_cursor const & that, long) const
0322 {
0323 return this->data_.second().equal(this->data_.first(), that.data_.first());
0324 }
0325 template<typename C = adaptor_cursor>
0326 auto equal(adaptor_cursor const & that) const
0327 -> decltype(std::declval<C const &>().equal_(that, 42))
0328 {
0329 return this->equal_(that, 42);
0330 }
0331 template<typename S, typename A,
0332 typename = decltype(std::declval<A const &>().empty(
0333 std::declval<BaseIter const &>(), std::declval<Adapt const &>(),
0334 std::declval<S const &>()))>
0335 constexpr bool equal_(adaptor_sentinel<S, A> const & that, int) const
0336 {
0337 return that.data_.second().empty(
0338 this->data_.first(), this->data_.second(), that.data_.first());
0339 }
0340 template<typename S, typename A,
0341 typename = decltype(std::declval<A const &>().empty(
0342 std::declval<BaseIter const &>(), std::declval<S const &>()))>
0343 constexpr bool equal_(adaptor_sentinel<S, A> const & that, long) const
0344 {
0345 return that.data_.second().empty(this->data_.first(), that.data_.first());
0346 }
0347 template<typename S, typename A>
0348 constexpr auto equal(adaptor_sentinel<S, A> const & that) const
0349 -> decltype(std::declval<adaptor_cursor const &>().equal_(that, 42))
0350 {
0351 return this->equal_(that, 42);
0352 }
0353 template<typename A = Adapt, typename = decltype(std::declval<A &>().prev(
0354 std::declval<BaseIter &>()))>
0355 void prev()
0356 {
0357 this->data_.second().prev(this->data_.first());
0358 }
0359 template<typename A = Adapt, typename = decltype(std::declval<A &>().advance(
0360 std::declval<BaseIter &>(), 0))>
0361 void advance(iter_difference_t<BaseIter> n)
0362 {
0363 this->data_.second().advance(this->data_.first(), n);
0364 }
0365 template<typename A = Adapt,
0366 typename R = decltype(std::declval<A const &>().distance_to(
0367 std::declval<BaseIter const &>(), std::declval<BaseIter const &>(),
0368 std::declval<A const &>()))>
0369 R distance_to_(adaptor_cursor const & that, int) const
0370 {
0371 return this->data_.second().distance_to(
0372 this->data_.first(), that.data_.first(), that.data_.second());
0373 }
0374 template<typename A = Adapt,
0375 typename R = decltype(std::declval<A const &>().distance_to(
0376 std::declval<BaseIter const &>(), std::declval<BaseIter const &>()))>
0377 R distance_to_(adaptor_cursor const & that, long) const
0378 {
0379 return this->data_.second().distance_to(this->data_.first(),
0380 that.data_.first());
0381 }
0382 template<typename C = adaptor_cursor>
0383 auto distance_to(adaptor_cursor const & that) const
0384 -> decltype(std::declval<C const &>().distance_to_(that, 42))
0385 {
0386 return this->distance_to_(that, 42);
0387 }
0388
0389 template<typename A = Adapt,
0390 typename X = decltype(std::declval<A const &>().iter_move(
0391 std::declval<BaseIter const &>()))>
0392 X iter_move_(int) const noexcept(noexcept(
0393 std::declval<A const &>().iter_move(std::declval<BaseIter const &>())))
0394 {
0395 using V = range_access::cursor_value_t<adaptor_cursor>;
0396 using R = decltype(this->data_.second().read(this->data_.first()));
0397 static_assert(
0398 common_reference_with<X &&, V const &>,
0399 "In your adaptor, the result of your iter_move member function does "
0400 "not share a common reference with your value type.");
0401 static_assert(
0402 common_reference_with<R &&, X &&>,
0403 "In your adaptor, the result of your iter_move member function does "
0404 "not share a common reference with the result of your read member "
0405 "function.");
0406 return this->data_.second().iter_move(this->data_.first());
0407 }
0408
0409
0410 template<typename A = Adapt,
0411 typename R = decltype(std::declval<A const &>().read(
0412 std::declval<BaseIter const &>(),
0413 detail::adaptor_base_current_mem_fn{})),
0414 typename X = iter_rvalue_reference_t<BaseIter>>
0415 X iter_move_(long) const
0416 noexcept(noexcept(X(ranges::iter_move(std::declval<BaseIter const &>()))))
0417 {
0418 return ranges::iter_move(this->data_.first());
0419 }
0420
0421
0422 template<typename A = Adapt,
0423 typename R = decltype(
0424 std::declval<A const &>().read(std::declval<BaseIter const &>())),
0425 typename X = aux::move_t<R>>
0426 X iter_move_(detail::ignore_t) const noexcept(noexcept(X(static_cast<X &&>(
0427 std::declval<A const &>().read(std::declval<BaseIter const &>())))))
0428 {
0429 using V = range_access::cursor_value_t<adaptor_cursor>;
0430 static_assert(
0431 common_reference_with<X &&, V const &>,
0432 "In your adaptor, you've specified a value type that does not share a "
0433 "common "
0434 "reference type with the result of moving the result of the read member "
0435 "function. Consider defining an iter_move function in your adaptor.");
0436 return static_cast<X &&>(this->data_.second().read(this->data_.first()));
0437 }
0438
0439 auto move() const
0440 noexcept(noexcept(std::declval<const adaptor_cursor &>().iter_move_(42)))
0441 -> decltype(std::declval<const adaptor_cursor &>().iter_move_(42))
0442 {
0443 return iter_move_(42);
0444 }
0445
0446 public:
0447 adaptor_cursor() = default;
0448 adaptor_cursor(BaseIter iter, Adapt adapt)
0449 : base_t{{std::move(iter), std::move(adapt)}}
0450 {}
0451 template(typename OtherIter, typename OtherAdapt)(
0452 requires
0453 (!same_as<adaptor_cursor<OtherIter, OtherAdapt>, adaptor_cursor>) AND
0454 convertible_to<OtherIter, BaseIter> AND
0455 convertible_to<OtherAdapt, Adapt>)
0456 adaptor_cursor(adaptor_cursor<OtherIter, OtherAdapt> that)
0457 : base_t{{std::move(that.data_.first()), std::move(that.data_.second())}}
0458 {}
0459 };
0460
0461 template<typename D>
0462 using adaptor_cursor_t =
0463 adaptor_cursor<detail::adapted_iterator_t<D>, detail::begin_adaptor_t<D>>;
0464
0465 template<typename D>
0466 using adaptor_sentinel_t = meta::if_c<
0467 same_as<detail::adapted_iterator_t<D>, detail::adapted_sentinel_t<D>> &&
0468 same_as<detail::begin_adaptor_t<D>, detail::end_adaptor_t<D>>,
0469 adaptor_cursor_t<D>,
0470 adaptor_sentinel<detail::adapted_sentinel_t<D>, detail::end_adaptor_t<D>>>;
0471
0472 template<typename Derived, typename BaseRng,
0473 cardinality Cardinality >
0474 struct view_adaptor : view_facade<Derived, Cardinality>
0475 {
0476 private:
0477 friend Derived;
0478 friend range_access;
0479 friend adaptor_base;
0480 CPP_assert(viewable_range<BaseRng>);
0481 using base_range_t = views::all_t<BaseRng>;
0482 using view_facade<Derived, Cardinality>::derived;
0483
0484 base_range_t rng_;
0485
0486 constexpr adaptor_base begin_adaptor() const noexcept
0487 {
0488 return {};
0489 }
0490 constexpr adaptor_base end_adaptor() const noexcept
0491 {
0492 return {};
0493 }
0494
0495 template<typename D>
0496 static constexpr adaptor_cursor_t<D> begin_cursor_(D & d) noexcept(noexcept(
0497 adaptor_cursor_t<D>{std::declval<detail::begin_adaptor_t<D> &>().begin(d),
0498 range_access::begin_adaptor(d)}))
0499 {
0500 auto adapt = range_access::begin_adaptor(d);
0501 auto pos = adapt.begin(d);
0502 return {std::move(pos), std::move(adapt)};
0503 }
0504 template(typename D = Derived)(
0505 requires same_as<D, Derived>)
0506 constexpr auto begin_cursor() noexcept(
0507 noexcept(view_adaptor::begin_cursor_(std::declval<D &>())))
0508 -> decltype(view_adaptor::begin_cursor_(std::declval<D &>()))
0509 {
0510 return view_adaptor::begin_cursor_(derived());
0511 }
0512 template(typename D = Derived)(
0513 requires same_as<D, Derived> AND range<base_range_t const>)
0514 constexpr auto begin_cursor() const
0515 noexcept(noexcept(view_adaptor::begin_cursor_(std::declval<D const &>())))
0516 -> decltype(view_adaptor::begin_cursor_(std::declval<D const &>()))
0517 {
0518 return view_adaptor::begin_cursor_(derived());
0519 }
0520
0521 template<typename D>
0522 static constexpr adaptor_sentinel_t<D> end_cursor_(D & d) noexcept(noexcept(
0523 adaptor_sentinel_t<D>{std::declval<detail::end_adaptor_t<D> &>().end(d),
0524 range_access::end_adaptor(d)}))
0525 {
0526 auto adapt = range_access::end_adaptor(d);
0527 auto pos = adapt.end(d);
0528 return {std::move(pos), std::move(adapt)};
0529 }
0530 template(typename D = Derived)(
0531 requires same_as<D, Derived>)
0532 constexpr auto end_cursor() noexcept(
0533 noexcept(view_adaptor::end_cursor_(std::declval<D &>())))
0534 -> decltype(view_adaptor::end_cursor_(std::declval<D &>()))
0535 {
0536 return view_adaptor::end_cursor_(derived());
0537 }
0538 template(typename D = Derived)(
0539 requires same_as<D, Derived> AND range<base_range_t const>)
0540 constexpr auto end_cursor() const noexcept(
0541 noexcept(view_adaptor::end_cursor_(std::declval<D const &>())))
0542 -> decltype(view_adaptor::end_cursor_(std::declval<D const &>()))
0543 {
0544 return view_adaptor::end_cursor_(derived());
0545 }
0546
0547 protected:
0548 ~view_adaptor() = default;
0549
0550 public:
0551 view_adaptor() = default;
0552 view_adaptor(view_adaptor &&) = default;
0553 view_adaptor(view_adaptor const &) = default;
0554 view_adaptor & operator=(view_adaptor &&) = default;
0555 view_adaptor & operator=(view_adaptor const &) = default;
0556 constexpr explicit view_adaptor(BaseRng && rng)
0557 : rng_(views::all(static_cast<BaseRng &&>(rng)))
0558 {}
0559 constexpr base_range_t & base() noexcept
0560 {
0561 return rng_;
0562 }
0563
0564 constexpr base_range_t const & base() const noexcept
0565 {
0566 return rng_;
0567 }
0568 };
0569
0570
0571 }
0572
0573 #include <range/v3/detail/epilogue.hpp>
0574
0575 #endif