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