1fe6060f1SDimitry Andric // -*- C++ -*- 2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric // 4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric // 8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 10fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H 11fe6060f1SDimitry Andric #define _LIBCPP___RANGES_VIEW_INTERFACE_H 12fe6060f1SDimitry Andric 1381ad6265SDimitry Andric #include <__assert> 1481ad6265SDimitry Andric #include <__concepts/derived_from.h> 1581ad6265SDimitry Andric #include <__concepts/same_as.h> 16fe6060f1SDimitry Andric #include <__config> 17fe6060f1SDimitry Andric #include <__iterator/concepts.h> 18fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 19fe6060f1SDimitry Andric #include <__iterator/prev.h> 20fe6060f1SDimitry Andric #include <__memory/pointer_traits.h> 21fe6060f1SDimitry Andric #include <__ranges/access.h> 22fe6060f1SDimitry Andric #include <__ranges/concepts.h> 23fe6060f1SDimitry Andric #include <__ranges/empty.h> 24*0fca6ea1SDimitry Andric #include <__ranges/size.h> 25bdd1243dSDimitry Andric #include <__type_traits/is_class.h> 26bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h> 27bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h> 28fe6060f1SDimitry Andric 29fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30fe6060f1SDimitry Andric # pragma GCC system_header 31fe6060f1SDimitry Andric #endif 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 34fe6060f1SDimitry Andric 3506c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 36fe6060f1SDimitry Andric 37fe6060f1SDimitry Andric namespace ranges { 38fe6060f1SDimitry Andric 39fe6060f1SDimitry Andric template <class _Derived> 40fe6060f1SDimitry Andric requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> 4104eeddc0SDimitry Andric class view_interface { 42cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Derived& __derived() noexcept { 43349cc55cSDimitry Andric static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>); 44fe6060f1SDimitry Andric return static_cast<_Derived&>(*this); 45fe6060f1SDimitry Andric } 46fe6060f1SDimitry Andric 47cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Derived const& __derived() const noexcept { 48349cc55cSDimitry Andric static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>); 49fe6060f1SDimitry Andric return static_cast<_Derived const&>(*this); 50fe6060f1SDimitry Andric } 51fe6060f1SDimitry Andric 52fe6060f1SDimitry Andric public: 53fe6060f1SDimitry Andric template <class _D2 = _Derived> 54fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() 55*0fca6ea1SDimitry Andric requires sized_range<_D2> || forward_range<_D2> 56fe6060f1SDimitry Andric { 57*0fca6ea1SDimitry Andric if constexpr (sized_range<_D2>) { 58*0fca6ea1SDimitry Andric return ranges::size(__derived()) == 0; 59*0fca6ea1SDimitry Andric } else { 60fe6060f1SDimitry Andric return ranges::begin(__derived()) == ranges::end(__derived()); 61fe6060f1SDimitry Andric } 62*0fca6ea1SDimitry Andric } 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric template <class _D2 = _Derived> 65fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const 66*0fca6ea1SDimitry Andric requires sized_range<const _D2> || forward_range<const _D2> 67fe6060f1SDimitry Andric { 68*0fca6ea1SDimitry Andric if constexpr (sized_range<const _D2>) { 69*0fca6ea1SDimitry Andric return ranges::size(__derived()) == 0; 70*0fca6ea1SDimitry Andric } else { 71fe6060f1SDimitry Andric return ranges::begin(__derived()) == ranges::end(__derived()); 72fe6060f1SDimitry Andric } 73*0fca6ea1SDimitry Andric } 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric template <class _D2 = _Derived> 76cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() 7781ad6265SDimitry Andric requires requires(_D2& __t) { ranges::empty(__t); } 78fe6060f1SDimitry Andric { 79fe6060f1SDimitry Andric return !ranges::empty(__derived()); 80fe6060f1SDimitry Andric } 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric template <class _D2 = _Derived> 83cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const 8481ad6265SDimitry Andric requires requires(const _D2& __t) { ranges::empty(__t); } 85fe6060f1SDimitry Andric { 86fe6060f1SDimitry Andric return !ranges::empty(__derived()); 87fe6060f1SDimitry Andric } 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric template <class _D2 = _Derived> 90cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto data() 91fe6060f1SDimitry Andric requires contiguous_iterator<iterator_t<_D2>> 92fe6060f1SDimitry Andric { 9381ad6265SDimitry Andric return std::to_address(ranges::begin(__derived())); 94fe6060f1SDimitry Andric } 95fe6060f1SDimitry Andric 96fe6060f1SDimitry Andric template <class _D2 = _Derived> 97cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto data() const 98fe6060f1SDimitry Andric requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>> 99fe6060f1SDimitry Andric { 10081ad6265SDimitry Andric return std::to_address(ranges::begin(__derived())); 101fe6060f1SDimitry Andric } 102fe6060f1SDimitry Andric 103fe6060f1SDimitry Andric template <class _D2 = _Derived> 104cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto size() 10581ad6265SDimitry Andric requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>> 106fe6060f1SDimitry Andric { 107bdd1243dSDimitry Andric return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); 108fe6060f1SDimitry Andric } 109fe6060f1SDimitry Andric 110fe6060f1SDimitry Andric template <class _D2 = _Derived> 111cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto size() const 11281ad6265SDimitry Andric requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>> 113fe6060f1SDimitry Andric { 114bdd1243dSDimitry Andric return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); 115fe6060f1SDimitry Andric } 116fe6060f1SDimitry Andric 117fe6060f1SDimitry Andric template <class _D2 = _Derived> 118cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() 119fe6060f1SDimitry Andric requires forward_range<_D2> 120fe6060f1SDimitry Andric { 121cb14a3feSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 122cb14a3feSDimitry Andric !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); 123fe6060f1SDimitry Andric return *ranges::begin(__derived()); 124fe6060f1SDimitry Andric } 125fe6060f1SDimitry Andric 126fe6060f1SDimitry Andric template <class _D2 = _Derived> 127cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() const 128fe6060f1SDimitry Andric requires forward_range<const _D2> 129fe6060f1SDimitry Andric { 130cb14a3feSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 131cb14a3feSDimitry Andric !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); 132fe6060f1SDimitry Andric return *ranges::begin(__derived()); 133fe6060f1SDimitry Andric } 134fe6060f1SDimitry Andric 135fe6060f1SDimitry Andric template <class _D2 = _Derived> 136cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() 137fe6060f1SDimitry Andric requires bidirectional_range<_D2> && common_range<_D2> 138fe6060f1SDimitry Andric { 139cb14a3feSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 140cb14a3feSDimitry Andric !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); 141fe6060f1SDimitry Andric return *ranges::prev(ranges::end(__derived())); 142fe6060f1SDimitry Andric } 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric template <class _D2 = _Derived> 145cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() const 146fe6060f1SDimitry Andric requires bidirectional_range<const _D2> && common_range<const _D2> 147fe6060f1SDimitry Andric { 148cb14a3feSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 149cb14a3feSDimitry Andric !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); 150fe6060f1SDimitry Andric return *ranges::prev(ranges::end(__derived())); 151fe6060f1SDimitry Andric } 152fe6060f1SDimitry Andric 153fe6060f1SDimitry Andric template <random_access_range _RARange = _Derived> 154cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) { 155fe6060f1SDimitry Andric return ranges::begin(__derived())[__index]; 156fe6060f1SDimitry Andric } 157fe6060f1SDimitry Andric 158fe6060f1SDimitry Andric template <random_access_range _RARange = const _Derived> 159cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const { 160fe6060f1SDimitry Andric return ranges::begin(__derived())[__index]; 161fe6060f1SDimitry Andric } 162fe6060f1SDimitry Andric }; 163fe6060f1SDimitry Andric 1641fd87a68SDimitry Andric } // namespace ranges 165fe6060f1SDimitry Andric 16606c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 167fe6060f1SDimitry Andric 168fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 169fe6060f1SDimitry Andric 170fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H 171