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 //===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H
10fe6060f1SDimitry Andric #define _LIBCPP___RANGES_VIEW_INTERFACE_H
11fe6060f1SDimitry Andric 
12*81ad6265SDimitry Andric #include <__assert>
13*81ad6265SDimitry Andric #include <__concepts/derived_from.h>
14*81ad6265SDimitry Andric #include <__concepts/same_as.h>
15fe6060f1SDimitry Andric #include <__config>
16fe6060f1SDimitry Andric #include <__iterator/concepts.h>
17fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h>
18fe6060f1SDimitry Andric #include <__iterator/prev.h>
19fe6060f1SDimitry Andric #include <__memory/pointer_traits.h>
20fe6060f1SDimitry Andric #include <__ranges/access.h>
21fe6060f1SDimitry Andric #include <__ranges/concepts.h>
22fe6060f1SDimitry Andric #include <__ranges/empty.h>
23fe6060f1SDimitry Andric #include <type_traits>
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26fe6060f1SDimitry Andric #  pragma GCC system_header
27fe6060f1SDimitry Andric #endif
28fe6060f1SDimitry Andric 
29fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
30fe6060f1SDimitry Andric 
31*81ad6265SDimitry Andric #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
32fe6060f1SDimitry Andric 
33fe6060f1SDimitry Andric namespace ranges {
34fe6060f1SDimitry Andric 
35fe6060f1SDimitry Andric template<class _Derived>
36fe6060f1SDimitry Andric   requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
3704eeddc0SDimitry Andric class view_interface {
38fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
39fe6060f1SDimitry Andric   constexpr _Derived& __derived() noexcept {
40349cc55cSDimitry Andric     static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
41fe6060f1SDimitry Andric     return static_cast<_Derived&>(*this);
42fe6060f1SDimitry Andric   }
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
45fe6060f1SDimitry Andric   constexpr _Derived const& __derived() const noexcept {
46349cc55cSDimitry Andric     static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>);
47fe6060f1SDimitry Andric     return static_cast<_Derived const&>(*this);
48fe6060f1SDimitry Andric   }
49fe6060f1SDimitry Andric 
50fe6060f1SDimitry Andric public:
51fe6060f1SDimitry Andric   template<class _D2 = _Derived>
52fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
53fe6060f1SDimitry Andric     requires forward_range<_D2>
54fe6060f1SDimitry Andric   {
55fe6060f1SDimitry Andric     return ranges::begin(__derived()) == ranges::end(__derived());
56fe6060f1SDimitry Andric   }
57fe6060f1SDimitry Andric 
58fe6060f1SDimitry Andric   template<class _D2 = _Derived>
59fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
60fe6060f1SDimitry Andric     requires forward_range<const _D2>
61fe6060f1SDimitry Andric   {
62fe6060f1SDimitry Andric     return ranges::begin(__derived()) == ranges::end(__derived());
63fe6060f1SDimitry Andric   }
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric   template<class _D2 = _Derived>
66fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
67fe6060f1SDimitry Andric   constexpr explicit operator bool()
68*81ad6265SDimitry 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>
74fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
75fe6060f1SDimitry Andric   constexpr explicit operator bool() const
76*81ad6265SDimitry Andric     requires requires (const _D2& __t) { ranges::empty(__t); }
77fe6060f1SDimitry Andric   {
78fe6060f1SDimitry Andric     return !ranges::empty(__derived());
79fe6060f1SDimitry Andric   }
80fe6060f1SDimitry Andric 
81fe6060f1SDimitry Andric   template<class _D2 = _Derived>
82fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
83fe6060f1SDimitry Andric   constexpr auto data()
84fe6060f1SDimitry Andric     requires contiguous_iterator<iterator_t<_D2>>
85fe6060f1SDimitry Andric   {
86*81ad6265SDimitry Andric     return std::to_address(ranges::begin(__derived()));
87fe6060f1SDimitry Andric   }
88fe6060f1SDimitry Andric 
89fe6060f1SDimitry Andric   template<class _D2 = _Derived>
90fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
91fe6060f1SDimitry Andric   constexpr auto data() const
92fe6060f1SDimitry Andric     requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
93fe6060f1SDimitry Andric   {
94*81ad6265SDimitry Andric     return std::to_address(ranges::begin(__derived()));
95fe6060f1SDimitry Andric   }
96fe6060f1SDimitry Andric 
97fe6060f1SDimitry Andric   template<class _D2 = _Derived>
98fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
99fe6060f1SDimitry Andric   constexpr auto size()
100*81ad6265SDimitry Andric     requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
101fe6060f1SDimitry Andric   {
102fe6060f1SDimitry Andric     return ranges::end(__derived()) - ranges::begin(__derived());
103fe6060f1SDimitry Andric   }
104fe6060f1SDimitry Andric 
105fe6060f1SDimitry Andric   template<class _D2 = _Derived>
106fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
107fe6060f1SDimitry Andric   constexpr auto size() const
108*81ad6265SDimitry Andric     requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
109fe6060f1SDimitry Andric   {
110fe6060f1SDimitry Andric     return ranges::end(__derived()) - ranges::begin(__derived());
111fe6060f1SDimitry Andric   }
112fe6060f1SDimitry Andric 
113fe6060f1SDimitry Andric   template<class _D2 = _Derived>
114fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
115fe6060f1SDimitry Andric   constexpr decltype(auto) front()
116fe6060f1SDimitry Andric     requires forward_range<_D2>
117fe6060f1SDimitry Andric   {
118fe6060f1SDimitry Andric     _LIBCPP_ASSERT(!empty(),
119fe6060f1SDimitry Andric         "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
120fe6060f1SDimitry Andric     return *ranges::begin(__derived());
121fe6060f1SDimitry Andric   }
122fe6060f1SDimitry Andric 
123fe6060f1SDimitry Andric   template<class _D2 = _Derived>
124fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
125fe6060f1SDimitry Andric   constexpr decltype(auto) front() const
126fe6060f1SDimitry Andric     requires forward_range<const _D2>
127fe6060f1SDimitry Andric   {
128fe6060f1SDimitry Andric     _LIBCPP_ASSERT(!empty(),
129fe6060f1SDimitry Andric         "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
130fe6060f1SDimitry Andric     return *ranges::begin(__derived());
131fe6060f1SDimitry Andric   }
132fe6060f1SDimitry Andric 
133fe6060f1SDimitry Andric   template<class _D2 = _Derived>
134fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
135fe6060f1SDimitry Andric   constexpr decltype(auto) back()
136fe6060f1SDimitry Andric     requires bidirectional_range<_D2> && common_range<_D2>
137fe6060f1SDimitry Andric   {
138fe6060f1SDimitry Andric     _LIBCPP_ASSERT(!empty(),
139fe6060f1SDimitry Andric         "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
140fe6060f1SDimitry Andric     return *ranges::prev(ranges::end(__derived()));
141fe6060f1SDimitry Andric   }
142fe6060f1SDimitry Andric 
143fe6060f1SDimitry Andric   template<class _D2 = _Derived>
144fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
145fe6060f1SDimitry Andric   constexpr decltype(auto) back() const
146fe6060f1SDimitry Andric     requires bidirectional_range<const _D2> && common_range<const _D2>
147fe6060f1SDimitry Andric   {
148fe6060f1SDimitry Andric     _LIBCPP_ASSERT(!empty(),
149fe6060f1SDimitry Andric         "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>
154fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
155fe6060f1SDimitry Andric   constexpr decltype(auto) operator[](range_difference_t<_RARange> __index)
156fe6060f1SDimitry Andric   {
157fe6060f1SDimitry Andric     return ranges::begin(__derived())[__index];
158fe6060f1SDimitry Andric   }
159fe6060f1SDimitry Andric 
160fe6060f1SDimitry Andric   template<random_access_range _RARange = const _Derived>
161fe6060f1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
162fe6060f1SDimitry Andric   constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const
163fe6060f1SDimitry Andric   {
164fe6060f1SDimitry Andric     return ranges::begin(__derived())[__index];
165fe6060f1SDimitry Andric   }
166fe6060f1SDimitry Andric };
167fe6060f1SDimitry Andric 
1681fd87a68SDimitry Andric } // namespace ranges
169fe6060f1SDimitry Andric 
170*81ad6265SDimitry Andric #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
171fe6060f1SDimitry Andric 
172fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
173fe6060f1SDimitry Andric 
174fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H
175