]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/std/array
libstdc++: Simplify std::array accessors [PR104719]
[thirdparty/gcc.git] / libstdc++-v3 / include / std / array
CommitLineData
af13a7a6
BK
1// <array> -*- C++ -*-
2
7adcbafe 3// Copyright (C) 2007-2022 Free Software Foundation, Inc.
af13a7a6
BK
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
748086b7 8// Free Software Foundation; either version 3, or (at your option)
af13a7a6
BK
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
748086b7
JJ
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.
af13a7a6 19
748086b7
JJ
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/>.
af13a7a6
BK
24
25/** @file include/array
26 * This is a Standard C++ Library header.
27 */
28
4514bed6
BK
29#ifndef _GLIBCXX_ARRAY
30#define _GLIBCXX_ARRAY 1
af13a7a6
BK
31
32#pragma GCC system_header
33
734f5023 34#if __cplusplus < 201103L
ab65a4c7 35# include <bits/c++0x_warning.h>
57317d2a 36#else
af13a7a6 37
261d5a4a
JW
38#include <compare>
39#include <initializer_list>
40
41#include <type_traits>
beb0086f 42#include <bits/functexcept.h>
e133ace8 43#include <bits/stl_algobase.h>
261d5a4a
JW
44#include <bits/range_access.h> // std::begin, std::end etc.
45#include <bits/utility.h> // std::index_sequence, std::tuple_size
6db08247 46#include <debug/assertions.h>
e133ace8 47
12ffa228
BK
48namespace std _GLIBCXX_VISIBILITY(default)
49{
6db08247 50_GLIBCXX_BEGIN_NAMESPACE_VERSION
53dc5044 51
ef8d5ac0 52 template<typename _Tp, size_t _Nm>
90f9c94e
PC
53 struct __array_traits
54 {
ef8d5ac0
JW
55 using _Type = _Tp[_Nm];
56 using _Is_swappable = __is_swappable<_Tp>;
57 using _Is_nothrow_swappable = __is_nothrow_swappable<_Tp>;
90f9c94e
PC
58 };
59
60 template<typename _Tp>
61 struct __array_traits<_Tp, 0>
62 {
ef8d5ac0
JW
63 // Empty type used instead of _Tp[0] for std::array<_Tp, 0>.
64 struct _Type
65 {
66 // Indexing is undefined.
67 __attribute__((__always_inline__,__artificial__,__noreturn__))
68 _Tp& operator[](size_t) const noexcept { __builtin_trap(); }
69
70 // Conversion to a pointer produces a null pointer.
71 __attribute__((__always_inline__,__artificial__))
72 operator _Tp*() const noexcept { return nullptr; }
73 };
74
75 using _Is_swappable = true_type;
76 using _Is_nothrow_swappable = true_type;
90f9c94e
PC
77 };
78
53dc5044
PC
79 /**
80 * @brief A standard container for storing a fixed size sequence of elements.
81 *
82 * @ingroup sequences
83 *
84 * Meets the requirements of a <a href="tables.html#65">container</a>, a
85 * <a href="tables.html#66">reversible container</a>, and a
86 * <a href="tables.html#67">sequence</a>.
87 *
88 * Sets support random access iterators.
89 *
d632488a 90 * @tparam Tp Type of element. Required to be a complete type.
cb0de9b6 91 * @tparam Nm Number of elements.
53dc5044
PC
92 */
93 template<typename _Tp, std::size_t _Nm>
94 struct array
95 {
96 typedef _Tp value_type;
a7d0c94e
BK
97 typedef value_type* pointer;
98 typedef const value_type* const_pointer;
53dc5044
PC
99 typedef value_type& reference;
100 typedef const value_type& const_reference;
101 typedef value_type* iterator;
102 typedef const value_type* const_iterator;
103 typedef std::size_t size_type;
104 typedef std::ptrdiff_t difference_type;
105 typedef std::reverse_iterator<iterator> reverse_iterator;
106 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
107
108 // Support for zero-sized arrays mandatory.
ef8d5ac0 109 typename __array_traits<_Tp, _Nm>::_Type _M_elems;
53dc5044
PC
110
111 // No explicit construct/copy/destroy for aggregate type.
112
113 // DR 776.
1c09b664 114 _GLIBCXX20_CONSTEXPR void
53dc5044
PC
115 fill(const value_type& __u)
116 { std::fill_n(begin(), size(), __u); }
117
1c09b664 118 _GLIBCXX20_CONSTEXPR void
53dc5044 119 swap(array& __other)
ef8d5ac0 120 noexcept(__array_traits<_Tp, _Nm>::_Is_nothrow_swappable::value)
53dc5044
PC
121 { std::swap_ranges(begin(), end(), __other.begin()); }
122
123 // Iterators.
756eabac 124 [[__gnu__::__const__, __nodiscard__]]
06db9920 125 _GLIBCXX17_CONSTEXPR iterator
18eeaec4 126 begin() noexcept
a7d0c94e 127 { return iterator(data()); }
53dc5044 128
0d04fe49 129 [[__nodiscard__]]
06db9920 130 _GLIBCXX17_CONSTEXPR const_iterator
18eeaec4 131 begin() const noexcept
a7d0c94e 132 { return const_iterator(data()); }
53dc5044 133
756eabac 134 [[__gnu__::__const__, __nodiscard__]]
06db9920 135 _GLIBCXX17_CONSTEXPR iterator
18eeaec4 136 end() noexcept
a7d0c94e 137 { return iterator(data() + _Nm); }
53dc5044 138
0d04fe49 139 [[__nodiscard__]]
06db9920 140 _GLIBCXX17_CONSTEXPR const_iterator
18eeaec4 141 end() const noexcept
a7d0c94e 142 { return const_iterator(data() + _Nm); }
53dc5044 143
756eabac 144 [[__gnu__::__const__, __nodiscard__]]
06db9920 145 _GLIBCXX17_CONSTEXPR reverse_iterator
18eeaec4 146 rbegin() noexcept
53dc5044
PC
147 { return reverse_iterator(end()); }
148
0d04fe49 149 [[__nodiscard__]]
06db9920 150 _GLIBCXX17_CONSTEXPR const_reverse_iterator
18eeaec4 151 rbegin() const noexcept
53dc5044
PC
152 { return const_reverse_iterator(end()); }
153
756eabac 154 [[__gnu__::__const__, __nodiscard__]]
06db9920 155 _GLIBCXX17_CONSTEXPR reverse_iterator
18eeaec4 156 rend() noexcept
53dc5044
PC
157 { return reverse_iterator(begin()); }
158
0d04fe49 159 [[__nodiscard__]]
06db9920 160 _GLIBCXX17_CONSTEXPR const_reverse_iterator
18eeaec4 161 rend() const noexcept
53dc5044
PC
162 { return const_reverse_iterator(begin()); }
163
0d04fe49 164 [[__nodiscard__]]
06db9920 165 _GLIBCXX17_CONSTEXPR const_iterator
18eeaec4 166 cbegin() const noexcept
90f9c94e 167 { return const_iterator(data()); }
53dc5044 168
0d04fe49 169 [[__nodiscard__]]
06db9920 170 _GLIBCXX17_CONSTEXPR const_iterator
18eeaec4 171 cend() const noexcept
90f9c94e 172 { return const_iterator(data() + _Nm); }
53dc5044 173
0d04fe49 174 [[__nodiscard__]]
06db9920 175 _GLIBCXX17_CONSTEXPR const_reverse_iterator
18eeaec4 176 crbegin() const noexcept
53dc5044
PC
177 { return const_reverse_iterator(end()); }
178
0d04fe49 179 [[__nodiscard__]]
06db9920 180 _GLIBCXX17_CONSTEXPR const_reverse_iterator
18eeaec4 181 crend() const noexcept
53dc5044
PC
182 { return const_reverse_iterator(begin()); }
183
184 // Capacity.
756eabac 185 [[__gnu__::__const__, __nodiscard__]]
33ac58d5 186 constexpr size_type
18eeaec4 187 size() const noexcept { return _Nm; }
53dc5044 188
756eabac 189 [[__gnu__::__const__, __nodiscard__]]
33ac58d5 190 constexpr size_type
18eeaec4 191 max_size() const noexcept { return _Nm; }
53dc5044 192
756eabac 193 [[__gnu__::__const__, __nodiscard__]]
0d04fe49 194 constexpr bool
18eeaec4 195 empty() const noexcept { return size() == 0; }
53dc5044
PC
196
197 // Element access.
0d04fe49 198 [[__nodiscard__]]
06db9920 199 _GLIBCXX17_CONSTEXPR reference
b4efa80e 200 operator[](size_type __n) noexcept
6db08247
FD
201 {
202 __glibcxx_requires_subscript(__n);
ef8d5ac0 203 return _M_elems[__n];
6db08247 204 }
53dc5044 205
0d04fe49 206 [[__nodiscard__]]
bfef3a71
BK
207 constexpr const_reference
208 operator[](size_type __n) const noexcept
6db08247 209 {
91cfacc4 210#if __cplusplus >= 201402L
6db08247 211 __glibcxx_requires_subscript(__n);
91cfacc4 212#endif
ef8d5ac0 213 return _M_elems[__n];
6db08247 214 }
53dc5044 215
06db9920 216 _GLIBCXX17_CONSTEXPR reference
53dc5044
PC
217 at(size_type __n)
218 {
219 if (__n >= _Nm)
9779c871
PP
220 std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
221 ">= _Nm (which is %zu)"),
222 __n, _Nm);
ef8d5ac0 223 return _M_elems[__n];
53dc5044
PC
224 }
225
bfef3a71 226 constexpr const_reference
53dc5044
PC
227 at(size_type __n) const
228 {
885e8121
JW
229 // Result of conditional expression must be an lvalue so use
230 // boolean ? lvalue : (throw-expr, lvalue)
ef8d5ac0 231 return __n < _Nm ? _M_elems[__n]
9779c871
PP
232 : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
233 ">= _Nm (which is %zu)"),
234 __n, _Nm),
ef8d5ac0 235 _M_elems[__n]);
9bc13c23 236 }
53dc5044 237
0d04fe49 238 [[__nodiscard__]]
06db9920 239 _GLIBCXX17_CONSTEXPR reference
b4efa80e 240 front() noexcept
6db08247
FD
241 {
242 __glibcxx_requires_nonempty();
ef8d5ac0 243 return _M_elems[0];
6db08247 244 }
53dc5044 245
0d04fe49 246 [[__nodiscard__]]
33ac58d5 247 constexpr const_reference
b4efa80e 248 front() const noexcept
6db08247 249 {
91cfacc4 250#if __cplusplus >= 201402L
6db08247 251 __glibcxx_requires_nonempty();
91cfacc4 252#endif
ef8d5ac0 253 return _M_elems[0];
6db08247 254 }
53dc5044 255
0d04fe49 256 [[__nodiscard__]]
06db9920 257 _GLIBCXX17_CONSTEXPR reference
b4efa80e 258 back() noexcept
6db08247
FD
259 {
260 __glibcxx_requires_nonempty();
ef8d5ac0 261 return _M_elems[_Nm - 1];
6db08247 262 }
53dc5044 263
0d04fe49 264 [[__nodiscard__]]
33ac58d5 265 constexpr const_reference
b4efa80e 266 back() const noexcept
33ac58d5 267 {
91cfacc4 268#if __cplusplus >= 201402L
6db08247 269 __glibcxx_requires_nonempty();
91cfacc4 270#endif
ef8d5ac0 271 return _M_elems[_Nm - 1];
a9ba8ba5 272 }
53dc5044 273
756eabac 274 [[__gnu__::__const__, __nodiscard__]]
06db9920 275 _GLIBCXX17_CONSTEXPR pointer
18eeaec4 276 data() noexcept
ef8d5ac0 277 { return _M_elems; }
53dc5044 278
0d04fe49 279 [[__nodiscard__]]
06db9920 280 _GLIBCXX17_CONSTEXPR const_pointer
18eeaec4 281 data() const noexcept
ef8d5ac0 282 { return _M_elems; }
53dc5044
PC
283 };
284
af181c91
JW
285#if __cpp_deduction_guides >= 201606
286 template<typename _Tp, typename... _Up>
287 array(_Tp, _Up...)
288 -> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
289 1 + sizeof...(_Up)>;
290#endif
291
53dc5044
PC
292 // Array comparisons.
293 template<typename _Tp, std::size_t _Nm>
0d04fe49 294 [[__nodiscard__]]
3a66e68a 295 _GLIBCXX20_CONSTEXPR
33ac58d5 296 inline bool
53dc5044
PC
297 operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
298 { return std::equal(__one.begin(), __one.end(), __two.begin()); }
299
3a4cc628
JW
300#if __cpp_lib_three_way_comparison && __cpp_lib_concepts
301 template<typename _Tp, size_t _Nm>
0d04fe49 302 [[nodiscard]]
3a4cc628
JW
303 constexpr __detail::__synth3way_t<_Tp>
304 operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
305 {
2f983fa6 306 if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value)
74d14778 307 if (!std::__is_constant_evaluated())
2f983fa6
JW
308 {
309 constexpr size_t __n = _Nm * sizeof(_Tp);
310 return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0;
311 }
2f983fa6
JW
312
313 for (size_t __i = 0; __i < _Nm; ++__i)
3a4cc628 314 {
2f983fa6
JW
315 auto __c = __detail::__synth3way(__a[__i], __b[__i]);
316 if (__c != 0)
317 return __c;
3a4cc628
JW
318 }
319 return strong_ordering::equal;
320 }
321#else
53dc5044 322 template<typename _Tp, std::size_t _Nm>
0d04fe49 323 [[__nodiscard__]]
3a66e68a 324 _GLIBCXX20_CONSTEXPR
53dc5044
PC
325 inline bool
326 operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
327 { return !(__one == __two); }
328
329 template<typename _Tp, std::size_t _Nm>
0d04fe49 330 [[__nodiscard__]]
3a66e68a 331 _GLIBCXX20_CONSTEXPR
53dc5044
PC
332 inline bool
333 operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
33ac58d5 334 {
53dc5044 335 return std::lexicographical_compare(__a.begin(), __a.end(),
33ac58d5 336 __b.begin(), __b.end());
53dc5044
PC
337 }
338
339 template<typename _Tp, std::size_t _Nm>
0d04fe49 340 [[__nodiscard__]]
3a66e68a 341 _GLIBCXX20_CONSTEXPR
53dc5044
PC
342 inline bool
343 operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
344 { return __two < __one; }
345
346 template<typename _Tp, std::size_t _Nm>
0d04fe49 347 [[__nodiscard__]]
3a66e68a 348 _GLIBCXX20_CONSTEXPR
53dc5044
PC
349 inline bool
350 operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
351 { return !(__one > __two); }
352
353 template<typename _Tp, std::size_t _Nm>
0d04fe49 354 [[__nodiscard__]]
3a66e68a 355 _GLIBCXX20_CONSTEXPR
53dc5044
PC
356 inline bool
357 operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
358 { return !(__one < __two); }
3a4cc628 359#endif // three_way_comparison && concepts
53dc5044 360
18eeaec4 361 // Specialized algorithms.
53dc5044 362 template<typename _Tp, std::size_t _Nm>
1c09b664 363 _GLIBCXX20_CONSTEXPR
6b9539e2
DK
364 inline
365#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
366 // Constrained free swap overload, see p0185r1
ef8d5ac0 367 __enable_if_t<__array_traits<_Tp, _Nm>::_Is_swappable::value>
6b9539e2
DK
368#else
369 void
370#endif
53dc5044 371 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
18eeaec4 372 noexcept(noexcept(__one.swap(__two)))
53dc5044
PC
373 { __one.swap(__two); }
374
a2863bde
VV
375#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
376 template<typename _Tp, std::size_t _Nm>
ef8d5ac0 377 __enable_if_t<!__array_traits<_Tp, _Nm>::_Is_swappable::value>
a2863bde
VV
378 swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
379#endif
380
53dc5044 381 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
0d04fe49 382 [[__nodiscard__]]
9480716c 383 constexpr _Tp&
18eeaec4 384 get(array<_Tp, _Nm>& __arr) noexcept
9771644a 385 {
3c040fa4 386 static_assert(_Int < _Nm, "array index is within bounds");
ef8d5ac0 387 return __arr._M_elems[_Int];
9771644a 388 }
53dc5044 389
18eeaec4 390 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
0d04fe49 391 [[__nodiscard__]]
9480716c 392 constexpr _Tp&&
18eeaec4 393 get(array<_Tp, _Nm>&& __arr) noexcept
9771644a 394 {
3c040fa4 395 static_assert(_Int < _Nm, "array index is within bounds");
6db08247 396 return std::move(std::get<_Int>(__arr));
9771644a 397 }
18eeaec4 398
53dc5044 399 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
0d04fe49 400 [[__nodiscard__]]
9480716c 401 constexpr const _Tp&
18eeaec4 402 get(const array<_Tp, _Nm>& __arr) noexcept
9771644a 403 {
3c040fa4 404 static_assert(_Int < _Nm, "array index is within bounds");
ef8d5ac0 405 return __arr._M_elems[_Int];
9771644a 406 }
53dc5044 407
ccbbf8df 408 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
0d04fe49 409 [[__nodiscard__]]
ccbbf8df
VV
410 constexpr const _Tp&&
411 get(const array<_Tp, _Nm>&& __arr) noexcept
412 {
413 static_assert(_Int < _Nm, "array index is within bounds");
6db08247 414 return std::move(std::get<_Int>(__arr));
ccbbf8df
VV
415 }
416
cb0de9b6
JW
417#if __cplusplus > 201703L
418#define __cpp_lib_to_array 201907L
419
420 template<bool _Move = false, typename _Tp, size_t... _Idx>
421 constexpr array<remove_cv_t<_Tp>, sizeof...(_Idx)>
422 __to_array(_Tp (&__a)[sizeof...(_Idx)], index_sequence<_Idx...>)
423 {
424 if constexpr (_Move)
425 return {{std::move(__a[_Idx])...}};
426 else
427 return {{__a[_Idx]...}};
428 }
429
430 template<typename _Tp, size_t _Nm>
0d04fe49 431 [[nodiscard]]
cb0de9b6
JW
432 constexpr array<remove_cv_t<_Tp>, _Nm>
433 to_array(_Tp (&__a)[_Nm])
434 noexcept(is_nothrow_constructible_v<_Tp, _Tp&>)
435 {
436 static_assert(!is_array_v<_Tp>);
437 static_assert(is_constructible_v<_Tp, _Tp&>);
438 if constexpr (is_constructible_v<_Tp, _Tp&>)
6db08247 439 return __to_array(__a, make_index_sequence<_Nm>{});
cb0de9b6
JW
440 __builtin_unreachable(); // FIXME: see PR c++/91388
441 }
442
443 template<typename _Tp, size_t _Nm>
0d04fe49 444 [[nodiscard]]
cb0de9b6
JW
445 constexpr array<remove_cv_t<_Tp>, _Nm>
446 to_array(_Tp (&&__a)[_Nm])
447 noexcept(is_nothrow_move_constructible_v<_Tp>)
448 {
449 static_assert(!is_array_v<_Tp>);
450 static_assert(is_move_constructible_v<_Tp>);
451 if constexpr (is_move_constructible_v<_Tp>)
6db08247 452 return __to_array<1>(__a, make_index_sequence<_Nm>{});
cb0de9b6
JW
453 __builtin_unreachable(); // FIXME: see PR c++/91388
454 }
455#endif // C++20
456
741aacaf
PC
457 // Tuple interface to class template array.
458
3a004764 459 /// Partial specialization for std::array
261d5a4a 460 template<typename _Tp, size_t _Nm>
6db08247 461 struct tuple_size<array<_Tp, _Nm>>
261d5a4a 462 : public integral_constant<size_t, _Nm> { };
741aacaf 463
3a004764 464 /// Partial specialization for std::array
261d5a4a
JW
465 template<size_t _Ind, typename _Tp, size_t _Nm>
466 struct tuple_element<_Ind, array<_Tp, _Nm>>
741aacaf 467 {
261d5a4a
JW
468 static_assert(_Ind < _Nm, "array index is in range");
469 using type = _Tp;
741aacaf
PC
470 };
471
09aab7e6
JW
472#if __cplusplus >= 201703L
473 template<typename _Tp, size_t _Nm>
474 inline constexpr size_t tuple_size_v<array<_Tp, _Nm>> = _Nm;
475
476 template<typename _Tp, size_t _Nm>
477 inline constexpr size_t tuple_size_v<const array<_Tp, _Nm>> = _Nm;
478#endif
479
261d5a4a 480 template<typename _Tp, size_t _Nm>
6db08247 481 struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type
7d17de7f
FD
482 { };
483
741aacaf
PC
484_GLIBCXX_END_NAMESPACE_VERSION
485} // namespace std
486
734f5023 487#endif // C++11
57317d2a 488
4514bed6 489#endif // _GLIBCXX_ARRAY