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