1// Range access functions for containers -*- C++ -*-
2
3// Copyright (C) 2010-2021 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/range_access.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{iterator}
28 */
29
30#ifndef _GLIBCXX_RANGE_ACCESS_H
31#define _GLIBCXX_RANGE_ACCESS_H 1
32
33#pragma GCC system_header
34
35#if __cplusplus >= 201103L
36#include <initializer_list>
37#include <type_traits> // common_type_t, make_signed_t
38#include <bits/stl_iterator.h> // reverse_iterator
39
40namespace std _GLIBCXX_VISIBILITY(default)
41{
42_GLIBCXX_BEGIN_NAMESPACE_VERSION
43
44 /**
45 * @brief Return an iterator pointing to the first element of
46 * the container.
47 * @param __cont Container.
48 */
49 template<typename _Container>
50 inline _GLIBCXX17_CONSTEXPR auto
51 begin(_Container& __cont) -> decltype(__cont.begin())
52 { return __cont.begin(); }
53
54 /**
55 * @brief Return an iterator pointing to the first element of
56 * the const container.
57 * @param __cont Container.
58 */
59 template<typename _Container>
60 inline _GLIBCXX17_CONSTEXPR auto
61 begin(const _Container& __cont) -> decltype(__cont.begin())
62 { return __cont.begin(); }
63
64 /**
65 * @brief Return an iterator pointing to one past the last element of
66 * the container.
67 * @param __cont Container.
68 */
69 template<typename _Container>
70 inline _GLIBCXX17_CONSTEXPR auto
71 end(_Container& __cont) -> decltype(__cont.end())
72 { return __cont.end(); }
73
74 /**
75 * @brief Return an iterator pointing to one past the last element of
76 * the const container.
77 * @param __cont Container.
78 */
79 template<typename _Container>
80 inline _GLIBCXX17_CONSTEXPR auto
81 end(const _Container& __cont) -> decltype(__cont.end())
82 { return __cont.end(); }
83
84 /**
85 * @brief Return an iterator pointing to the first element of the array.
86 * @param __arr Array.
87 */
88 template<typename _Tp, size_t _Nm>
89 inline _GLIBCXX14_CONSTEXPR _Tp*
90 begin(_Tp (&__arr)[_Nm]) noexcept
91 { return __arr; }
92
93 /**
94 * @brief Return an iterator pointing to one past the last element
95 * of the array.
96 * @param __arr Array.
97 */
98 template<typename _Tp, size_t _Nm>
99 inline _GLIBCXX14_CONSTEXPR _Tp*
100 end(_Tp (&__arr)[_Nm]) noexcept
101 { return __arr + _Nm; }
102
103#if __cplusplus >= 201402L
104
105 template<typename _Tp> class valarray;
106 // These overloads must be declared for cbegin and cend to use them.
107 template<typename _Tp> _Tp* begin(valarray<_Tp>&) noexcept;
108 template<typename _Tp> const _Tp* begin(const valarray<_Tp>&) noexcept;
109 template<typename _Tp> _Tp* end(valarray<_Tp>&) noexcept;
110 template<typename _Tp> const _Tp* end(const valarray<_Tp>&) noexcept;
111
112 /**
113 * @brief Return an iterator pointing to the first element of
114 * the const container.
115 * @param __cont Container.
116 */
117 template<typename _Container>
118 inline constexpr auto
119 cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont)))
120 -> decltype(std::begin(__cont))
121 { return std::begin(__cont); }
122
123 /**
124 * @brief Return an iterator pointing to one past the last element of
125 * the const container.
126 * @param __cont Container.
127 */
128 template<typename _Container>
129 inline constexpr auto
130 cend(const _Container& __cont) noexcept(noexcept(std::end(__cont)))
131 -> decltype(std::end(__cont))
132 { return std::end(__cont); }
133
134 /**
135 * @brief Return a reverse iterator pointing to the last element of
136 * the container.
137 * @param __cont Container.
138 */
139 template<typename _Container>
140 inline _GLIBCXX17_CONSTEXPR auto
141 rbegin(_Container& __cont) -> decltype(__cont.rbegin())
142 { return __cont.rbegin(); }
143
144 /**
145 * @brief Return a reverse iterator pointing to the last element of
146 * the const container.
147 * @param __cont Container.
148 */
149 template<typename _Container>
150 inline _GLIBCXX17_CONSTEXPR auto
151 rbegin(const _Container& __cont) -> decltype(__cont.rbegin())
152 { return __cont.rbegin(); }
153
154 /**
155 * @brief Return a reverse iterator pointing one past the first element of
156 * the container.
157 * @param __cont Container.
158 */
159 template<typename _Container>
160 inline _GLIBCXX17_CONSTEXPR auto
161 rend(_Container& __cont) -> decltype(__cont.rend())
162 { return __cont.rend(); }
163
164 /**
165 * @brief Return a reverse iterator pointing one past the first element of
166 * the const container.
167 * @param __cont Container.
168 */
169 template<typename _Container>
170 inline _GLIBCXX17_CONSTEXPR auto
171 rend(const _Container& __cont) -> decltype(__cont.rend())
172 { return __cont.rend(); }
173
174 /**
175 * @brief Return a reverse iterator pointing to the last element of
176 * the array.
177 * @param __arr Array.
178 */
179 template<typename _Tp, size_t _Nm>
180 inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
181 rbegin(_Tp (&__arr)[_Nm]) noexcept
182 { return reverse_iterator<_Tp*>(__arr + _Nm); }
183
184 /**
185 * @brief Return a reverse iterator pointing one past the first element of
186 * the array.
187 * @param __arr Array.
188 */
189 template<typename _Tp, size_t _Nm>
190 inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
191 rend(_Tp (&__arr)[_Nm]) noexcept
192 { return reverse_iterator<_Tp*>(__arr); }
193
194 /**
195 * @brief Return a reverse iterator pointing to the last element of
196 * the initializer_list.
197 * @param __il initializer_list.
198 */
199 template<typename _Tp>
200 inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
201 rbegin(initializer_list<_Tp> __il) noexcept
202 { return reverse_iterator<const _Tp*>(__il.end()); }
203
204 /**
205 * @brief Return a reverse iterator pointing one past the first element of
206 * the initializer_list.
207 * @param __il initializer_list.
208 */
209 template<typename _Tp>
210 inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
211 rend(initializer_list<_Tp> __il) noexcept
212 { return reverse_iterator<const _Tp*>(__il.begin()); }
213
214 /**
215 * @brief Return a reverse iterator pointing to the last element of
216 * the const container.
217 * @param __cont Container.
218 */
219 template<typename _Container>
220 inline _GLIBCXX17_CONSTEXPR auto
221 crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont))
222 { return std::rbegin(__cont); }
223
224 /**
225 * @brief Return a reverse iterator pointing one past the first element of
226 * the const container.
227 * @param __cont Container.
228 */
229 template<typename _Container>
230 inline _GLIBCXX17_CONSTEXPR auto
231 crend(const _Container& __cont) -> decltype(std::rend(__cont))
232 { return std::rend(__cont); }
233
234#endif // C++14
235
236#if __cplusplus >= 201703L
237#define __cpp_lib_nonmember_container_access 201411
238
239 /**
240 * @brief Return the size of a container.
241 * @param __cont Container.
242 */
243 template <typename _Container>
244 constexpr auto
245 size(const _Container& __cont) noexcept(noexcept(__cont.size()))
246 -> decltype(__cont.size())
247 { return __cont.size(); }
248
249 /**
250 * @brief Return the size of an array.
251 */
252 template <typename _Tp, size_t _Nm>
253 constexpr size_t
254 size(const _Tp (&)[_Nm]) noexcept
255 { return _Nm; }
256
257 /**
258 * @brief Return whether a container is empty.
259 * @param __cont Container.
260 */
261 template <typename _Container>
262 [[nodiscard]] constexpr auto
263 empty(const _Container& __cont) noexcept(noexcept(__cont.empty()))
264 -> decltype(__cont.empty())
265 { return __cont.empty(); }
266
267 /**
268 * @brief Return whether an array is empty (always false).
269 */
270 template <typename _Tp, size_t _Nm>
271 [[nodiscard]] constexpr bool
272 empty(const _Tp (&)[_Nm]) noexcept
273 { return false; }
274
275 /**
276 * @brief Return whether an initializer_list is empty.
277 * @param __il Initializer list.
278 */
279 template <typename _Tp>
280 [[nodiscard]] constexpr bool
281 empty(initializer_list<_Tp> __il) noexcept
282 { return __il.size() == 0;}
283
284 /**
285 * @brief Return the data pointer of a container.
286 * @param __cont Container.
287 */
288 template <typename _Container>
289 constexpr auto
290 data(_Container& __cont) noexcept(noexcept(__cont.data()))
291 -> decltype(__cont.data())
292 { return __cont.data(); }
293
294 /**
295 * @brief Return the data pointer of a const container.
296 * @param __cont Container.
297 */
298 template <typename _Container>
299 constexpr auto
300 data(const _Container& __cont) noexcept(noexcept(__cont.data()))
301 -> decltype(__cont.data())
302 { return __cont.data(); }
303
304 /**
305 * @brief Return the data pointer of an array.
306 * @param __array Array.
307 */
308 template <typename _Tp, size_t _Nm>
309 constexpr _Tp*
310 data(_Tp (&__array)[_Nm]) noexcept
311 { return __array; }
312
313 /**
314 * @brief Return the data pointer of an initializer list.
315 * @param __il Initializer list.
316 */
317 template <typename _Tp>
318 constexpr const _Tp*
319 data(initializer_list<_Tp> __il) noexcept
320 { return __il.begin(); }
321
322#if __cplusplus > 201703L
323#define __cpp_lib_ssize 201902L
324 template<typename _Container>
325 constexpr auto
326 ssize(const _Container& __cont)
327 noexcept(noexcept(__cont.size()))
328 -> common_type_t<ptrdiff_t, make_signed_t<decltype(__cont.size())>>
329 {
330 using type = make_signed_t<decltype(__cont.size())>;
331 return static_cast<common_type_t<ptrdiff_t, type>>(__cont.size());
332 }
333
334 template<typename _Tp, ptrdiff_t _Num>
335 constexpr ptrdiff_t
336 ssize(const _Tp (&)[_Num]) noexcept
337 { return _Num; }
338#endif // C++20
339
340#endif // C++17
341_GLIBCXX_END_NAMESPACE_VERSION
342} // namespace
343
344#endif // C++11
345#endif // _GLIBCXX_RANGE_ACCESS_H
346