// -*- C++ -*- //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP___RANGES_DROP_VIEW_H #define _LIBCPP___RANGES_DROP_VIEW_H #include <__assert> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> #include <__ranges/enable_borrowed_range.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> #include <__utility/move.h> #include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif _LIBCPP_BEGIN_NAMESPACE_STD #if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) namespace ranges { template class drop_view : public view_interface> { // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an // amortized O(1) begin() method. If this is an input_range, then we cannot cache // begin because begin is not equality preserving. // Note: drop_view::begin() is still trivially amortized O(1) because // one can't call begin() on it more than once. static constexpr bool _UseCache = forward_range<_View> && !(random_access_range<_View> && sized_range<_View>); using _Cache = _If<_UseCache, __non_propagating_cache>, __empty_cache>; _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache(); range_difference_t<_View> __count_ = 0; _View __base_ = _View(); public: drop_view() requires default_initializable<_View> = default; _LIBCPP_HIDE_FROM_ABI constexpr drop_view(_View __base, range_difference_t<_View> __count) : __count_(__count) , __base_(std::move(__base)) { _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero."); } _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } _LIBCPP_HIDE_FROM_ABI constexpr auto begin() requires (!(__simple_view<_View> && random_access_range && sized_range)) { if constexpr (_UseCache) if (__cached_begin_.__has_value()) return *__cached_begin_; auto __tmp = ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); if constexpr (_UseCache) __cached_begin_.__emplace(__tmp); return __tmp; } _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const requires random_access_range && sized_range { return ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_)); } _LIBCPP_HIDE_FROM_ABI constexpr auto end() requires (!__simple_view<_View>) { return ranges::end(__base_); } _LIBCPP_HIDE_FROM_ABI constexpr auto end() const requires range { return ranges::end(__base_); } _LIBCPP_HIDE_FROM_ABI static constexpr auto __size(auto& __self) { const auto __s = ranges::size(__self.__base_); const auto __c = static_cast(__self.__count_); return __s < __c ? 0 : __s - __c; } _LIBCPP_HIDE_FROM_ABI constexpr auto size() requires sized_range<_View> { return __size(*this); } _LIBCPP_HIDE_FROM_ABI constexpr auto size() const requires sized_range { return __size(*this); } }; template drop_view(_Range&&, range_difference_t<_Range>) -> drop_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Tp>; } // namespace ranges #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___RANGES_DROP_VIEW_H