view_interface.h 5.2 KB

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