view_interface.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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_VIEW_INTERFACE_H
  10. #define _LIBCPP___RANGES_VIEW_INTERFACE_H
  11. #include <__assert>
  12. #include <__concepts/derived_from.h>
  13. #include <__concepts/same_as.h>
  14. #include <__config>
  15. #include <__iterator/concepts.h>
  16. #include <__iterator/iterator_traits.h>
  17. #include <__iterator/prev.h>
  18. #include <__memory/pointer_traits.h>
  19. #include <__ranges/access.h>
  20. #include <__ranges/concepts.h>
  21. #include <__ranges/empty.h>
  22. #include <__ranges/size.h>
  23. #include <__type_traits/is_class.h>
  24. #include <__type_traits/make_unsigned.h>
  25. #include <__type_traits/remove_cv.h>
  26. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  27. # pragma GCC system_header
  28. #endif
  29. _LIBCPP_BEGIN_NAMESPACE_STD
  30. #if _LIBCPP_STD_VER >= 20
  31. namespace ranges {
  32. template <class _Derived>
  33. requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
  34. class view_interface {
  35. _LIBCPP_HIDE_FROM_ABI constexpr _Derived& __derived() noexcept {
  36. static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
  37. return static_cast<_Derived&>(*this);
  38. }
  39. _LIBCPP_HIDE_FROM_ABI constexpr _Derived const& __derived() const noexcept {
  40. static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
  41. return static_cast<_Derived const&>(*this);
  42. }
  43. public:
  44. template <class _D2 = _Derived>
  45. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
  46. requires sized_range<_D2> || forward_range<_D2>
  47. {
  48. if constexpr (sized_range<_D2>) {
  49. return ranges::size(__derived()) == 0;
  50. } else {
  51. return ranges::begin(__derived()) == ranges::end(__derived());
  52. }
  53. }
  54. template <class _D2 = _Derived>
  55. [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
  56. requires sized_range<const _D2> || forward_range<const _D2>
  57. {
  58. if constexpr (sized_range<const _D2>) {
  59. return ranges::size(__derived()) == 0;
  60. } else {
  61. return ranges::begin(__derived()) == ranges::end(__derived());
  62. }
  63. }
  64. template <class _D2 = _Derived>
  65. _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool()
  66. requires requires(_D2& __t) { ranges::empty(__t); }
  67. {
  68. return !ranges::empty(__derived());
  69. }
  70. template <class _D2 = _Derived>
  71. _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const
  72. requires requires(const _D2& __t) { ranges::empty(__t); }
  73. {
  74. return !ranges::empty(__derived());
  75. }
  76. template <class _D2 = _Derived>
  77. _LIBCPP_HIDE_FROM_ABI constexpr auto data()
  78. requires contiguous_iterator<iterator_t<_D2>>
  79. {
  80. return std::to_address(ranges::begin(__derived()));
  81. }
  82. template <class _D2 = _Derived>
  83. _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
  84. requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
  85. {
  86. return std::to_address(ranges::begin(__derived()));
  87. }
  88. template <class _D2 = _Derived>
  89. _LIBCPP_HIDE_FROM_ABI constexpr auto size()
  90. requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
  91. {
  92. return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
  93. }
  94. template <class _D2 = _Derived>
  95. _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
  96. requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
  97. {
  98. return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
  99. }
  100. template <class _D2 = _Derived>
  101. _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front()
  102. requires forward_range<_D2>
  103. {
  104. _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
  105. !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
  106. return *ranges::begin(__derived());
  107. }
  108. template <class _D2 = _Derived>
  109. _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() const
  110. requires forward_range<const _D2>
  111. {
  112. _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
  113. !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
  114. return *ranges::begin(__derived());
  115. }
  116. template <class _D2 = _Derived>
  117. _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back()
  118. requires bidirectional_range<_D2> && common_range<_D2>
  119. {
  120. _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
  121. !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
  122. return *ranges::prev(ranges::end(__derived()));
  123. }
  124. template <class _D2 = _Derived>
  125. _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() const
  126. requires bidirectional_range<const _D2> && common_range<const _D2>
  127. {
  128. _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
  129. !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
  130. return *ranges::prev(ranges::end(__derived()));
  131. }
  132. template <random_access_range _RARange = _Derived>
  133. _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) {
  134. return ranges::begin(__derived())[__index];
  135. }
  136. template <random_access_range _RARange = const _Derived>
  137. _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const {
  138. return ranges::begin(__derived())[__index];
  139. }
  140. };
  141. } // namespace ranges
  142. #endif // _LIBCPP_STD_VER >= 20
  143. _LIBCPP_END_NAMESPACE_STD
  144. #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H