view_interface.h 5.1 KB

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