Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:09:55

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Andrey Diduh 2019
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 
0014 #ifndef RANGES_V3_VIEW_DROP_LAST_HPP
0015 #define RANGES_V3_VIEW_DROP_LAST_HPP
0016 
0017 #include <type_traits>
0018 
0019 #include <meta/meta.hpp>
0020 
0021 #include <range/v3/functional/bind_back.hpp>
0022 #include <range/v3/iterator/counted_iterator.hpp>
0023 #include <range/v3/iterator/default_sentinel.hpp>
0024 #include <range/v3/iterator/operations.hpp>
0025 #include <range/v3/range/access.hpp>
0026 #include <range/v3/range/concepts.hpp>
0027 #include <range/v3/range/primitives.hpp>
0028 #include <range/v3/utility/optional.hpp>
0029 #include <range/v3/utility/static_const.hpp>
0030 #include <range/v3/view/adaptor.hpp>
0031 #include <range/v3/view/all.hpp>
0032 #include <range/v3/view/interface.hpp>
0033 #include <range/v3/view/view.hpp>
0034 
0035 #include <range/v3/detail/prologue.hpp>
0036 
0037 namespace ranges
0038 {
0039     /// \addtogroup group-views
0040     /// @{
0041 
0042     /// \cond
0043     namespace detail
0044     {
0045         namespace drop_last_view
0046         {
0047             template<typename Rng>
0048             range_size_t<Rng> get_size(Rng & rng, range_difference_t<Rng> n_)
0049             {
0050                 RANGES_EXPECT(n_ >= 0);
0051                 range_size_t<Rng> const initial_size = ranges::size(rng);
0052                 range_size_t<Rng> const n = static_cast<range_size_t<Rng>>(n_);
0053                 return initial_size > n ? initial_size - n : 0;
0054             }
0055 
0056             template(typename Rng)(
0057                 requires random_access_range<Rng> AND sized_range<Rng>)
0058             iterator_t<Rng> get_end(Rng & rng, range_difference_t<Rng> n, int)
0059             {
0060                 return begin(rng) + static_cast<range_difference_t<Rng>>(
0061                                         drop_last_view::get_size(rng, n));
0062             }
0063             template(typename Rng)(
0064                 requires bidirectional_range<Rng> AND common_range<Rng>)
0065             iterator_t<Rng> get_end(Rng & rng, range_difference_t<Rng> n, long)
0066             {
0067                 return prev(end(rng), n, begin(rng));
0068             }
0069 
0070             enum class mode_enum
0071             {
0072                 bidi,
0073                 forward,
0074                 sized,
0075                 invalid
0076             };
0077 
0078             template<mode_enum Mode>
0079             using mode_t = std::integral_constant<mode_enum, Mode>;
0080 
0081             using mode_bidi = mode_t<mode_enum::bidi>;
0082             using mode_forward = mode_t<mode_enum::forward>;
0083             using mode_sized = mode_t<mode_enum::sized>;
0084             using mode_invalid = mode_t<mode_enum::invalid>;
0085 
0086             template<typename Rng>
0087             constexpr mode_enum get_mode() noexcept
0088             {
0089                 // keep range bound
0090                 // Sized Bidi O(N)
0091                 return (random_access_range<Rng> && view_<Rng> && sized_range<Rng>) ||
0092                                (bidirectional_range<Rng> && view_<Rng> &&
0093                                 common_range<Rng>)
0094                            ? mode_enum::bidi                        //
0095                            : sized_range<Rng> && view_<Rng>         //
0096                                  ? mode_enum::sized                 //
0097                                  : forward_range<Rng> && view_<Rng> //
0098                                        ? mode_enum::forward         //
0099                                        : mode_enum::invalid;        //
0100 
0101                 // max performance
0102                 // Sized Bidi O(1)
0103                 // Sized Bidi use mode::sized instead of mode::bidi - thus become unbound.
0104                 /*return (random_access_range<Rng> && view_<Rng> && sized_range<Rng> &&
0105                    view_<Rng>) || (bidirectional_range<Rng> && view_<Rng> &&
0106                    common_range<Rng> && view_<Rng>) ? mode::bidi : sized_range<Rng> &&
0107                    view_<Rng> ? mode::sized : bidirectional_range<Rng> && view_<Rng> &&
0108                    common_range<Rng> && view_<Rng> ? mode::bidi : forward_range<Rng> &&
0109                    view_<Rng> ? mode::forward : mode::invalid;*/
0110             }
0111 
0112             template<typename Rng>
0113             using mode_of = mode_t<drop_last_view::get_mode<Rng>()>;
0114         } // namespace drop_last_view
0115     }     // namespace detail
0116     /// \endcond
0117 
0118     template<typename Rng, typename = detail::drop_last_view::mode_of<Rng>>
0119     struct drop_last_view
0120     {};
0121 
0122     template<typename Rng>
0123     struct drop_last_view<Rng, detail::drop_last_view::mode_bidi>
0124       : view_interface<drop_last_view<Rng, detail::drop_last_view::mode_bidi>,
0125                        is_finite<Rng>::value
0126                            ? finite
0127                            : range_cardinality<Rng>::value> // finite at best
0128     {
0129         CPP_assert(
0130             (random_access_range<Rng> && view_<Rng> && sized_range<Rng>) ||
0131             (bidirectional_range<Rng> && view_<Rng> && common_range<Rng>));
0132 
0133     private:
0134         friend range_access;
0135         using difference_t = range_difference_t<Rng>;
0136 
0137         Rng rng_;
0138         difference_t n_;
0139         detail::non_propagating_cache<iterator_t<Rng>> end_;
0140 
0141     public:
0142         drop_last_view() = default;
0143         constexpr drop_last_view(Rng rng, difference_t n)
0144           : rng_(std::move(rng))
0145           , n_(n)
0146         {
0147             RANGES_EXPECT(n >= 0);
0148         }
0149 
0150         iterator_t<Rng> begin()
0151         {
0152             return ranges::begin(rng_);
0153         }
0154         sentinel_t<Rng> end()
0155         {
0156             if(!end_)
0157                 end_ = detail::drop_last_view::get_end(rng_, n_, 0);
0158             return *end_;
0159         }
0160         template(typename CRng = Rng const)(
0161             requires random_access_range<CRng> AND sized_range<CRng>)
0162         iterator_t<CRng> begin() const
0163         {
0164             return ranges::begin(rng_);
0165         }
0166         template(typename CRng = Rng const)(
0167             requires random_access_range<CRng> AND sized_range<CRng>)
0168         iterator_t<CRng> end() const
0169         {
0170             return detail::drop_last_view::get_end(rng_, n_, 0);
0171         }
0172 
0173         CPP_auto_member
0174         auto CPP_fun(size)()(
0175             requires sized_range<Rng>)
0176         {
0177             return detail::drop_last_view::get_size(rng_, n_);
0178         }
0179         CPP_auto_member
0180         auto CPP_fun(size)()(const //
0181             requires sized_range<Rng const>)
0182         {
0183             return detail::drop_last_view::get_size(rng_, n_);
0184         }
0185 
0186         Rng & base()
0187         {
0188             return rng_;
0189         }
0190         Rng const & base() const
0191         {
0192             return rng_;
0193         }
0194     };
0195 
0196     template<typename Rng>
0197     struct drop_last_view<Rng, detail::drop_last_view::mode_forward>
0198       : view_adaptor<drop_last_view<Rng, detail::drop_last_view::mode_forward>, Rng,
0199                      is_finite<Rng>::value
0200                          ? finite
0201                          : range_cardinality<Rng>::value> // finite at best (but
0202                                                           // unknown is expected)
0203     {
0204         CPP_assert(forward_range<Rng> && view_<Rng>);
0205 
0206     private:
0207         friend range_access;
0208 
0209         using difference_t = range_difference_t<Rng>;
0210         difference_t n_;
0211         detail::non_propagating_cache<iterator_t<Rng>> probe_begin;
0212 
0213         struct adaptor : adaptor_base
0214         {
0215             iterator_t<Rng> probe_;
0216 
0217             adaptor() = default;
0218             adaptor(iterator_t<Rng> probe_first)
0219               : probe_(std::move(probe_first))
0220             {}
0221             void next(iterator_t<Rng> & it)
0222             {
0223                 ++it;
0224                 ++probe_;
0225             }
0226         };
0227 
0228         struct sentinel_adaptor : adaptor_base
0229         {
0230             template<typename I, typename S>
0231             bool empty(I const &, adaptor const & ia, S const & s) const
0232             {
0233                 return ia.probe_ == s;
0234             }
0235         };
0236 
0237         adaptor begin_adaptor()
0238         {
0239             if(!probe_begin)
0240                 probe_begin = next(begin(this->base()), n_, end(this->base()));
0241             return {*probe_begin};
0242         }
0243         sentinel_adaptor end_adaptor()
0244         {
0245             return {};
0246         }
0247 
0248     public:
0249         drop_last_view() = default;
0250         constexpr drop_last_view(Rng rng, difference_t n)
0251           : drop_last_view::view_adaptor(std::move(rng))
0252           , n_(n)
0253         {
0254             RANGES_EXPECT(n >= 0);
0255         }
0256 
0257         CPP_auto_member
0258         auto CPP_fun(size)()(
0259             requires sized_range<Rng>)
0260         {
0261             return detail::drop_last_view::get_size(this->base(), n_);
0262         }
0263         CPP_auto_member
0264         auto CPP_fun(size)()(const //
0265             requires sized_range<Rng const>)
0266         {
0267             return detail::drop_last_view::get_size(this->base(), n_);
0268         }
0269     };
0270 
0271     template<typename Rng>
0272     struct drop_last_view<Rng, detail::drop_last_view::mode_sized>
0273       : view_interface<drop_last_view<Rng, detail::drop_last_view::mode_sized>, finite>
0274     {
0275         CPP_assert(sized_range<Rng> && view_<Rng>);
0276 
0277     private:
0278         friend range_access;
0279 
0280         using difference_t = range_difference_t<Rng>;
0281         Rng rng_;
0282         difference_t n_;
0283 
0284     public:
0285         drop_last_view() = default;
0286         constexpr drop_last_view(Rng rng, difference_t n)
0287           : rng_(std::move(rng))
0288           , n_(n)
0289         {
0290             RANGES_EXPECT(n >= 0);
0291         }
0292 
0293         counted_iterator<iterator_t<Rng>> begin()
0294         {
0295             return {ranges::begin(rng_), static_cast<difference_t>(size())};
0296         }
0297         template(typename CRng = Rng const)(
0298             requires sized_range<CRng>)
0299         counted_iterator<iterator_t<CRng>> begin() const
0300         {
0301             return {ranges::begin(rng_), static_cast<difference_t>(size())};
0302         }
0303         default_sentinel_t end() const
0304         {
0305             return {};
0306         }
0307         range_size_t<Rng> size()
0308         {
0309             return detail::drop_last_view::get_size(this->base(), n_);
0310         }
0311         CPP_auto_member
0312         auto CPP_fun(size)()(const //
0313             requires sized_range<Rng const>)
0314         {
0315             return detail::drop_last_view::get_size(this->base(), n_);
0316         }
0317 
0318         Rng & base()
0319         {
0320             return rng_;
0321         }
0322         Rng const & base() const
0323         {
0324             return rng_;
0325         }
0326     };
0327 
0328     template<typename Rng, typename T>
0329     RANGES_INLINE_VAR constexpr bool enable_borrowed_range<drop_last_view<Rng, T>> = //
0330         enable_borrowed_range<Rng>;
0331 
0332 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0333     template<typename Rng>
0334     drop_last_view(Rng &&, range_difference_t<Rng>)
0335         -> drop_last_view<views::all_t<Rng>>;
0336 #endif
0337 
0338     namespace views
0339     {
0340         struct drop_last_base_fn
0341         {
0342             template(typename Rng)(
0343                 requires sized_range<Rng> || forward_range<Rng>)
0344             constexpr auto operator()(Rng && rng, range_difference_t<Rng> n) const
0345                 -> drop_last_view<all_t<Rng>>
0346             {
0347                 return {all(static_cast<Rng &&>(rng)), n};
0348             }
0349         };
0350 
0351         struct drop_last_fn : drop_last_base_fn
0352         {
0353             using drop_last_base_fn::operator();
0354 
0355             template(typename Int)(
0356                 requires detail::integer_like_<Int>)
0357             constexpr auto operator()(Int n) const
0358             {
0359                 return make_view_closure(bind_back(drop_last_base_fn{}, n));
0360             }
0361         };
0362 
0363         RANGES_INLINE_VARIABLE(drop_last_fn, drop_last)
0364     } // namespace views
0365 
0366     /// @}
0367 } // namespace ranges
0368 
0369 #include <range/v3/detail/epilogue.hpp>
0370 #include <range/v3/detail/satisfy_boost_range.hpp>
0371 RANGES_SATISFY_BOOST_RANGE(::ranges::drop_last_view)
0372 
0373 #endif