reverse_view.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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_REVERSE_VIEW_H
  10. #define _LIBCPP___RANGES_REVERSE_VIEW_H
  11. #include <__concepts/constructible.h>
  12. #include <__config>
  13. #include <__iterator/concepts.h>
  14. #include <__iterator/next.h>
  15. #include <__iterator/reverse_iterator.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/range_adaptor.h>
  22. #include <__ranges/size.h>
  23. #include <__ranges/subrange.h>
  24. #include <__ranges/view_interface.h>
  25. #include <__type_traits/conditional.h>
  26. #include <__type_traits/remove_cvref.h>
  27. #include <__utility/forward.h>
  28. #include <__utility/move.h>
  29. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  30. # pragma GCC system_header
  31. #endif
  32. _LIBCPP_PUSH_MACROS
  33. #include <__undef_macros>
  34. _LIBCPP_BEGIN_NAMESPACE_STD
  35. #if _LIBCPP_STD_VER >= 20
  36. namespace ranges {
  37. template <view _View>
  38. requires bidirectional_range<_View>
  39. class reverse_view : public view_interface<reverse_view<_View>> {
  40. // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an
  41. // amortized O(1) begin() method.
  42. static constexpr bool _UseCache = !random_access_range<_View> && !common_range<_View>;
  43. using _Cache = _If<_UseCache, __non_propagating_cache<reverse_iterator<iterator_t<_View>>>, __empty_cache>;
  44. _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();
  45. _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
  46. public:
  47. _LIBCPP_HIDE_FROM_ABI reverse_view()
  48. requires default_initializable<_View>
  49. = default;
  50. _LIBCPP_HIDE_FROM_ABI constexpr explicit reverse_view(_View __view) : __base_(std::move(__view)) {}
  51. _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
  52. requires copy_constructible<_View>
  53. {
  54. return __base_;
  55. }
  56. _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
  57. _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin() {
  58. if constexpr (_UseCache)
  59. if (__cached_begin_.__has_value())
  60. return *__cached_begin_;
  61. auto __tmp = std::make_reverse_iterator(ranges::next(ranges::begin(__base_), ranges::end(__base_)));
  62. if constexpr (_UseCache)
  63. __cached_begin_.__emplace(__tmp);
  64. return __tmp;
  65. }
  66. _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin()
  67. requires common_range<_View>
  68. {
  69. return std::make_reverse_iterator(ranges::end(__base_));
  70. }
  71. _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
  72. requires common_range<const _View>
  73. {
  74. return std::make_reverse_iterator(ranges::end(__base_));
  75. }
  76. _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> end() {
  77. return std::make_reverse_iterator(ranges::begin(__base_));
  78. }
  79. _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
  80. requires common_range<const _View>
  81. {
  82. return std::make_reverse_iterator(ranges::begin(__base_));
  83. }
  84. _LIBCPP_HIDE_FROM_ABI constexpr auto size()
  85. requires sized_range<_View>
  86. {
  87. return ranges::size(__base_);
  88. }
  89. _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
  90. requires sized_range<const _View>
  91. {
  92. return ranges::size(__base_);
  93. }
  94. };
  95. template <class _Range>
  96. reverse_view(_Range&&) -> reverse_view<views::all_t<_Range>>;
  97. template <class _Tp>
  98. inline constexpr bool enable_borrowed_range<reverse_view<_Tp>> = enable_borrowed_range<_Tp>;
  99. namespace views {
  100. namespace __reverse {
  101. template <class _Tp>
  102. inline constexpr bool __is_reverse_view = false;
  103. template <class _Tp>
  104. inline constexpr bool __is_reverse_view<reverse_view<_Tp>> = true;
  105. template <class _Tp>
  106. inline constexpr bool __is_sized_reverse_subrange = false;
  107. template <class _Iter>
  108. inline constexpr bool
  109. __is_sized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, subrange_kind::sized>> =
  110. true;
  111. template <class _Tp>
  112. inline constexpr bool __is_unsized_reverse_subrange = false;
  113. template <class _Iter, subrange_kind _Kind>
  114. inline constexpr bool __is_unsized_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> =
  115. _Kind == subrange_kind::unsized;
  116. template <class _Tp>
  117. struct __unwrapped_reverse_subrange {
  118. using type =
  119. void; // avoid SFINAE-ing out the overload below -- let the concept requirements do it for better diagnostics
  120. };
  121. template <class _Iter, subrange_kind _Kind>
  122. struct __unwrapped_reverse_subrange<subrange<reverse_iterator<_Iter>, reverse_iterator<_Iter>, _Kind>> {
  123. using type = subrange<_Iter, _Iter, _Kind>;
  124. };
  125. struct __fn : __range_adaptor_closure<__fn> {
  126. template <class _Range>
  127. requires __is_reverse_view<remove_cvref_t<_Range>>
  128. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
  129. noexcept(noexcept(std::forward<_Range>(__range).base())) -> decltype(std::forward<_Range>(__range).base()) {
  130. return std::forward<_Range>(__range).base();
  131. }
  132. template <class _Range,
  133. class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>
  134. requires __is_sized_reverse_subrange<remove_cvref_t<_Range>>
  135. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
  136. noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())))
  137. -> decltype(_UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size())) {
  138. return _UnwrappedSubrange(__range.end().base(), __range.begin().base(), __range.size());
  139. }
  140. template <class _Range,
  141. class _UnwrappedSubrange = typename __unwrapped_reverse_subrange<remove_cvref_t<_Range>>::type>
  142. requires __is_unsized_reverse_subrange<remove_cvref_t<_Range>>
  143. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
  144. noexcept(noexcept(_UnwrappedSubrange(__range.end().base(), __range.begin().base())))
  145. -> decltype(_UnwrappedSubrange(__range.end().base(), __range.begin().base())) {
  146. return _UnwrappedSubrange(__range.end().base(), __range.begin().base());
  147. }
  148. template <class _Range>
  149. requires(!__is_reverse_view<remove_cvref_t<_Range>> && !__is_sized_reverse_subrange<remove_cvref_t<_Range>> &&
  150. !__is_unsized_reverse_subrange<remove_cvref_t<_Range>>)
  151. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
  152. noexcept(noexcept(reverse_view{std::forward<_Range>(__range)}))
  153. -> decltype(reverse_view{std::forward<_Range>(__range)}) {
  154. return reverse_view{std::forward<_Range>(__range)};
  155. }
  156. };
  157. } // namespace __reverse
  158. inline namespace __cpo {
  159. inline constexpr auto reverse = __reverse::__fn{};
  160. } // namespace __cpo
  161. } // namespace views
  162. } // namespace ranges
  163. #endif // _LIBCPP_STD_VER >= 20
  164. _LIBCPP_END_NAMESPACE_STD
  165. _LIBCPP_POP_MACROS
  166. #endif // _LIBCPP___RANGES_REVERSE_VIEW_H