Back to home page

EIC code displayed by LXR

 
 

    


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 /// \file
0002 // Range v3 library
0003 //
0004 // Copyright Eric Niebler 2014-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
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     /// \cond
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  // ^^^ workaround ^^^ / vvv no workaround vvv
0094             using value_type = typename Adapt::value_type;
0095 #endif // RANGES_WORKAROUND_MSVC_688606
0096             compressed_pair<BaseIter, Adapt> data_;
0097         };
0098     } // namespace detail
0099     /// \endcond
0100 
0101     /// \addtogroup group-views
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         // clang-format off
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             // clang-format on
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     // Build a sentinel out of a sentinel into the adapted range, and an
0178     // adaptor that customizes behavior.
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         // All sentinels into adapted ranges have a base() member for fetching
0194         // the underlying sentinel.
0195         BaseSent base() const
0196         {
0197             return data_.first();
0198         }
0199 
0200     protected:
0201         // Adaptor accessor
0202         Adapt & get()
0203         {
0204             return data_.second();
0205         }
0206         Adapt const & get() const
0207         {
0208             return data_.second();
0209         }
0210     };
0211 
0212     /// \cond
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     } // namespace detail
0230     /// \endcond
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     // Build a cursor out of an iterator into the adapted range, and an
0239     // adaptor that customizes behavior.
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             // All iterators into adapted ranges have a base() member for fetching
0265             // the underlying iterator.
0266             BaseIter base() const
0267             {
0268                 return basic_adaptor_mixin::basic_mixin::get().data_.first();
0269             }
0270 
0271         protected:
0272             // Adaptor accessor
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         // If the adaptor has an iter_move function, use it.
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         // If there is no iter_move member and the adaptor has not overridden the read
0409         // member function, then dispatch to the base iterator's iter_move function.
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         // If the adaptor does not have an iter_move function but overrides the read
0421         // member function, apply std::move to the result of calling read.
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         // Gives users a way to override the default iter_move function in their adaptors.
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 /*= range_cardinality<BaseRng>::value*/>
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         /// \overload
0564         constexpr base_range_t const & base() const noexcept
0565         {
0566             return rng_;
0567         }
0568     };
0569 
0570     /// @}
0571 } // namespace ranges
0572 
0573 #include <range/v3/detail/epilogue.hpp>
0574 
0575 #endif