reverse_view.h 7.2 KB

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