1// <array> -*- C++ -*-
2
3// Copyright (C) 2007-2019 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 include/array
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_ARRAY
30#define _GLIBCXX_ARRAY 1
31
32#pragma GCC system_header
33
34#if __cplusplus < 201103L
35# include <bits/c++0x_warning.h>
36#else
37
38#include <utility>
39#include <stdexcept>
40#include <bits/stl_algobase.h>
41#include <bits/range_access.h>
42
43namespace std _GLIBCXX_VISIBILITY(default)
44{
45_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
46
47 template<typename _Tp, std::size_t _Nm>
48 struct __array_traits
49 {
50 typedef _Tp _Type[_Nm];
51 typedef __is_swappable<_Tp> _Is_swappable;
52 typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable;
53
54 static constexpr _Tp&
55 _S_ref(const _Type& __t, std::size_t __n) noexcept
56 { return const_cast<_Tp&>(__t[__n]); }
57
58 static constexpr _Tp*
59 _S_ptr(const _Type& __t) noexcept
60 { return const_cast<_Tp*>(__t); }
61 };
62
63 template<typename _Tp>
64 struct __array_traits<_Tp, 0>
65 {
66 struct _Type { };
67 typedef true_type _Is_swappable;
68 typedef true_type _Is_nothrow_swappable;
69
70 static constexpr _Tp&
71 _S_ref(const _Type&, std::size_t) noexcept
72 { return *static_cast<_Tp*>(nullptr); }
73
74 static constexpr _Tp*
75 _S_ptr(const _Type&) noexcept
76 { return nullptr; }
77 };
78
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 *
90 * @tparam Tp Type of element. Required to be a complete type.
91 * @tparam N Number of elements.
92 */
93 template<typename _Tp, std::size_t _Nm>
94 struct array
95 {
96 typedef _Tp value_type;
97 typedef value_type* pointer;
98 typedef const value_type* const_pointer;
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.
109 typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
110 typename _AT_Type::_Type _M_elems;
111
112 // No explicit construct/copy/destroy for aggregate type.
113
114 // DR 776.
115 void
116 fill(const value_type& __u)
117 { std::fill_n(begin(), size(), __u); }
118
119 void
120 swap(array& __other)
121 noexcept(_AT_Type::_Is_nothrow_swappable::value)
122 { std::swap_ranges(begin(), end(), __other.begin()); }
123
124 // Iterators.
125 _GLIBCXX17_CONSTEXPR iterator
126 begin() noexcept
127 { return iterator(data()); }
128
129 _GLIBCXX17_CONSTEXPR const_iterator
130 begin() const noexcept
131 { return const_iterator(data()); }
132
133 _GLIBCXX17_CONSTEXPR iterator
134 end() noexcept
135 { return iterator(data() + _Nm); }
136
137 _GLIBCXX17_CONSTEXPR const_iterator
138 end() const noexcept
139 { return const_iterator(data() + _Nm); }
140
141 _GLIBCXX17_CONSTEXPR reverse_iterator
142 rbegin() noexcept
143 { return reverse_iterator(end()); }
144
145 _GLIBCXX17_CONSTEXPR const_reverse_iterator
146 rbegin() const noexcept
147 { return const_reverse_iterator(end()); }
148
149 _GLIBCXX17_CONSTEXPR reverse_iterator
150 rend() noexcept
151 { return reverse_iterator(begin()); }
152
153 _GLIBCXX17_CONSTEXPR const_reverse_iterator
154 rend() const noexcept
155 { return const_reverse_iterator(begin()); }
156
157 _GLIBCXX17_CONSTEXPR const_iterator
158 cbegin() const noexcept
159 { return const_iterator(data()); }
160
161 _GLIBCXX17_CONSTEXPR const_iterator
162 cend() const noexcept
163 { return const_iterator(data() + _Nm); }
164
165 _GLIBCXX17_CONSTEXPR const_reverse_iterator
166 crbegin() const noexcept
167 { return const_reverse_iterator(end()); }
168
169 _GLIBCXX17_CONSTEXPR const_reverse_iterator
170 crend() const noexcept
171 { return const_reverse_iterator(begin()); }
172
173 // Capacity.
174 constexpr size_type
175 size() const noexcept { return _Nm; }
176
177 constexpr size_type
178 max_size() const noexcept { return _Nm; }
179
180 _GLIBCXX_NODISCARD constexpr bool
181 empty() const noexcept { return size() == 0; }
182
183 // Element access.
184 _GLIBCXX17_CONSTEXPR reference
185 operator[](size_type __n) noexcept
186 { return _AT_Type::_S_ref(_M_elems, __n); }
187
188 constexpr const_reference
189 operator[](size_type __n) const noexcept
190 { return _AT_Type::_S_ref(_M_elems, __n); }
191
192 _GLIBCXX17_CONSTEXPR reference
193 at(size_type __n)
194 {
195 if (__n >= _Nm)
196 std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
197 ">= _Nm (which is %zu)"),
198 __n, _Nm);
199 return _AT_Type::_S_ref(_M_elems, __n);
200 }
201
202 constexpr const_reference
203 at(size_type __n) const
204 {
205 // Result of conditional expression must be an lvalue so use
206 // boolean ? lvalue : (throw-expr, lvalue)
207 return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
208 : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
209 ">= _Nm (which is %zu)"),
210 __n, _Nm),
211 _AT_Type::_S_ref(_M_elems, 0));
212 }
213
214 _GLIBCXX17_CONSTEXPR reference
215 front() noexcept
216 { return *begin(); }
217
218 constexpr const_reference
219 front() const noexcept
220 { return _AT_Type::_S_ref(_M_elems, 0); }
221
222 _GLIBCXX17_CONSTEXPR reference
223 back() noexcept
224 { return _Nm ? *(end() - 1) : *end(); }
225
226 constexpr const_reference
227 back() const noexcept
228 {
229 return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
230 : _AT_Type::_S_ref(_M_elems, 0);
231 }
232
233 _GLIBCXX17_CONSTEXPR pointer
234 data() noexcept
235 { return _AT_Type::_S_ptr(_M_elems); }
236
237 _GLIBCXX17_CONSTEXPR const_pointer
238 data() const noexcept
239 { return _AT_Type::_S_ptr(_M_elems); }
240 };
241
242#if __cpp_deduction_guides >= 201606
243 template<typename _Tp, typename... _Up>
244 array(_Tp, _Up...)
245 -> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
246 1 + sizeof...(_Up)>;
247#endif
248
249 // Array comparisons.
250 template<typename _Tp, std::size_t _Nm>
251 inline bool
252 operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
253 { return std::equal(__one.begin(), __one.end(), __two.begin()); }
254
255 template<typename _Tp, std::size_t _Nm>
256 inline bool
257 operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
258 { return !(__one == __two); }
259
260 template<typename _Tp, std::size_t _Nm>
261 inline bool
262 operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
263 {
264 return std::lexicographical_compare(__a.begin(), __a.end(),
265 __b.begin(), __b.end());
266 }
267
268 template<typename _Tp, std::size_t _Nm>
269 inline bool
270 operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
271 { return __two < __one; }
272
273 template<typename _Tp, std::size_t _Nm>
274 inline bool
275 operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
276 { return !(__one > __two); }
277
278 template<typename _Tp, std::size_t _Nm>
279 inline bool
280 operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
281 { return !(__one < __two); }
282
283 // Specialized algorithms.
284 template<typename _Tp, std::size_t _Nm>
285 inline
286#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
287 // Constrained free swap overload, see p0185r1
288 typename enable_if<
289 _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value
290 >::type
291#else
292 void
293#endif
294 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
295 noexcept(noexcept(__one.swap(__two)))
296 { __one.swap(__two); }
297
298#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
299 template<typename _Tp, std::size_t _Nm>
300 typename enable_if<
301 !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
302 swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
303#endif
304
305 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
306 constexpr _Tp&
307 get(array<_Tp, _Nm>& __arr) noexcept
308 {
309 static_assert(_Int < _Nm, "array index is within bounds");
310 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
311 _S_ref(__arr._M_elems, _Int);
312 }
313
314 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
315 constexpr _Tp&&
316 get(array<_Tp, _Nm>&& __arr) noexcept
317 {
318 static_assert(_Int < _Nm, "array index is within bounds");
319 return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
320 }
321
322 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
323 constexpr const _Tp&
324 get(const array<_Tp, _Nm>& __arr) noexcept
325 {
326 static_assert(_Int < _Nm, "array index is within bounds");
327 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
328 _S_ref(__arr._M_elems, _Int);
329 }
330
331 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
332 constexpr const _Tp&&
333 get(const array<_Tp, _Nm>&& __arr) noexcept
334 {
335 static_assert(_Int < _Nm, "array index is within bounds");
336 return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
337 }
338
339_GLIBCXX_END_NAMESPACE_CONTAINER
340} // namespace std
341
342namespace std _GLIBCXX_VISIBILITY(default)
343{
344_GLIBCXX_BEGIN_NAMESPACE_VERSION
345
346 // Tuple interface to class template array.
347
348 /// tuple_size
349 template<typename _Tp>
350 struct tuple_size;
351
352 /// Partial specialization for std::array
353 template<typename _Tp, std::size_t _Nm>
354 struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>>
355 : public integral_constant<std::size_t, _Nm> { };
356
357 /// tuple_element
358 template<std::size_t _Int, typename _Tp>
359 struct tuple_element;
360
361 /// Partial specialization for std::array
362 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
363 struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>>
364 {
365 static_assert(_Int < _Nm, "index is out of bounds");
366 typedef _Tp type;
367 };
368
369 template<typename _Tp, std::size_t _Nm>
370 struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type
371 { };
372
373_GLIBCXX_END_NAMESPACE_VERSION
374} // namespace std
375
376#ifdef _GLIBCXX_DEBUG
377# include <debug/array>
378#endif
379
380#ifdef _GLIBCXX_PROFILE
381# include <profile/array>
382#endif
383
384#endif // C++11
385
386#endif // _GLIBCXX_ARRAY
387