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