xref: /freebsd/contrib/llvm-project/libcxx/include/__ranges/view_interface.h (revision e9e8876a4d6afc1ad5315faaa191b25121a813d7)
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   _LIBCPP_HIDE_FROM_ABI
47   constexpr _Derived& __derived() noexcept {
48     return static_cast<_Derived&>(*this);
49   }
50 
51   _LIBCPP_HIDE_FROM_ABI
52   constexpr _Derived const& __derived() const noexcept {
53     return static_cast<_Derived const&>(*this);
54   }
55 
56 public:
57   template<class _D2 = _Derived>
58   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
59     noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
60     requires forward_range<_D2>
61   {
62     return ranges::begin(__derived()) == ranges::end(__derived());
63   }
64 
65   template<class _D2 = _Derived>
66   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
67     noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
68     requires forward_range<const _D2>
69   {
70     return ranges::begin(__derived()) == ranges::end(__derived());
71   }
72 
73   template<class _D2 = _Derived>
74   _LIBCPP_HIDE_FROM_ABI
75   constexpr explicit operator bool()
76     noexcept(noexcept(ranges::empty(declval<_D2>())))
77     requires __can_empty<_D2>
78   {
79     return !ranges::empty(__derived());
80   }
81 
82   template<class _D2 = _Derived>
83   _LIBCPP_HIDE_FROM_ABI
84   constexpr explicit operator bool() const
85     noexcept(noexcept(ranges::empty(declval<const _D2>())))
86     requires __can_empty<const _D2>
87   {
88     return !ranges::empty(__derived());
89   }
90 
91   template<class _D2 = _Derived>
92   _LIBCPP_HIDE_FROM_ABI
93   constexpr auto data()
94     noexcept(noexcept(_VSTD::to_address(ranges::begin(__derived()))))
95     requires contiguous_iterator<iterator_t<_D2>>
96   {
97     return _VSTD::to_address(ranges::begin(__derived()));
98   }
99 
100   template<class _D2 = _Derived>
101   _LIBCPP_HIDE_FROM_ABI
102   constexpr auto data() const
103     noexcept(noexcept(_VSTD::to_address(ranges::begin(__derived()))))
104     requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
105   {
106     return _VSTD::to_address(ranges::begin(__derived()));
107   }
108 
109   template<class _D2 = _Derived>
110   _LIBCPP_HIDE_FROM_ABI
111   constexpr auto size()
112     noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
113     requires forward_range<_D2>
114       && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
115   {
116     return ranges::end(__derived()) - ranges::begin(__derived());
117   }
118 
119   template<class _D2 = _Derived>
120   _LIBCPP_HIDE_FROM_ABI
121   constexpr auto size() const
122     noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
123     requires forward_range<const _D2>
124       && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
125   {
126     return ranges::end(__derived()) - ranges::begin(__derived());
127   }
128 
129   template<class _D2 = _Derived>
130   _LIBCPP_HIDE_FROM_ABI
131   constexpr decltype(auto) front()
132     noexcept(noexcept(*ranges::begin(__derived())))
133     requires forward_range<_D2>
134   {
135     _LIBCPP_ASSERT(!empty(),
136         "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
137     return *ranges::begin(__derived());
138   }
139 
140   template<class _D2 = _Derived>
141   _LIBCPP_HIDE_FROM_ABI
142   constexpr decltype(auto) front() const
143     noexcept(noexcept(*ranges::begin(__derived())))
144     requires forward_range<const _D2>
145   {
146     _LIBCPP_ASSERT(!empty(),
147         "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
148     return *ranges::begin(__derived());
149   }
150 
151   template<class _D2 = _Derived>
152   _LIBCPP_HIDE_FROM_ABI
153   constexpr decltype(auto) back()
154     noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
155     requires bidirectional_range<_D2> && common_range<_D2>
156   {
157     _LIBCPP_ASSERT(!empty(),
158         "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
159     return *ranges::prev(ranges::end(__derived()));
160   }
161 
162   template<class _D2 = _Derived>
163   _LIBCPP_HIDE_FROM_ABI
164   constexpr decltype(auto) back() const
165     noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
166     requires bidirectional_range<const _D2> && common_range<const _D2>
167   {
168     _LIBCPP_ASSERT(!empty(),
169         "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
170     return *ranges::prev(ranges::end(__derived()));
171   }
172 
173   template<random_access_range _RARange = _Derived>
174   _LIBCPP_HIDE_FROM_ABI
175   constexpr decltype(auto) operator[](range_difference_t<_RARange> __index)
176     noexcept(noexcept(ranges::begin(__derived())[__index]))
177   {
178     return ranges::begin(__derived())[__index];
179   }
180 
181   template<random_access_range _RARange = const _Derived>
182   _LIBCPP_HIDE_FROM_ABI
183   constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const
184     noexcept(noexcept(ranges::begin(__derived())[__index]))
185   {
186     return ranges::begin(__derived())[__index];
187   }
188 };
189 
190 }
191 
192 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
193 
194 _LIBCPP_END_NAMESPACE_STD
195 
196 _LIBCPP_POP_MACROS
197 
198 #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H
199