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>
24bdd1243dSDimitry Andric #include <__type_traits/is_class.h>
25bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h>
26bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h>
27fe6060f1SDimitry Andric 
28fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29fe6060f1SDimitry Andric #  pragma GCC system_header
30fe6060f1SDimitry Andric #endif
31fe6060f1SDimitry Andric 
32fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
33fe6060f1SDimitry Andric 
3406c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
35fe6060f1SDimitry Andric 
36fe6060f1SDimitry Andric namespace ranges {
37fe6060f1SDimitry Andric 
38fe6060f1SDimitry Andric template <class _Derived>
39fe6060f1SDimitry Andric   requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
4004eeddc0SDimitry Andric class view_interface {
__derived()41*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Derived& __derived() noexcept {
42349cc55cSDimitry Andric     static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
43fe6060f1SDimitry Andric     return static_cast<_Derived&>(*this);
44fe6060f1SDimitry Andric   }
45fe6060f1SDimitry Andric 
__derived()46*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Derived const& __derived() const noexcept {
47349cc55cSDimitry Andric     static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
48fe6060f1SDimitry Andric     return static_cast<_Derived const&>(*this);
49fe6060f1SDimitry Andric   }
50fe6060f1SDimitry Andric 
51fe6060f1SDimitry Andric public:
52fe6060f1SDimitry Andric   template <class _D2 = _Derived>
empty()53fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
54fe6060f1SDimitry Andric     requires forward_range<_D2>
55fe6060f1SDimitry Andric   {
56fe6060f1SDimitry Andric     return ranges::begin(__derived()) == ranges::end(__derived());
57fe6060f1SDimitry Andric   }
58fe6060f1SDimitry Andric 
59fe6060f1SDimitry Andric   template <class _D2 = _Derived>
empty()60fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
61fe6060f1SDimitry Andric     requires forward_range<const _D2>
62fe6060f1SDimitry Andric   {
63fe6060f1SDimitry Andric     return ranges::begin(__derived()) == ranges::end(__derived());
64fe6060f1SDimitry Andric   }
65fe6060f1SDimitry Andric 
66fe6060f1SDimitry Andric   template <class _D2 = _Derived>
67*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool()
requires(_D2 & __t)6881ad6265SDimitry Andric     requires requires(_D2& __t) { ranges::empty(__t); }
69fe6060f1SDimitry Andric   {
70fe6060f1SDimitry Andric     return !ranges::empty(__derived());
71fe6060f1SDimitry Andric   }
72fe6060f1SDimitry Andric 
73fe6060f1SDimitry Andric   template <class _D2 = _Derived>
74*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const
requires(const _D2 & __t)7581ad6265SDimitry Andric     requires requires(const _D2& __t) { ranges::empty(__t); }
76fe6060f1SDimitry Andric   {
77fe6060f1SDimitry Andric     return !ranges::empty(__derived());
78fe6060f1SDimitry Andric   }
79fe6060f1SDimitry Andric 
80fe6060f1SDimitry Andric   template <class _D2 = _Derived>
data()81*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto data()
82fe6060f1SDimitry Andric     requires contiguous_iterator<iterator_t<_D2>>
83fe6060f1SDimitry Andric   {
8481ad6265SDimitry Andric     return std::to_address(ranges::begin(__derived()));
85fe6060f1SDimitry Andric   }
86fe6060f1SDimitry Andric 
87fe6060f1SDimitry Andric   template <class _D2 = _Derived>
data()88*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
89fe6060f1SDimitry Andric     requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
90fe6060f1SDimitry Andric   {
9181ad6265SDimitry Andric     return std::to_address(ranges::begin(__derived()));
92fe6060f1SDimitry Andric   }
93fe6060f1SDimitry Andric 
94fe6060f1SDimitry Andric   template <class _D2 = _Derived>
size()95*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto size()
9681ad6265SDimitry Andric     requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
97fe6060f1SDimitry Andric   {
98bdd1243dSDimitry Andric     return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
99fe6060f1SDimitry Andric   }
100fe6060f1SDimitry Andric 
101fe6060f1SDimitry Andric   template <class _D2 = _Derived>
size()102*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
10381ad6265SDimitry Andric     requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
104fe6060f1SDimitry Andric   {
105bdd1243dSDimitry Andric     return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
106fe6060f1SDimitry Andric   }
107fe6060f1SDimitry Andric 
108fe6060f1SDimitry Andric   template <class _D2 = _Derived>
decltype(auto)109*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front()
110fe6060f1SDimitry Andric     requires forward_range<_D2>
111fe6060f1SDimitry Andric   {
112*cb14a3feSDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
113*cb14a3feSDimitry Andric         !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
114fe6060f1SDimitry Andric     return *ranges::begin(__derived());
115fe6060f1SDimitry Andric   }
116fe6060f1SDimitry Andric 
117fe6060f1SDimitry Andric   template <class _D2 = _Derived>
decltype(auto)118*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() const
119fe6060f1SDimitry Andric     requires forward_range<const _D2>
120fe6060f1SDimitry Andric   {
121*cb14a3feSDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
122*cb14a3feSDimitry 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>
decltype(auto)127*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back()
128fe6060f1SDimitry Andric     requires bidirectional_range<_D2> && common_range<_D2>
129fe6060f1SDimitry Andric   {
130*cb14a3feSDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
131*cb14a3feSDimitry Andric         !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
132fe6060f1SDimitry Andric     return *ranges::prev(ranges::end(__derived()));
133fe6060f1SDimitry Andric   }
134fe6060f1SDimitry Andric 
135fe6060f1SDimitry Andric   template <class _D2 = _Derived>
decltype(auto)136*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() const
137fe6060f1SDimitry Andric     requires bidirectional_range<const _D2> && common_range<const _D2>
138fe6060f1SDimitry Andric   {
139*cb14a3feSDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
140*cb14a3feSDimitry 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 <random_access_range _RARange = _Derived>
decltype(auto)145*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) {
146fe6060f1SDimitry Andric     return ranges::begin(__derived())[__index];
147fe6060f1SDimitry Andric   }
148fe6060f1SDimitry Andric 
149fe6060f1SDimitry Andric   template <random_access_range _RARange = const _Derived>
decltype(auto)150*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const {
151fe6060f1SDimitry Andric     return ranges::begin(__derived())[__index];
152fe6060f1SDimitry Andric   }
153fe6060f1SDimitry Andric };
154fe6060f1SDimitry Andric 
1551fd87a68SDimitry Andric } // namespace ranges
156fe6060f1SDimitry Andric 
15706c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
158fe6060f1SDimitry Andric 
159fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
160fe6060f1SDimitry Andric 
161fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H
162