Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Eric Niebler 2013-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 
0014 #ifndef RANGES_V3_VIEW_SLICE_HPP
0015 #define RANGES_V3_VIEW_SLICE_HPP
0016 
0017 #include <type_traits>
0018 
0019 #include <meta/meta.hpp>
0020 
0021 #include <range/v3/range_fwd.hpp>
0022 
0023 #include <range/v3/functional/bind_back.hpp>
0024 #include <range/v3/iterator/counted_iterator.hpp>
0025 #include <range/v3/iterator/default_sentinel.hpp>
0026 #include <range/v3/iterator/operations.hpp>
0027 #include <range/v3/iterator/traits.hpp>
0028 #include <range/v3/range/concepts.hpp>
0029 #include <range/v3/range/traits.hpp>
0030 #include <range/v3/utility/optional.hpp>
0031 #include <range/v3/utility/static_const.hpp>
0032 #include <range/v3/view/all.hpp>
0033 #include <range/v3/view/drop_exactly.hpp>
0034 #include <range/v3/view/facade.hpp>
0035 #include <range/v3/view/subrange.hpp>
0036 #include <range/v3/view/view.hpp>
0037 
0038 #include <range/v3/detail/prologue.hpp>
0039 
0040 namespace ranges
0041 {
0042     /// \cond
0043     namespace detail
0044     {
0045         template<typename Rng, typename Int>
0046         iterator_t<Rng> pos_at_(Rng && rng, Int i, input_range_tag, std::true_type)
0047         {
0048             RANGES_EXPECT(0 <= i);
0049             return next(ranges::begin(rng), i);
0050         }
0051 
0052         template<typename Rng, typename Int>
0053         iterator_t<Rng> pos_at_(Rng && rng, Int i, bidirectional_range_tag,
0054                                 std::false_type)
0055         {
0056             if(0 > i)
0057             {
0058                 // If it's not common and we know the size, faster to count from the front
0059                 if(RANGES_CONSTEXPR_IF(sized_range<Rng> && !common_range<Rng>))
0060                     return next(ranges::begin(rng), distance(rng) + i);
0061                 // Otherwise, probably faster to count from the back.
0062                 return next(ranges::next(ranges::begin(rng), ranges::end(rng)), i);
0063             }
0064             return next(ranges::begin(rng), i);
0065         }
0066 
0067         template<typename Rng, typename Int>
0068         iterator_t<Rng> pos_at_(Rng && rng, Int i, input_range_tag, std::false_type)
0069         {
0070             RANGES_EXPECT(i >= 0 || (bool)sized_range<Rng> || (bool)forward_range<Rng>);
0071             if(0 > i)
0072                 return next(ranges::begin(rng), distance(rng) + i);
0073             return next(ranges::begin(rng), i);
0074         }
0075 
0076         template<typename Rng, bool IsRandomAccess>
0077         struct slice_view_ : view_facade<slice_view<Rng>, finite>
0078         {
0079         private:
0080             friend range_access;
0081             Rng rng_;
0082             range_difference_t<Rng> from_, count_;
0083             detail::non_propagating_cache<iterator_t<Rng>> begin_;
0084 
0085             iterator_t<Rng> get_begin_()
0086             {
0087                 if(!begin_)
0088                     begin_ = detail::pos_at_(
0089                         rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
0090                 return *begin_;
0091             }
0092 
0093         public:
0094             slice_view_() = default;
0095             constexpr slice_view_(Rng rng, range_difference_t<Rng> from,
0096                                   range_difference_t<Rng> count)
0097               : rng_(std::move(rng))
0098               , from_(from)
0099               , count_(count)
0100             {}
0101             counted_iterator<iterator_t<Rng>> begin()
0102             {
0103                 return make_counted_iterator(get_begin_(), count_);
0104             }
0105             default_sentinel_t end()
0106             {
0107                 return {};
0108             }
0109             auto size() const
0110             {
0111                 return static_cast<detail::iter_size_t<iterator_t<Rng>>>(count_);
0112             }
0113             Rng base() const
0114             {
0115                 return rng_;
0116             }
0117         };
0118 
0119         template<typename Rng>
0120         struct slice_view_<Rng, true> : view_interface<slice_view<Rng>, finite>
0121         {
0122         private:
0123             Rng rng_;
0124             range_difference_t<Rng> from_, count_;
0125 
0126         public:
0127             slice_view_() = default;
0128             constexpr slice_view_(Rng rng, range_difference_t<Rng> from,
0129                                   range_difference_t<Rng> count)
0130               : rng_(std::move(rng))
0131               , from_(from)
0132               , count_(count)
0133             {
0134                 RANGES_EXPECT(0 <= count_);
0135             }
0136             iterator_t<Rng> begin()
0137             {
0138                 return detail::pos_at_(
0139                     rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
0140             }
0141             iterator_t<Rng> end()
0142             {
0143                 return detail::pos_at_(
0144                            rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{}) +
0145                        count_;
0146             }
0147             template(typename BaseRng = Rng)(
0148                 requires range<BaseRng const>)
0149             iterator_t<BaseRng const> begin() const
0150             {
0151                 return detail::pos_at_(
0152                     rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{});
0153             }
0154             template(typename BaseRng = Rng)(
0155                 requires range<BaseRng const>)
0156             iterator_t<BaseRng const> end() const
0157             {
0158                 return detail::pos_at_(
0159                            rng_, from_, range_tag_of<Rng>{}, is_infinite<Rng>{}) +
0160                        count_;
0161             }
0162             auto size() const
0163             {
0164                 return static_cast<detail::iter_size_t<iterator_t<Rng>>>(count_);
0165             }
0166             Rng base() const
0167             {
0168                 return rng_;
0169             }
0170         };
0171     } // namespace detail
0172     /// \endcond
0173 
0174     /// \addtogroup group-views
0175     /// @{
0176     template<typename Rng>
0177     struct slice_view : detail::slice_view_<Rng, (bool)random_access_range<Rng>>
0178     {
0179         using detail::slice_view_<Rng, (bool)random_access_range<Rng>>::slice_view_;
0180     };
0181 
0182     template<typename Rng>
0183     RANGES_INLINE_VAR constexpr bool enable_borrowed_range<slice_view<Rng>> = //
0184         enable_borrowed_range<Rng>;
0185 
0186 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0187     template<typename Rng>
0188     slice_view(Rng &&, range_difference_t<Rng>, range_difference_t<Rng>)
0189         ->slice_view<views::all_t<Rng>>;
0190 #endif
0191 
0192     namespace views
0193     {
0194         struct slice_base_fn
0195         {
0196         private:
0197             template<typename Rng>
0198             static constexpr slice_view<all_t<Rng>> impl_(Rng && rng,
0199                                                           range_difference_t<Rng> from,
0200                                                           range_difference_t<Rng> count,
0201                                                           input_range_tag, range_tag = {})
0202             {
0203                 return {all(static_cast<Rng &&>(rng)), from, count};
0204             }
0205             template(typename Rng)(
0206                 requires borrowed_range<Rng>)
0207             static subrange<iterator_t<Rng>> impl_(Rng && rng,
0208                                                    range_difference_t<Rng> from,
0209                                                    range_difference_t<Rng> count,
0210                                                    random_access_range_tag,
0211                                                    common_range_tag = {})
0212             {
0213                 auto it =
0214                     detail::pos_at_(rng, from, range_tag_of<Rng>{}, is_infinite<Rng>{});
0215                 return {it, it + count};
0216             }
0217 
0218         public:
0219             // slice(rng, 2, 4)
0220             template(typename Rng)(
0221                 requires viewable_range<Rng> AND input_range<Rng>)
0222             constexpr auto operator()(Rng && rng,
0223                                       range_difference_t<Rng> from,
0224                                       range_difference_t<Rng> to) const
0225             {
0226                 RANGES_EXPECT(0 <= from && from <= to);
0227                 return slice_base_fn::impl_(
0228                     static_cast<Rng &&>(rng), from, to - from, range_tag_of<Rng>{});
0229             }
0230             // slice(rng, 4, end-2)
0231             //  TODO Support Forward, non-Sized ranges by returning a range that
0232             //       doesn't know it's size?
0233             template(typename Rng)(
0234                 requires viewable_range<Rng> AND input_range<Rng> AND sized_range<Rng>)
0235             auto operator()(Rng && rng,
0236                             range_difference_t<Rng> from,
0237                             detail::from_end_of_t<Rng> to) const
0238             {
0239                 static_assert(!is_infinite<Rng>::value,
0240                               "Can't index from the end of an infinite range!");
0241                 RANGES_EXPECT(0 <= from);
0242                 RANGES_ASSERT(from <= distance(rng) + to.dist_);
0243                 return slice_base_fn::impl_(static_cast<Rng &&>(rng),
0244                                             from,
0245                                             distance(rng) + to.dist_ - from,
0246                                             range_tag_of<Rng>{});
0247             }
0248             // slice(rng, end-4, end-2)
0249             template(typename Rng)(
0250                 requires viewable_range<Rng> AND
0251                     (forward_range<Rng> || (input_range<Rng> && sized_range<Rng>)))
0252             auto operator()(Rng && rng,
0253                             detail::from_end_of_t<Rng> from,
0254                             detail::from_end_of_t<Rng> to) const
0255             {
0256                 static_assert(!is_infinite<Rng>::value,
0257                               "Can't index from the end of an infinite range!");
0258                 RANGES_EXPECT(from.dist_ <= to.dist_);
0259                 return slice_base_fn::impl_(static_cast<Rng &&>(rng),
0260                                             from.dist_,
0261                                             to.dist_ - from.dist_,
0262                                             range_tag_of<Rng>{},
0263                                             common_range_tag_of<Rng>{});
0264             }
0265             // slice(rng, 4, end)
0266             template(typename Rng)(
0267                 requires viewable_range<Rng> AND input_range<Rng>)
0268             auto operator()(Rng && rng, range_difference_t<Rng> from, end_fn) const
0269             {
0270                 RANGES_EXPECT(0 <= from);
0271                 return ranges::views::drop_exactly(static_cast<Rng &&>(rng), from);
0272             }
0273             // slice(rng, end-4, end)
0274             template(typename Rng)(
0275                 requires viewable_range<Rng> AND
0276                     (forward_range<Rng> || (input_range<Rng> && sized_range<Rng>)))
0277             auto operator()(Rng && rng,
0278                             detail::from_end_of_t<Rng> from,
0279                             end_fn) const
0280             {
0281                 static_assert(!is_infinite<Rng>::value,
0282                               "Can't index from the end of an infinite range!");
0283                 return slice_base_fn::impl_(static_cast<Rng &&>(rng),
0284                                             from.dist_,
0285                                             -from.dist_,
0286                                             range_tag_of<Rng>{},
0287                                             common_range_tag_of<Rng>{});
0288             }
0289         };
0290 
0291         struct slice_fn : slice_base_fn
0292         {
0293             using slice_base_fn::operator();
0294 
0295             // Overloads for the pipe syntax: rng | views::slice(from,to)
0296             template(typename Int)(
0297                 requires detail::integer_like_<Int>)
0298             constexpr auto operator()(Int from, Int to) const
0299             {
0300                 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0301             }
0302             template(typename Int)(
0303                 requires detail::integer_like_<Int>)
0304             constexpr auto operator()(Int from, detail::from_end_<Int> to) const
0305             {
0306                 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0307             }
0308             template(typename Int)(
0309                 requires detail::integer_like_<Int>)
0310             constexpr auto operator()(detail::from_end_<Int> from,
0311                                       detail::from_end_<Int> to) const
0312             {
0313                 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0314             }
0315             template(typename Int)(
0316                 requires detail::integer_like_<Int>)
0317             constexpr auto operator()(Int from, end_fn) const
0318             {
0319                 return make_view_closure(
0320                     bind_back(ranges::views::drop_exactly_base_fn{}, from));
0321             }
0322             template(typename Int)(
0323                 requires detail::integer_like_<Int>)
0324             constexpr auto operator()(detail::from_end_<Int> from, end_fn to) const
0325             {
0326                 return make_view_closure(bind_back(slice_base_fn{}, from, to));
0327             }
0328         };
0329 
0330         /// \relates _slice_fn
0331         /// \ingroup group-views
0332         RANGES_INLINE_VARIABLE(slice_fn, slice)
0333     } // namespace views
0334     /// @}
0335 } // namespace ranges
0336 
0337 #include <range/v3/detail/epilogue.hpp>
0338 #include <range/v3/detail/satisfy_boost_range.hpp>
0339 RANGES_SATISFY_BOOST_RANGE(::ranges::slice_view)
0340 
0341 #endif