You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
14KB

  1. // <array> -*- C++ -*-
  2. // Copyright (C) 2007-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file include/array
  21. * This is a Standard C++ Library header.
  22. */
  23. #ifndef _GLIBCXX_ARRAY
  24. #define _GLIBCXX_ARRAY 1
  25. #pragma GCC system_header
  26. #if __cplusplus < 201103L
  27. # include <bits/c++0x_warning.h>
  28. #else
  29. #include <utility>
  30. #include <bits/functexcept.h>
  31. #include <bits/stl_algobase.h>
  32. #include <bits/range_access.h>
  33. namespace std _GLIBCXX_VISIBILITY(default)
  34. {
  35. _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  36. template<typename _Tp, std::size_t _Nm>
  37. struct __array_traits
  38. {
  39. typedef _Tp _Type[_Nm];
  40. typedef __is_swappable<_Tp> _Is_swappable;
  41. typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable;
  42. static constexpr _Tp&
  43. _S_ref(const _Type& __t, std::size_t __n) noexcept
  44. { return const_cast<_Tp&>(__t[__n]); }
  45. static constexpr _Tp*
  46. _S_ptr(const _Type& __t) noexcept
  47. { return const_cast<_Tp*>(__t); }
  48. };
  49. template<typename _Tp>
  50. struct __array_traits<_Tp, 0>
  51. {
  52. struct _Type { };
  53. typedef true_type _Is_swappable;
  54. typedef true_type _Is_nothrow_swappable;
  55. static constexpr _Tp&
  56. _S_ref(const _Type&, std::size_t) noexcept
  57. { return *static_cast<_Tp*>(nullptr); }
  58. static constexpr _Tp*
  59. _S_ptr(const _Type&) noexcept
  60. { return nullptr; }
  61. };
  62. /**
  63. * @brief A standard container for storing a fixed size sequence of elements.
  64. *
  65. * @ingroup sequences
  66. *
  67. * Meets the requirements of a <a href="tables.html#65">container</a>, a
  68. * <a href="tables.html#66">reversible container</a>, and a
  69. * <a href="tables.html#67">sequence</a>.
  70. *
  71. * Sets support random access iterators.
  72. *
  73. * @tparam Tp Type of element. Required to be a complete type.
  74. * @tparam Nm Number of elements.
  75. */
  76. template<typename _Tp, std::size_t _Nm>
  77. struct array
  78. {
  79. typedef _Tp value_type;
  80. typedef value_type* pointer;
  81. typedef const value_type* const_pointer;
  82. typedef value_type& reference;
  83. typedef const value_type& const_reference;
  84. typedef value_type* iterator;
  85. typedef const value_type* const_iterator;
  86. typedef std::size_t size_type;
  87. typedef std::ptrdiff_t difference_type;
  88. typedef std::reverse_iterator<iterator> reverse_iterator;
  89. typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  90. // Support for zero-sized arrays mandatory.
  91. typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
  92. typename _AT_Type::_Type _M_elems;
  93. // No explicit construct/copy/destroy for aggregate type.
  94. // DR 776.
  95. _GLIBCXX20_CONSTEXPR void
  96. fill(const value_type& __u)
  97. { std::fill_n(begin(), size(), __u); }
  98. _GLIBCXX20_CONSTEXPR void
  99. swap(array& __other)
  100. noexcept(_AT_Type::_Is_nothrow_swappable::value)
  101. { std::swap_ranges(begin(), end(), __other.begin()); }
  102. // Iterators.
  103. _GLIBCXX17_CONSTEXPR iterator
  104. begin() noexcept
  105. { return iterator(data()); }
  106. _GLIBCXX17_CONSTEXPR const_iterator
  107. begin() const noexcept
  108. { return const_iterator(data()); }
  109. _GLIBCXX17_CONSTEXPR iterator
  110. end() noexcept
  111. { return iterator(data() + _Nm); }
  112. _GLIBCXX17_CONSTEXPR const_iterator
  113. end() const noexcept
  114. { return const_iterator(data() + _Nm); }
  115. _GLIBCXX17_CONSTEXPR reverse_iterator
  116. rbegin() noexcept
  117. { return reverse_iterator(end()); }
  118. _GLIBCXX17_CONSTEXPR const_reverse_iterator
  119. rbegin() const noexcept
  120. { return const_reverse_iterator(end()); }
  121. _GLIBCXX17_CONSTEXPR reverse_iterator
  122. rend() noexcept
  123. { return reverse_iterator(begin()); }
  124. _GLIBCXX17_CONSTEXPR const_reverse_iterator
  125. rend() const noexcept
  126. { return const_reverse_iterator(begin()); }
  127. _GLIBCXX17_CONSTEXPR const_iterator
  128. cbegin() const noexcept
  129. { return const_iterator(data()); }
  130. _GLIBCXX17_CONSTEXPR const_iterator
  131. cend() const noexcept
  132. { return const_iterator(data() + _Nm); }
  133. _GLIBCXX17_CONSTEXPR const_reverse_iterator
  134. crbegin() const noexcept
  135. { return const_reverse_iterator(end()); }
  136. _GLIBCXX17_CONSTEXPR const_reverse_iterator
  137. crend() const noexcept
  138. { return const_reverse_iterator(begin()); }
  139. // Capacity.
  140. constexpr size_type
  141. size() const noexcept { return _Nm; }
  142. constexpr size_type
  143. max_size() const noexcept { return _Nm; }
  144. _GLIBCXX_NODISCARD constexpr bool
  145. empty() const noexcept { return size() == 0; }
  146. // Element access.
  147. _GLIBCXX17_CONSTEXPR reference
  148. operator[](size_type __n) noexcept
  149. { return _AT_Type::_S_ref(_M_elems, __n); }
  150. constexpr const_reference
  151. operator[](size_type __n) const noexcept
  152. { return _AT_Type::_S_ref(_M_elems, __n); }
  153. _GLIBCXX17_CONSTEXPR reference
  154. at(size_type __n)
  155. {
  156. if (__n >= _Nm)
  157. std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
  158. ">= _Nm (which is %zu)"),
  159. __n, _Nm);
  160. return _AT_Type::_S_ref(_M_elems, __n);
  161. }
  162. constexpr const_reference
  163. at(size_type __n) const
  164. {
  165. // Result of conditional expression must be an lvalue so use
  166. // boolean ? lvalue : (throw-expr, lvalue)
  167. return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
  168. : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
  169. ">= _Nm (which is %zu)"),
  170. __n, _Nm),
  171. _AT_Type::_S_ref(_M_elems, 0));
  172. }
  173. _GLIBCXX17_CONSTEXPR reference
  174. front() noexcept
  175. { return *begin(); }
  176. constexpr const_reference
  177. front() const noexcept
  178. { return _AT_Type::_S_ref(_M_elems, 0); }
  179. _GLIBCXX17_CONSTEXPR reference
  180. back() noexcept
  181. { return _Nm ? *(end() - 1) : *end(); }
  182. constexpr const_reference
  183. back() const noexcept
  184. {
  185. return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
  186. : _AT_Type::_S_ref(_M_elems, 0);
  187. }
  188. _GLIBCXX17_CONSTEXPR pointer
  189. data() noexcept
  190. { return _AT_Type::_S_ptr(_M_elems); }
  191. _GLIBCXX17_CONSTEXPR const_pointer
  192. data() const noexcept
  193. { return _AT_Type::_S_ptr(_M_elems); }
  194. };
  195. #if __cpp_deduction_guides >= 201606
  196. template<typename _Tp, typename... _Up>
  197. array(_Tp, _Up...)
  198. -> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
  199. 1 + sizeof...(_Up)>;
  200. #endif
  201. // Array comparisons.
  202. template<typename _Tp, std::size_t _Nm>
  203. _GLIBCXX20_CONSTEXPR
  204. inline bool
  205. operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
  206. { return std::equal(__one.begin(), __one.end(), __two.begin()); }
  207. #if __cpp_lib_three_way_comparison && __cpp_lib_concepts
  208. template<typename _Tp, size_t _Nm>
  209. constexpr __detail::__synth3way_t<_Tp>
  210. operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
  211. {
  212. #ifdef __cpp_lib_is_constant_evaluated
  213. if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value)
  214. if (!std::is_constant_evaluated())
  215. {
  216. constexpr size_t __n = _Nm * sizeof(_Tp);
  217. return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0;
  218. }
  219. #endif
  220. for (size_t __i = 0; __i < _Nm; ++__i)
  221. {
  222. auto __c = __detail::__synth3way(__a[__i], __b[__i]);
  223. if (__c != 0)
  224. return __c;
  225. }
  226. return strong_ordering::equal;
  227. }
  228. #else
  229. template<typename _Tp, std::size_t _Nm>
  230. _GLIBCXX20_CONSTEXPR
  231. inline bool
  232. operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
  233. { return !(__one == __two); }
  234. template<typename _Tp, std::size_t _Nm>
  235. _GLIBCXX20_CONSTEXPR
  236. inline bool
  237. operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
  238. {
  239. return std::lexicographical_compare(__a.begin(), __a.end(),
  240. __b.begin(), __b.end());
  241. }
  242. template<typename _Tp, std::size_t _Nm>
  243. _GLIBCXX20_CONSTEXPR
  244. inline bool
  245. operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
  246. { return __two < __one; }
  247. template<typename _Tp, std::size_t _Nm>
  248. _GLIBCXX20_CONSTEXPR
  249. inline bool
  250. operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
  251. { return !(__one > __two); }
  252. template<typename _Tp, std::size_t _Nm>
  253. _GLIBCXX20_CONSTEXPR
  254. inline bool
  255. operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
  256. { return !(__one < __two); }
  257. #endif // three_way_comparison && concepts
  258. // Specialized algorithms.
  259. template<typename _Tp, std::size_t _Nm>
  260. _GLIBCXX20_CONSTEXPR
  261. inline
  262. #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
  263. // Constrained free swap overload, see p0185r1
  264. typename enable_if<
  265. _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value
  266. >::type
  267. #else
  268. void
  269. #endif
  270. swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
  271. noexcept(noexcept(__one.swap(__two)))
  272. { __one.swap(__two); }
  273. #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
  274. template<typename _Tp, std::size_t _Nm>
  275. typename enable_if<
  276. !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
  277. swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
  278. #endif
  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, "array index is within bounds");
  284. return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
  285. _S_ref(__arr._M_elems, _Int);
  286. }
  287. template<std::size_t _Int, typename _Tp, std::size_t _Nm>
  288. constexpr _Tp&&
  289. get(array<_Tp, _Nm>&& __arr) noexcept
  290. {
  291. static_assert(_Int < _Nm, "array index is within bounds");
  292. return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
  293. }
  294. template<std::size_t _Int, typename _Tp, std::size_t _Nm>
  295. constexpr const _Tp&
  296. get(const array<_Tp, _Nm>& __arr) noexcept
  297. {
  298. static_assert(_Int < _Nm, "array index is within bounds");
  299. return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
  300. _S_ref(__arr._M_elems, _Int);
  301. }
  302. template<std::size_t _Int, typename _Tp, std::size_t _Nm>
  303. constexpr const _Tp&&
  304. get(const array<_Tp, _Nm>&& __arr) noexcept
  305. {
  306. static_assert(_Int < _Nm, "array index is within bounds");
  307. return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
  308. }
  309. #if __cplusplus > 201703L
  310. #define __cpp_lib_to_array 201907L
  311. template<bool _Move = false, typename _Tp, size_t... _Idx>
  312. constexpr array<remove_cv_t<_Tp>, sizeof...(_Idx)>
  313. __to_array(_Tp (&__a)[sizeof...(_Idx)], index_sequence<_Idx...>)
  314. {
  315. if constexpr (_Move)
  316. return {{std::move(__a[_Idx])...}};
  317. else
  318. return {{__a[_Idx]...}};
  319. }
  320. template<typename _Tp, size_t _Nm>
  321. constexpr array<remove_cv_t<_Tp>, _Nm>
  322. to_array(_Tp (&__a)[_Nm])
  323. noexcept(is_nothrow_constructible_v<_Tp, _Tp&>)
  324. {
  325. static_assert(!is_array_v<_Tp>);
  326. static_assert(is_constructible_v<_Tp, _Tp&>);
  327. if constexpr (is_constructible_v<_Tp, _Tp&>)
  328. return _GLIBCXX_STD_C::__to_array(__a, make_index_sequence<_Nm>{});
  329. __builtin_unreachable(); // FIXME: see PR c++/91388
  330. }
  331. template<typename _Tp, size_t _Nm>
  332. constexpr array<remove_cv_t<_Tp>, _Nm>
  333. to_array(_Tp (&&__a)[_Nm])
  334. noexcept(is_nothrow_move_constructible_v<_Tp>)
  335. {
  336. static_assert(!is_array_v<_Tp>);
  337. static_assert(is_move_constructible_v<_Tp>);
  338. if constexpr (is_move_constructible_v<_Tp>)
  339. return _GLIBCXX_STD_C::__to_array<1>(__a, make_index_sequence<_Nm>{});
  340. __builtin_unreachable(); // FIXME: see PR c++/91388
  341. }
  342. #endif // C++20
  343. _GLIBCXX_END_NAMESPACE_CONTAINER
  344. } // namespace std
  345. namespace std _GLIBCXX_VISIBILITY(default)
  346. {
  347. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  348. // Tuple interface to class template array.
  349. /// tuple_size
  350. template<typename _Tp>
  351. struct tuple_size;
  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. /// tuple_element
  357. template<std::size_t _Int, typename _Tp>
  358. struct tuple_element;
  359. /// Partial specialization for std::array
  360. template<std::size_t _Int, typename _Tp, std::size_t _Nm>
  361. struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>>
  362. {
  363. static_assert(_Int < _Nm, "index is out of bounds");
  364. typedef _Tp type;
  365. };
  366. template<typename _Tp, std::size_t _Nm>
  367. struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type
  368. { };
  369. _GLIBCXX_END_NAMESPACE_VERSION
  370. } // namespace std
  371. #ifdef _GLIBCXX_DEBUG
  372. # include <debug/array>
  373. #endif
  374. #endif // C++11
  375. #endif // _GLIBCXX_ARRAY