/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_VIEW_TAKE_HPP #define RANGES_V3_VIEW_TAKE_HPP #include #include #include #include #include #include #include #include #include #include #include namespace ranges { template struct take_view : view_interface, finite> { private: CPP_assert(view_); Rng base_ = Rng(); range_difference_t count_ = 0; template struct sentinel { private: using Base = detail::if_then_t; using CI = counted_iterator>; sentinel_t end_ = sentinel_t(); public: sentinel() = default; constexpr explicit sentinel(sentinel_t last) : end_(std::move(last)) {} CPP_template(bool Other)( // requires Const && (!Other) && convertible_to, sentinel_t>) // constexpr sentinel(sentinel that) : end_(std::move(that.end_)) {} constexpr sentinel_t base() const { return end_; } #ifdef RANGES_WORKAROUND_MSVC_756601 template #endif // RANGES_WORKAROUND_MSVC_756601 friend constexpr bool operator==(sentinel const & x, CI const & y) { return y.count() == 0 || y.base() == x.end_; } #ifdef RANGES_WORKAROUND_MSVC_756601 template #endif // RANGES_WORKAROUND_MSVC_756601 friend constexpr bool operator==(CI const & y, sentinel const & x) { return y.count() == 0 || y.base() == x.end_; } #ifdef RANGES_WORKAROUND_MSVC_756601 template #endif // RANGES_WORKAROUND_MSVC_756601 friend constexpr bool operator!=(sentinel const & x, CI const & y) { return y.count() != 0 && y.base() != x.end_; } #ifdef RANGES_WORKAROUND_MSVC_756601 template #endif // RANGES_WORKAROUND_MSVC_756601 friend constexpr bool operator!=(CI const & y, sentinel const & x) { return y.count() != 0 && y.base() != x.end_; } }; #if RANGES_CXX_IF_CONSTEXPR < RANGES_CXX_IF_CONSTEXPR_17 template static auto begin_random_access_(Take & take, std::true_type) { return ranges::begin(take.base_); } template static auto begin_random_access_(Take & take, std::false_type) { auto s = static_cast>(take.size()); return make_counted_iterator(ranges::begin(take.base_), s); } template static auto begin_sized_(Take & take, std::true_type) { return begin_random_access_( take, meta::bool_>{}); } template static auto begin_sized_(Take & take, std::false_type) { return make_counted_iterator(ranges::begin(take.base_), take.count_); } template static auto end_random_access_(Take & take, std::true_type) { return ranges::begin(take.base_) + static_cast>(take.size()); } static auto end_random_access_(detail::ignore_t, std::false_type) { return default_sentinel; } template static auto end_sized_(Take & take, std::true_type, std::false_type) // sized { return end_random_access_( take, meta::bool_>{}); } static auto end_sized_(detail::ignore_t, std::false_type, std::true_type) // infinite { return default_sentinel; } static auto end_sized_(take_view & take, std::false_type, std::false_type) { return sentinel{ranges::end(take.base_)}; } static auto end_sized_(take_view const & take, std::false_type, std::false_type) { return sentinel{ranges::end(take.base_)}; } #endif public: take_view() = default; constexpr take_view(Rng base, range_difference_t cnt) : base_(std::move(base)) , count_(cnt) {} constexpr Rng base() const { return base_; } CPP_member constexpr auto CPP_fun(begin)()(requires(!simple_view())) { #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17 if constexpr(sized_range) if constexpr(random_access_range) return ranges::begin(base_); else { // cannot always delegate to size() member on GCC with ConceptsTS #if defined(__cpp_concepts) && __cpp_concepts <= 201507 auto s = ranges::min( static_cast>(count_), static_cast>(ranges::size(base_))); #else auto s = static_cast>(size()); #endif return make_counted_iterator(ranges::begin(base_), s); } else return make_counted_iterator(ranges::begin(base_), count_); #else return begin_sized_(*this, meta::bool_>{}); #endif } CPP_member constexpr auto CPP_fun(begin)()(const requires range) { #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17 if constexpr(sized_range) if constexpr(random_access_range) return ranges::begin(base_); else { auto s = static_cast>(size()); return make_counted_iterator(ranges::begin(base_), s); } else return make_counted_iterator(ranges::begin(base_), count_); #else return begin_sized_(*this, meta::bool_>{}); #endif } CPP_member constexpr auto CPP_fun(end)()(requires(!simple_view())) { #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17 if constexpr(sized_range) if constexpr(random_access_range) return ranges::begin(base_) + static_cast>(size()); else return default_sentinel; // Not to spec: Infinite ranges: else if constexpr(is_infinite::value) return default_sentinel; else return sentinel{ranges::end(base_)}; #else return end_sized_(*this, meta::bool_>{}, is_infinite{}); #endif } CPP_member constexpr auto CPP_fun(end)()(const requires range) { #if RANGES_CXX_IF_CONSTEXPR >= RANGES_CXX_IF_CONSTEXPR_17 if constexpr(sized_range) if constexpr(random_access_range) return ranges::begin(base_) + static_cast>(size()); else return default_sentinel; // Not to spec: Infinite ranges: else if constexpr(is_infinite::value) return default_sentinel; else return sentinel{ranges::end(base_)}; #else return end_sized_( *this, meta::bool_>{}, is_infinite{}); #endif } CPP_member constexpr auto CPP_fun(size)()(requires sized_range) { auto n = ranges::size(base_); return ranges::min(n, static_cast(count_)); } CPP_member constexpr auto CPP_fun(size)()(const requires sized_range) { auto n = ranges::size(base_); return ranges::min(n, static_cast(count_)); } }; #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17 template take_view(Rng &&, range_difference_t)->take_view>; #endif namespace views { struct take_fn { private: friend view_access; template static constexpr auto CPP_fun(bind)(take_fn take, Int n)( // requires integral) { return make_pipeable(bind_back(take, n)); } public: template auto operator()(Rng && rng, range_difference_t n) const -> CPP_ret(take_view>)( // requires viewable_range) { return {all(static_cast(rng)), n}; } }; /// \relates take_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(view, take) } // namespace views namespace cpp20 { namespace views { using ranges::views::take; } CPP_template(typename Rng)( // requires view_) // using take_view = ranges::take_view; } // namespace cpp20 /// @} } // namespace ranges #include RANGES_SATISFY_BOOST_RANGE(::ranges::take_view) #endif