1// <array> -*- C++ -*- 2 3// Copyright (C) 2007-2016 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 52 static constexpr _Tp& 53 _S_ref(const _Type& __t, std::size_t __n) noexcept 54 { return const_cast<_Tp&>(__t[__n]); } 55 56 static constexpr _Tp* 57 _S_ptr(const _Type& __t) noexcept 58 { return const_cast<_Tp*>(__t); } 59 }; 60 61 template<typename _Tp> 62 struct __array_traits<_Tp, 0> 63 { 64 struct _Type { }; 65 66 static constexpr _Tp& 67 _S_ref(const _Type&, std::size_t) noexcept 68 { return *static_cast<_Tp*>(nullptr); } 69 70 static constexpr _Tp* 71 _S_ptr(const _Type&) noexcept 72 { return nullptr; } 73 }; 74 75 /** 76 * @brief A standard container for storing a fixed size sequence of elements. 77 * 78 * @ingroup sequences 79 * 80 * Meets the requirements of a <a href="tables.html#65">container</a>, a 81 * <a href="tables.html#66">reversible container</a>, and a 82 * <a href="tables.html#67">sequence</a>. 83 * 84 * Sets support random access iterators. 85 * 86 * @tparam Tp Type of element. Required to be a complete type. 87 * @tparam N Number of elements. 88 */ 89 template<typename _Tp, std::size_t _Nm> 90 struct array 91 { 92 typedef _Tp value_type; 93 typedef value_type* pointer; 94 typedef const value_type* const_pointer; 95 typedef value_type& reference; 96 typedef const value_type& const_reference; 97 typedef value_type* iterator; 98 typedef const value_type* const_iterator; 99 typedef std::size_t size_type; 100 typedef std::ptrdiff_t difference_type; 101 typedef std::reverse_iterator<iterator> reverse_iterator; 102 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 103 104 // Support for zero-sized arrays mandatory. 105 typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; 106 typename _AT_Type::_Type _M_elems; 107 108 // No explicit construct/copy/destroy for aggregate type. 109 110 // DR 776. 111 void 112 fill(const value_type& __u) 113 { std::fill_n(begin(), size(), __u); } 114 115 void 116 swap(array& __other) 117 noexcept(__is_nothrow_swappable<_Tp>::value) 118 { std::swap_ranges(begin(), end(), __other.begin()); } 119 120 // Iterators. 121 iterator 122 begin() noexcept 123 { return iterator(data()); } 124 125 const_iterator 126 begin() const noexcept 127 { return const_iterator(data()); } 128 129 iterator 130 end() noexcept 131 { return iterator(data() + _Nm); } 132 133 const_iterator 134 end() const noexcept 135 { return const_iterator(data() + _Nm); } 136 137 reverse_iterator 138 rbegin() noexcept 139 { return reverse_iterator(end()); } 140 141 const_reverse_iterator 142 rbegin() const noexcept 143 { return const_reverse_iterator(end()); } 144 145 reverse_iterator 146 rend() noexcept 147 { return reverse_iterator(begin()); } 148 149 const_reverse_iterator 150 rend() const noexcept 151 { return const_reverse_iterator(begin()); } 152 153 const_iterator 154 cbegin() const noexcept 155 { return const_iterator(data()); } 156 157 const_iterator 158 cend() const noexcept 159 { return const_iterator(data() + _Nm); } 160 161 const_reverse_iterator 162 crbegin() const noexcept 163 { return const_reverse_iterator(end()); } 164 165 const_reverse_iterator 166 crend() const noexcept 167 { return const_reverse_iterator(begin()); } 168 169 // Capacity. 170 constexpr size_type 171 size() const noexcept { return _Nm; } 172 173 constexpr size_type 174 max_size() const noexcept { return _Nm; } 175 176 constexpr bool 177 empty() const noexcept { return size() == 0; } 178 179 // Element access. 180 reference 181 operator[](size_type __n) noexcept 182 { return _AT_Type::_S_ref(_M_elems, __n); } 183 184 constexpr const_reference 185 operator[](size_type __n) const noexcept 186 { return _AT_Type::_S_ref(_M_elems, __n); } 187 188 reference 189 at(size_type __n) 190 { 191 if (__n >= _Nm) 192 std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " 193 ">= _Nm (which is %zu)"), 194 __n, _Nm); 195 return _AT_Type::_S_ref(_M_elems, __n); 196 } 197 198 constexpr const_reference 199 at(size_type __n) const 200 { 201 // Result of conditional expression must be an lvalue so use 202 // boolean ? lvalue : (throw-expr, lvalue) 203 return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) 204 : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " 205 ">= _Nm (which is %zu)"), 206 __n, _Nm), 207 _AT_Type::_S_ref(_M_elems, 0)); 208 } 209 210 reference 211 front() noexcept 212 { return *begin(); } 213 214 constexpr const_reference 215 front() const noexcept 216 { return _AT_Type::_S_ref(_M_elems, 0); } 217 218 reference 219 back() noexcept 220 { return _Nm ? *(end() - 1) : *end(); } 221 222 constexpr const_reference 223 back() const noexcept 224 { 225 return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) 226 : _AT_Type::_S_ref(_M_elems, 0); 227 } 228 229 pointer 230 data() noexcept 231 { return _AT_Type::_S_ptr(_M_elems); } 232 233 const_pointer 234 data() const noexcept 235 { return _AT_Type::_S_ptr(_M_elems); } 236 }; 237 238 // Array comparisons. 239 template<typename _Tp, std::size_t _Nm> 240 inline bool 241 operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 242 { return std::equal(__one.begin(), __one.end(), __two.begin()); } 243 244 template<typename _Tp, std::size_t _Nm> 245 inline bool 246 operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 247 { return !(__one == __two); } 248 249 template<typename _Tp, std::size_t _Nm> 250 inline bool 251 operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) 252 { 253 return std::lexicographical_compare(__a.begin(), __a.end(), 254 __b.begin(), __b.end()); 255 } 256 257 template<typename _Tp, std::size_t _Nm> 258 inline bool 259 operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 260 { return __two < __one; } 261 262 template<typename _Tp, std::size_t _Nm> 263 inline bool 264 operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 265 { return !(__one > __two); } 266 267 template<typename _Tp, std::size_t _Nm> 268 inline bool 269 operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 270 { return !(__one < __two); } 271 272 // Specialized algorithms. 273 template<typename _Tp, std::size_t _Nm> 274 inline void 275 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) 276 noexcept(noexcept(__one.swap(__two))) 277 { __one.swap(__two); } 278 279 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 280 constexpr _Tp& 281 get(array<_Tp, _Nm>& __arr) noexcept 282 { 283 static_assert(_Int < _Nm, "index is out of bounds"); 284 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 285 _S_ref(__arr._M_elems, _Int); 286 } 287 288 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 289 constexpr _Tp&& 290 get(array<_Tp, _Nm>&& __arr) noexcept 291 { 292 static_assert(_Int < _Nm, "index is out of bounds"); 293 return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); 294 } 295 296 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 297 constexpr const _Tp& 298 get(const array<_Tp, _Nm>& __arr) noexcept 299 { 300 static_assert(_Int < _Nm, "index is out of bounds"); 301 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 302 _S_ref(__arr._M_elems, _Int); 303 } 304 305_GLIBCXX_END_NAMESPACE_CONTAINER 306} // namespace std 307 308namespace std _GLIBCXX_VISIBILITY(default) 309{ 310_GLIBCXX_BEGIN_NAMESPACE_VERSION 311 312 // Tuple interface to class template array. 313 314 /// tuple_size 315 template<typename _Tp> 316 class tuple_size; 317 318 /// Partial specialization for std::array 319 template<typename _Tp, std::size_t _Nm> 320 struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>> 321 : public integral_constant<std::size_t, _Nm> { }; 322 323 /// tuple_element 324 template<std::size_t _Int, typename _Tp> 325 class tuple_element; 326 327 /// Partial specialization for std::array 328 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 329 struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>> 330 { 331 static_assert(_Int < _Nm, "index is out of bounds"); 332 typedef _Tp type; 333 }; 334 335 template<typename _Tp, std::size_t _Nm> 336 struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type 337 { }; 338 339_GLIBCXX_END_NAMESPACE_VERSION 340} // namespace std 341 342#ifdef _GLIBCXX_DEBUG 343# include <debug/array> 344#endif 345 346#ifdef _GLIBCXX_PROFILE 347# include <profile/array> 348#endif 349 350#endif // C++11 351 352#endif // _GLIBCXX_ARRAY 353