Back to home page

EIC code displayed by LXR

 
 

    


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

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_TAKE_HPP
0015 #define RANGES_V3_VIEW_TAKE_HPP
0016 
0017 #include <type_traits>
0018 
0019 #include <range/v3/range_fwd.hpp>
0020 
0021 #include <range/v3/algorithm/min.hpp>
0022 #include <range/v3/functional/bind_back.hpp>
0023 #include <range/v3/iterator/counted_iterator.hpp>
0024 #include <range/v3/iterator/default_sentinel.hpp>
0025 #include <range/v3/range/concepts.hpp>
0026 #include <range/v3/range/traits.hpp>
0027 #include <range/v3/utility/static_const.hpp>
0028 #include <range/v3/view/all.hpp>
0029 #include <range/v3/view/view.hpp>
0030 
0031 #include <range/v3/detail/prologue.hpp>
0032 
0033 namespace ranges
0034 {
0035     /// \addtogroup group-views
0036     /// @{
0037 
0038     template<typename Rng>
0039     struct take_view : view_interface<take_view<Rng>, finite>
0040     {
0041     private:
0042         CPP_assert(view_<Rng>);
0043         Rng base_ = Rng();
0044         range_difference_t<Rng> count_ = 0;
0045         template<bool Const>
0046         struct sentinel
0047         {
0048         private:
0049             using Base = meta::conditional_t<Const, Rng const, Rng>;
0050             using CI = counted_iterator<iterator_t<Base>>;
0051             sentinel_t<Base> end_ = sentinel_t<Base>();
0052 
0053         public:
0054             sentinel() = default;
0055             constexpr explicit sentinel(sentinel_t<Base> last)
0056               : end_(std::move(last))
0057             {}
0058             template(bool Other)(
0059                 requires Const AND CPP_NOT(Other) AND
0060                 convertible_to<sentinel_t<Rng>,
0061                                sentinel_t<Base>>)
0062                 constexpr sentinel(sentinel<Other> that)
0063               : end_(std::move(that.end_))
0064             {}
0065             constexpr sentinel_t<Base> base() const
0066             {
0067                 return end_;
0068             }
0069 #ifdef RANGES_WORKAROUND_MSVC_756601
0070             template<typename = void>
0071 #endif // RANGES_WORKAROUND_MSVC_756601
0072             friend constexpr bool operator==(sentinel const & x, CI const & y)
0073             {
0074                 return y.count() == 0 || y.base() == x.end_;
0075             }
0076 #ifdef RANGES_WORKAROUND_MSVC_756601
0077             template<typename = void>
0078 #endif // RANGES_WORKAROUND_MSVC_756601
0079             friend constexpr bool operator==(CI const & y, sentinel const & x)
0080             {
0081                 return y.count() == 0 || y.base() == x.end_;
0082             }
0083 #ifdef RANGES_WORKAROUND_MSVC_756601
0084             template<typename = void>
0085 #endif // RANGES_WORKAROUND_MSVC_756601
0086             friend constexpr bool operator!=(sentinel const & x, CI const & y)
0087             {
0088                 return y.count() != 0 && y.base() != x.end_;
0089             }
0090 #ifdef RANGES_WORKAROUND_MSVC_756601
0091             template<typename = void>
0092 #endif // RANGES_WORKAROUND_MSVC_756601
0093             friend constexpr bool operator!=(CI const & y, sentinel const & x)
0094             {
0095                 return y.count() != 0 && y.base() != x.end_;
0096             }
0097         };
0098 
0099 #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17
0100         template<typename Take>
0101         static auto begin_random_access_(Take & take, std::true_type)
0102         {
0103             return ranges::begin(take.base_);
0104         }
0105         template<typename Take>
0106         static auto begin_random_access_(Take & take, std::false_type)
0107         {
0108             auto s = static_cast<range_difference_t<Rng>>(take.size());
0109             return make_counted_iterator(ranges::begin(take.base_), s);
0110         }
0111         template<typename Take>
0112         static auto begin_sized_(Take & take, std::true_type)
0113         {
0114             return begin_random_access_(
0115                 take, meta::bool_<random_access_range<decltype((take.base_))>>{});
0116         }
0117         template<typename Take>
0118         static auto begin_sized_(Take & take, std::false_type)
0119         {
0120             return make_counted_iterator(ranges::begin(take.base_), take.count_);
0121         }
0122 
0123         template<typename Take>
0124         static auto end_random_access_(Take & take, std::true_type)
0125         {
0126             return ranges::begin(take.base_) +
0127                    static_cast<range_difference_t<Rng>>(take.size());
0128         }
0129         static auto end_random_access_(detail::ignore_t, std::false_type)
0130         {
0131             return default_sentinel;
0132         }
0133         template<typename Take>
0134         static auto end_sized_(Take & take, std::true_type, std::false_type) // sized
0135         {
0136             return end_random_access_(
0137                 take, meta::bool_<random_access_range<decltype((take.base_))>>{});
0138         }
0139         static auto end_sized_(detail::ignore_t, std::false_type,
0140                                std::true_type) // infinite
0141         {
0142             return default_sentinel;
0143         }
0144         static auto end_sized_(take_view & take, std::false_type, std::false_type)
0145         {
0146             return sentinel<false>{ranges::end(take.base_)};
0147         }
0148         static auto end_sized_(take_view const & take, std::false_type, std::false_type)
0149         {
0150             return sentinel<true>{ranges::end(take.base_)};
0151         }
0152 #endif
0153     public:
0154         take_view() = default;
0155 
0156         constexpr take_view(Rng base, range_difference_t<Rng> cnt)
0157           : base_(std::move(base))
0158           , count_(cnt)
0159         {}
0160 
0161         constexpr Rng base() const
0162         {
0163             return base_;
0164         }
0165 
0166         CPP_auto_member
0167         constexpr auto CPP_fun(begin)()(
0168             requires(!simple_view<Rng>()))
0169         {
0170 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0171             if constexpr(sized_range<Rng>)
0172                 if constexpr(random_access_range<Rng>)
0173                     return ranges::begin(base_);
0174                 else
0175                 {
0176                     // cannot always delegate to size() member on GCC with ConceptsTS
0177 #if defined(__cpp_concepts) && __cpp_concepts <= 201507
0178                     auto s = ranges::min(
0179                         static_cast<range_difference_t<Rng>>(count_),
0180                         static_cast<range_difference_t<Rng>>(ranges::size(base_)));
0181 #else
0182                     auto s = static_cast<range_difference_t<Rng>>(size());
0183 #endif
0184                     return make_counted_iterator(ranges::begin(base_), s);
0185                 }
0186             else
0187                 return make_counted_iterator(ranges::begin(base_), count_);
0188 #else
0189             return begin_sized_(*this, meta::bool_<sized_range<Rng>>{});
0190 #endif
0191         }
0192 
0193         CPP_auto_member
0194         constexpr auto CPP_fun(begin)()(const //
0195             requires range<Rng const>)
0196         {
0197 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0198             if constexpr(sized_range<Rng const>)
0199                 if constexpr(random_access_range<Rng const>)
0200                     return ranges::begin(base_);
0201                 else
0202                 {
0203                     auto s = static_cast<range_difference_t<Rng>>(size());
0204                     return make_counted_iterator(ranges::begin(base_), s);
0205                 }
0206             else
0207                 return make_counted_iterator(ranges::begin(base_), count_);
0208 #else
0209             return begin_sized_(*this, meta::bool_<sized_range<Rng const>>{});
0210 #endif
0211         }
0212 
0213         CPP_auto_member
0214         constexpr auto CPP_fun(end)()(
0215             requires(!simple_view<Rng>()))
0216         {
0217 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0218             if constexpr(sized_range<Rng>)
0219                 if constexpr(random_access_range<Rng>)
0220                     return ranges::begin(base_) +
0221                            static_cast<range_difference_t<Rng>>(size());
0222                 else
0223                     return default_sentinel;
0224             // Not to spec: Infinite ranges:
0225             else if constexpr(is_infinite<Rng>::value)
0226                 return default_sentinel;
0227             else
0228                 return sentinel<false>{ranges::end(base_)};
0229 #else
0230             return end_sized_(*this, meta::bool_<sized_range<Rng>>{}, is_infinite<Rng>{});
0231 #endif
0232         }
0233 
0234         CPP_auto_member
0235         constexpr auto CPP_fun(end)()(const //
0236             requires range<Rng const>)
0237         {
0238 #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17
0239             if constexpr(sized_range<Rng const>)
0240                 if constexpr(random_access_range<Rng const>)
0241                     return ranges::begin(base_) +
0242                            static_cast<range_difference_t<Rng>>(size());
0243                 else
0244                     return default_sentinel;
0245             // Not to spec: Infinite ranges:
0246             else if constexpr(is_infinite<Rng const>::value)
0247                 return default_sentinel;
0248             else
0249                 return sentinel<true>{ranges::end(base_)};
0250 #else
0251             return end_sized_(
0252                 *this, meta::bool_<sized_range<Rng const>>{}, is_infinite<Rng const>{});
0253 #endif
0254         }
0255 
0256         CPP_auto_member
0257         constexpr auto CPP_fun(size)()(
0258             requires sized_range<Rng>)
0259         {
0260             auto n = ranges::size(base_);
0261             return ranges::min(n, static_cast<decltype(n)>(count_));
0262         }
0263         CPP_auto_member
0264         constexpr auto CPP_fun(size)()(const //
0265             requires sized_range<Rng const>)
0266         {
0267             auto n = ranges::size(base_);
0268             return ranges::min(n, static_cast<decltype(n)>(count_));
0269         }
0270     };
0271 
0272     template<typename Rng>
0273     RANGES_INLINE_VAR constexpr bool enable_borrowed_range<take_view<Rng>> = //
0274         enable_borrowed_range<Rng>;
0275 
0276 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0277     template<typename Rng>
0278     take_view(Rng &&, range_difference_t<Rng>)
0279         -> take_view<views::all_t<Rng>>;
0280 #endif
0281 
0282     namespace views
0283     {
0284         struct take_base_fn
0285         {
0286             template(typename Rng)(
0287                 requires viewable_range<Rng>)
0288             take_view<all_t<Rng>> operator()(Rng && rng, range_difference_t<Rng> n) const
0289             {
0290                 return {all(static_cast<Rng &&>(rng)), n};
0291             }
0292         };
0293 
0294         struct take_fn : take_base_fn
0295         {
0296             using take_base_fn::operator();
0297 
0298             template(typename Int)(
0299                 requires detail::integer_like_<Int>)
0300             constexpr auto operator()(Int n) const
0301             {
0302                 return make_view_closure(bind_back(take_base_fn{}, n));
0303             }
0304         };
0305 
0306         /// \relates take_fn
0307         RANGES_INLINE_VARIABLE(take_fn, take)
0308     } // namespace views
0309 
0310     namespace cpp20
0311     {
0312         namespace views
0313         {
0314             using ranges::views::take;
0315         }
0316         template(typename Rng)(
0317             requires view_<Rng>)
0318         using take_view = ranges::take_view<Rng>;
0319     } // namespace cpp20
0320     /// @}
0321 } // namespace ranges
0322 
0323 #include <range/v3/detail/epilogue.hpp>
0324 #include <range/v3/detail/satisfy_boost_range.hpp>
0325 RANGES_SATISFY_BOOST_RANGE(::ranges::take_view)
0326 
0327 #endif