reverse_view.h 7.3 KB

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