File indexing completed on 2025-01-18 10:09:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
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
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
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
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
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)
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)
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
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
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
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
0307 RANGES_INLINE_VARIABLE(take_fn, take)
0308 }
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 }
0320
0321 }
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