drop_view.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___RANGES_DROP_VIEW_H
  10. #define _LIBCPP___RANGES_DROP_VIEW_H
  11. #include <__assert>
  12. #include <__config>
  13. #include <__iterator/concepts.h>
  14. #include <__iterator/iterator_traits.h>
  15. #include <__iterator/next.h>
  16. #include <__ranges/access.h>
  17. #include <__ranges/all.h>
  18. #include <__ranges/concepts.h>
  19. #include <__ranges/enable_borrowed_range.h>
  20. #include <__ranges/non_propagating_cache.h>
  21. #include <__ranges/size.h>
  22. #include <__ranges/view_interface.h>
  23. #include <__utility/move.h>
  24. #include <concepts>
  25. #include <type_traits>
  26. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  27. # pragma GCC system_header
  28. #endif
  29. _LIBCPP_BEGIN_NAMESPACE_STD
  30. #if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
  31. namespace ranges {
  32. template<view _View>
  33. class drop_view
  34. : public view_interface<drop_view<_View>>
  35. {
  36. // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an
  37. // amortized O(1) begin() method. If this is an input_range, then we cannot cache
  38. // begin because begin is not equality preserving.
  39. // Note: drop_view<input-range>::begin() is still trivially amortized O(1) because
  40. // one can't call begin() on it more than once.
  41. static constexpr bool _UseCache = forward_range<_View> && !(random_access_range<_View> && sized_range<_View>);
  42. using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>;
  43. _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();
  44. range_difference_t<_View> __count_ = 0;
  45. _View __base_ = _View();
  46. public:
  47. drop_view() requires default_initializable<_View> = default;
  48. _LIBCPP_HIDE_FROM_ABI
  49. constexpr drop_view(_View __base, range_difference_t<_View> __count)
  50. : __count_(__count)
  51. , __base_(std::move(__base))
  52. {
  53. _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero.");
  54. }
  55. _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
  56. _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
  57. _LIBCPP_HIDE_FROM_ABI
  58. constexpr auto begin()
  59. requires (!(__simple_view<_View> &&
  60. random_access_range<const _View> && sized_range<const _View>))
  61. {
  62. if constexpr (_UseCache)
  63. if (__cached_begin_.__has_value())
  64. return *__cached_begin_;
  65. auto __tmp = ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_));
  66. if constexpr (_UseCache)
  67. __cached_begin_.__emplace(__tmp);
  68. return __tmp;
  69. }
  70. _LIBCPP_HIDE_FROM_ABI
  71. constexpr auto begin() const
  72. requires random_access_range<const _View> && sized_range<const _View>
  73. {
  74. return ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_));
  75. }
  76. _LIBCPP_HIDE_FROM_ABI
  77. constexpr auto end()
  78. requires (!__simple_view<_View>)
  79. { return ranges::end(__base_); }
  80. _LIBCPP_HIDE_FROM_ABI
  81. constexpr auto end() const
  82. requires range<const _View>
  83. { return ranges::end(__base_); }
  84. _LIBCPP_HIDE_FROM_ABI
  85. static constexpr auto __size(auto& __self) {
  86. const auto __s = ranges::size(__self.__base_);
  87. const auto __c = static_cast<decltype(__s)>(__self.__count_);
  88. return __s < __c ? 0 : __s - __c;
  89. }
  90. _LIBCPP_HIDE_FROM_ABI
  91. constexpr auto size()
  92. requires sized_range<_View>
  93. { return __size(*this); }
  94. _LIBCPP_HIDE_FROM_ABI
  95. constexpr auto size() const
  96. requires sized_range<const _View>
  97. { return __size(*this); }
  98. };
  99. template<class _Range>
  100. drop_view(_Range&&, range_difference_t<_Range>) -> drop_view<views::all_t<_Range>>;
  101. template<class _Tp>
  102. inline constexpr bool enable_borrowed_range<drop_view<_Tp>> = enable_borrowed_range<_Tp>;
  103. } // namespace ranges
  104. #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
  105. _LIBCPP_END_NAMESPACE_STD
  106. #endif // _LIBCPP___RANGES_DROP_VIEW_H