1// <array> -*- C++ -*- 2 3// Copyright (C) 2007-2018 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 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