1// <array> -*- C++ -*- 2 3// Copyright (C) 2007-2020 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 <bits/functexcept.h> 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 Nm 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 _GLIBCXX20_CONSTEXPR void 116 fill(const value_type& __u) 117 { std::fill_n(begin(), size(), __u); } 118 119 _GLIBCXX20_CONSTEXPR 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 _GLIBCXX20_CONSTEXPR 252 inline bool 253 operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 254 { return std::equal(__one.begin(), __one.end(), __two.begin()); } 255 256#if __cpp_lib_three_way_comparison && __cpp_lib_concepts 257 template<typename _Tp, size_t _Nm> 258 constexpr __detail::__synth3way_t<_Tp> 259 operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) 260 { 261#ifdef __cpp_lib_is_constant_evaluated 262 if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value) 263 if (!std::is_constant_evaluated()) 264 { 265 constexpr size_t __n = _Nm * sizeof(_Tp); 266 return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0; 267 } 268#endif 269 270 for (size_t __i = 0; __i < _Nm; ++__i) 271 { 272 auto __c = __detail::__synth3way(__a[__i], __b[__i]); 273 if (__c != 0) 274 return __c; 275 } 276 return strong_ordering::equal; 277 } 278#else 279 template<typename _Tp, std::size_t _Nm> 280 _GLIBCXX20_CONSTEXPR 281 inline bool 282 operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 283 { return !(__one == __two); } 284 285 template<typename _Tp, std::size_t _Nm> 286 _GLIBCXX20_CONSTEXPR 287 inline bool 288 operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) 289 { 290 return std::lexicographical_compare(__a.begin(), __a.end(), 291 __b.begin(), __b.end()); 292 } 293 294 template<typename _Tp, std::size_t _Nm> 295 _GLIBCXX20_CONSTEXPR 296 inline bool 297 operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 298 { return __two < __one; } 299 300 template<typename _Tp, std::size_t _Nm> 301 _GLIBCXX20_CONSTEXPR 302 inline bool 303 operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 304 { return !(__one > __two); } 305 306 template<typename _Tp, std::size_t _Nm> 307 _GLIBCXX20_CONSTEXPR 308 inline bool 309 operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 310 { return !(__one < __two); } 311#endif // three_way_comparison && concepts 312 313 // Specialized algorithms. 314 template<typename _Tp, std::size_t _Nm> 315 _GLIBCXX20_CONSTEXPR 316 inline 317#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 318 // Constrained free swap overload, see p0185r1 319 typename enable_if< 320 _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value 321 >::type 322#else 323 void 324#endif 325 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) 326 noexcept(noexcept(__one.swap(__two))) 327 { __one.swap(__two); } 328 329#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 330 template<typename _Tp, std::size_t _Nm> 331 typename enable_if< 332 !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type 333 swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete; 334#endif 335 336 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 337 constexpr _Tp& 338 get(array<_Tp, _Nm>& __arr) noexcept 339 { 340 static_assert(_Int < _Nm, "array index is within bounds"); 341 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 342 _S_ref(__arr._M_elems, _Int); 343 } 344 345 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 346 constexpr _Tp&& 347 get(array<_Tp, _Nm>&& __arr) noexcept 348 { 349 static_assert(_Int < _Nm, "array index is within bounds"); 350 return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); 351 } 352 353 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 354 constexpr const _Tp& 355 get(const array<_Tp, _Nm>& __arr) noexcept 356 { 357 static_assert(_Int < _Nm, "array index is within bounds"); 358 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 359 _S_ref(__arr._M_elems, _Int); 360 } 361 362 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 363 constexpr const _Tp&& 364 get(const array<_Tp, _Nm>&& __arr) noexcept 365 { 366 static_assert(_Int < _Nm, "array index is within bounds"); 367 return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); 368 } 369 370#if __cplusplus > 201703L 371#define __cpp_lib_to_array 201907L 372 373 template<bool _Move = false, typename _Tp, size_t... _Idx> 374 constexpr array<remove_cv_t<_Tp>, sizeof...(_Idx)> 375 __to_array(_Tp (&__a)[sizeof...(_Idx)], index_sequence<_Idx...>) 376 { 377 if constexpr (_Move) 378 return {{std::move(__a[_Idx])...}}; 379 else 380 return {{__a[_Idx]...}}; 381 } 382 383 template<typename _Tp, size_t _Nm> 384 constexpr array<remove_cv_t<_Tp>, _Nm> 385 to_array(_Tp (&__a)[_Nm]) 386 noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) 387 { 388 static_assert(!is_array_v<_Tp>); 389 static_assert(is_constructible_v<_Tp, _Tp&>); 390 if constexpr (is_constructible_v<_Tp, _Tp&>) 391 return _GLIBCXX_STD_C::__to_array(__a, make_index_sequence<_Nm>{}); 392 __builtin_unreachable(); // FIXME: see PR c++/91388 393 } 394 395 template<typename _Tp, size_t _Nm> 396 constexpr array<remove_cv_t<_Tp>, _Nm> 397 to_array(_Tp (&&__a)[_Nm]) 398 noexcept(is_nothrow_move_constructible_v<_Tp>) 399 { 400 static_assert(!is_array_v<_Tp>); 401 static_assert(is_move_constructible_v<_Tp>); 402 if constexpr (is_move_constructible_v<_Tp>) 403 return _GLIBCXX_STD_C::__to_array<1>(__a, make_index_sequence<_Nm>{}); 404 __builtin_unreachable(); // FIXME: see PR c++/91388 405 } 406#endif // C++20 407 408_GLIBCXX_END_NAMESPACE_CONTAINER 409} // namespace std 410 411namespace std _GLIBCXX_VISIBILITY(default) 412{ 413_GLIBCXX_BEGIN_NAMESPACE_VERSION 414 415 // Tuple interface to class template array. 416 417 /// tuple_size 418 template<typename _Tp> 419 struct tuple_size; 420 421 /// Partial specialization for std::array 422 template<typename _Tp, std::size_t _Nm> 423 struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>> 424 : public integral_constant<std::size_t, _Nm> { }; 425 426 /// tuple_element 427 template<std::size_t _Int, typename _Tp> 428 struct tuple_element; 429 430 /// Partial specialization for std::array 431 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 432 struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>> 433 { 434 static_assert(_Int < _Nm, "index is out of bounds"); 435 typedef _Tp type; 436 }; 437 438 template<typename _Tp, std::size_t _Nm> 439 struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type 440 { }; 441 442_GLIBCXX_END_NAMESPACE_VERSION 443} // namespace std 444 445#ifdef _GLIBCXX_DEBUG 446# include <debug/array> 447#endif 448 449#endif // C++11 450 451#endif // _GLIBCXX_ARRAY 452