14fee23f9Smrg// <array> -*- C++ -*- 24fee23f9Smrg 3b1e83836Smrg// Copyright (C) 2007-2022 Free Software Foundation, Inc. 44fee23f9Smrg// 54fee23f9Smrg// This file is part of the GNU ISO C++ Library. This library is free 64fee23f9Smrg// software; you can redistribute it and/or modify it under the 74fee23f9Smrg// terms of the GNU General Public License as published by the 84fee23f9Smrg// Free Software Foundation; either version 3, or (at your option) 94fee23f9Smrg// any later version. 104fee23f9Smrg 114fee23f9Smrg// This library is distributed in the hope that it will be useful, 124fee23f9Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 134fee23f9Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144fee23f9Smrg// GNU General Public License for more details. 154fee23f9Smrg 164fee23f9Smrg// Under Section 7 of GPL version 3, you are granted additional 174fee23f9Smrg// permissions described in the GCC Runtime Library Exception, version 184fee23f9Smrg// 3.1, as published by the Free Software Foundation. 194fee23f9Smrg 204fee23f9Smrg// You should have received a copy of the GNU General Public License and 214fee23f9Smrg// a copy of the GCC Runtime Library Exception along with this program; 224fee23f9Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 234fee23f9Smrg// <http://www.gnu.org/licenses/>. 244fee23f9Smrg 254fee23f9Smrg/** @file include/array 264fee23f9Smrg * This is a Standard C++ Library header. 274fee23f9Smrg */ 284fee23f9Smrg 294fee23f9Smrg#ifndef _GLIBCXX_ARRAY 304fee23f9Smrg#define _GLIBCXX_ARRAY 1 314fee23f9Smrg 324fee23f9Smrg#pragma GCC system_header 334fee23f9Smrg 3448fb7bfaSmrg#if __cplusplus < 201103L 354fee23f9Smrg# include <bits/c++0x_warning.h> 364fee23f9Smrg#else 374fee23f9Smrg 38b1e83836Smrg#include <compare> 39b1e83836Smrg#include <initializer_list> 40b1e83836Smrg 41b1e83836Smrg#include <type_traits> 42fb8a8121Smrg#include <bits/functexcept.h> 434fee23f9Smrg#include <bits/stl_algobase.h> 44b1e83836Smrg#include <bits/range_access.h> // std::begin, std::end etc. 45b1e83836Smrg#include <bits/utility.h> // std::index_sequence, std::tuple_size 46b1e83836Smrg#include <debug/assertions.h> 474fee23f9Smrg 4848fb7bfaSmrgnamespace std _GLIBCXX_VISIBILITY(default) 4948fb7bfaSmrg{ 50b1e83836Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 5148fb7bfaSmrg 5248fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 5348fb7bfaSmrg struct __array_traits 5448fb7bfaSmrg { 5548fb7bfaSmrg typedef _Tp _Type[_Nm]; 56b17d1066Smrg typedef __is_swappable<_Tp> _Is_swappable; 57b17d1066Smrg typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable; 5848fb7bfaSmrg 5948fb7bfaSmrg static constexpr _Tp& 6048fb7bfaSmrg _S_ref(const _Type& __t, std::size_t __n) noexcept 6148fb7bfaSmrg { return const_cast<_Tp&>(__t[__n]); } 624d5abbe8Smrg 634d5abbe8Smrg static constexpr _Tp* 644d5abbe8Smrg _S_ptr(const _Type& __t) noexcept 654d5abbe8Smrg { return const_cast<_Tp*>(__t); } 6648fb7bfaSmrg }; 6748fb7bfaSmrg 6848fb7bfaSmrg template<typename _Tp> 6948fb7bfaSmrg struct __array_traits<_Tp, 0> 7048fb7bfaSmrg { 7148fb7bfaSmrg struct _Type { }; 72b17d1066Smrg typedef true_type _Is_swappable; 73b17d1066Smrg typedef true_type _Is_nothrow_swappable; 7448fb7bfaSmrg 7548fb7bfaSmrg static constexpr _Tp& 7648fb7bfaSmrg _S_ref(const _Type&, std::size_t) noexcept 7748fb7bfaSmrg { return *static_cast<_Tp*>(nullptr); } 784d5abbe8Smrg 794d5abbe8Smrg static constexpr _Tp* 804d5abbe8Smrg _S_ptr(const _Type&) noexcept 814d5abbe8Smrg { return nullptr; } 8248fb7bfaSmrg }; 8348fb7bfaSmrg 8448fb7bfaSmrg /** 8548fb7bfaSmrg * @brief A standard container for storing a fixed size sequence of elements. 8648fb7bfaSmrg * 8748fb7bfaSmrg * @ingroup sequences 8848fb7bfaSmrg * 8948fb7bfaSmrg * Meets the requirements of a <a href="tables.html#65">container</a>, a 9048fb7bfaSmrg * <a href="tables.html#66">reversible container</a>, and a 9148fb7bfaSmrg * <a href="tables.html#67">sequence</a>. 9248fb7bfaSmrg * 9348fb7bfaSmrg * Sets support random access iterators. 9448fb7bfaSmrg * 9548fb7bfaSmrg * @tparam Tp Type of element. Required to be a complete type. 96fb8a8121Smrg * @tparam Nm Number of elements. 9748fb7bfaSmrg */ 9848fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 9948fb7bfaSmrg struct array 10048fb7bfaSmrg { 10148fb7bfaSmrg typedef _Tp value_type; 10248fb7bfaSmrg typedef value_type* pointer; 10348fb7bfaSmrg typedef const value_type* const_pointer; 10448fb7bfaSmrg typedef value_type& reference; 10548fb7bfaSmrg typedef const value_type& const_reference; 10648fb7bfaSmrg typedef value_type* iterator; 10748fb7bfaSmrg typedef const value_type* const_iterator; 10848fb7bfaSmrg typedef std::size_t size_type; 10948fb7bfaSmrg typedef std::ptrdiff_t difference_type; 11048fb7bfaSmrg typedef std::reverse_iterator<iterator> reverse_iterator; 11148fb7bfaSmrg typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 11248fb7bfaSmrg 11348fb7bfaSmrg // Support for zero-sized arrays mandatory. 114b1e83836Smrg typedef __array_traits<_Tp, _Nm> _AT_Type; 11548fb7bfaSmrg typename _AT_Type::_Type _M_elems; 11648fb7bfaSmrg 11748fb7bfaSmrg // No explicit construct/copy/destroy for aggregate type. 11848fb7bfaSmrg 11948fb7bfaSmrg // DR 776. 120fb8a8121Smrg _GLIBCXX20_CONSTEXPR void 12148fb7bfaSmrg fill(const value_type& __u) 12248fb7bfaSmrg { std::fill_n(begin(), size(), __u); } 12348fb7bfaSmrg 124fb8a8121Smrg _GLIBCXX20_CONSTEXPR void 12548fb7bfaSmrg swap(array& __other) 126b17d1066Smrg noexcept(_AT_Type::_Is_nothrow_swappable::value) 12748fb7bfaSmrg { std::swap_ranges(begin(), end(), __other.begin()); } 12848fb7bfaSmrg 12948fb7bfaSmrg // Iterators. 130b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 131b17d1066Smrg _GLIBCXX17_CONSTEXPR iterator 13248fb7bfaSmrg begin() noexcept 13348fb7bfaSmrg { return iterator(data()); } 13448fb7bfaSmrg 135b1e83836Smrg [[__nodiscard__]] 136b17d1066Smrg _GLIBCXX17_CONSTEXPR const_iterator 13748fb7bfaSmrg begin() const noexcept 13848fb7bfaSmrg { return const_iterator(data()); } 13948fb7bfaSmrg 140b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 141b17d1066Smrg _GLIBCXX17_CONSTEXPR iterator 14248fb7bfaSmrg end() noexcept 14348fb7bfaSmrg { return iterator(data() + _Nm); } 14448fb7bfaSmrg 145b1e83836Smrg [[__nodiscard__]] 146b17d1066Smrg _GLIBCXX17_CONSTEXPR const_iterator 14748fb7bfaSmrg end() const noexcept 14848fb7bfaSmrg { return const_iterator(data() + _Nm); } 14948fb7bfaSmrg 150b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 151b17d1066Smrg _GLIBCXX17_CONSTEXPR reverse_iterator 15248fb7bfaSmrg rbegin() noexcept 15348fb7bfaSmrg { return reverse_iterator(end()); } 15448fb7bfaSmrg 155b1e83836Smrg [[__nodiscard__]] 156b17d1066Smrg _GLIBCXX17_CONSTEXPR const_reverse_iterator 15748fb7bfaSmrg rbegin() const noexcept 15848fb7bfaSmrg { return const_reverse_iterator(end()); } 15948fb7bfaSmrg 160b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 161b17d1066Smrg _GLIBCXX17_CONSTEXPR reverse_iterator 16248fb7bfaSmrg rend() noexcept 16348fb7bfaSmrg { return reverse_iterator(begin()); } 16448fb7bfaSmrg 165b1e83836Smrg [[__nodiscard__]] 166b17d1066Smrg _GLIBCXX17_CONSTEXPR const_reverse_iterator 16748fb7bfaSmrg rend() const noexcept 16848fb7bfaSmrg { return const_reverse_iterator(begin()); } 16948fb7bfaSmrg 170b1e83836Smrg [[__nodiscard__]] 171b17d1066Smrg _GLIBCXX17_CONSTEXPR const_iterator 17248fb7bfaSmrg cbegin() const noexcept 17348fb7bfaSmrg { return const_iterator(data()); } 17448fb7bfaSmrg 175b1e83836Smrg [[__nodiscard__]] 176b17d1066Smrg _GLIBCXX17_CONSTEXPR const_iterator 17748fb7bfaSmrg cend() const noexcept 17848fb7bfaSmrg { return const_iterator(data() + _Nm); } 17948fb7bfaSmrg 180b1e83836Smrg [[__nodiscard__]] 181b17d1066Smrg _GLIBCXX17_CONSTEXPR const_reverse_iterator 18248fb7bfaSmrg crbegin() const noexcept 18348fb7bfaSmrg { return const_reverse_iterator(end()); } 18448fb7bfaSmrg 185b1e83836Smrg [[__nodiscard__]] 186b17d1066Smrg _GLIBCXX17_CONSTEXPR const_reverse_iterator 18748fb7bfaSmrg crend() const noexcept 18848fb7bfaSmrg { return const_reverse_iterator(begin()); } 18948fb7bfaSmrg 19048fb7bfaSmrg // Capacity. 191b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 19248fb7bfaSmrg constexpr size_type 19348fb7bfaSmrg size() const noexcept { return _Nm; } 19448fb7bfaSmrg 195b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 19648fb7bfaSmrg constexpr size_type 19748fb7bfaSmrg max_size() const noexcept { return _Nm; } 19848fb7bfaSmrg 199b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 200b1e83836Smrg constexpr bool 20148fb7bfaSmrg empty() const noexcept { return size() == 0; } 20248fb7bfaSmrg 20348fb7bfaSmrg // Element access. 204b1e83836Smrg [[__nodiscard__]] 205b17d1066Smrg _GLIBCXX17_CONSTEXPR reference 2064d5abbe8Smrg operator[](size_type __n) noexcept 207b1e83836Smrg { 208b1e83836Smrg __glibcxx_requires_subscript(__n); 209b1e83836Smrg return _AT_Type::_S_ref(_M_elems, __n); 210b1e83836Smrg } 21148fb7bfaSmrg 212b1e83836Smrg [[__nodiscard__]] 21348fb7bfaSmrg constexpr const_reference 21448fb7bfaSmrg operator[](size_type __n) const noexcept 215b1e83836Smrg { 216b1e83836Smrg#if __cplusplus >= 201402L 217b1e83836Smrg __glibcxx_requires_subscript(__n); 218b1e83836Smrg#endif 219b1e83836Smrg return _AT_Type::_S_ref(_M_elems, __n); 220b1e83836Smrg } 22148fb7bfaSmrg 222b17d1066Smrg _GLIBCXX17_CONSTEXPR reference 22348fb7bfaSmrg at(size_type __n) 22448fb7bfaSmrg { 22548fb7bfaSmrg if (__n >= _Nm) 2264d5abbe8Smrg std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " 2274d5abbe8Smrg ">= _Nm (which is %zu)"), 2284d5abbe8Smrg __n, _Nm); 22948fb7bfaSmrg return _AT_Type::_S_ref(_M_elems, __n); 23048fb7bfaSmrg } 23148fb7bfaSmrg 23248fb7bfaSmrg constexpr const_reference 23348fb7bfaSmrg at(size_type __n) const 23448fb7bfaSmrg { 23548fb7bfaSmrg // Result of conditional expression must be an lvalue so use 23648fb7bfaSmrg // boolean ? lvalue : (throw-expr, lvalue) 23748fb7bfaSmrg return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) 2384d5abbe8Smrg : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " 2394d5abbe8Smrg ">= _Nm (which is %zu)"), 2404d5abbe8Smrg __n, _Nm), 24148fb7bfaSmrg _AT_Type::_S_ref(_M_elems, 0)); 24248fb7bfaSmrg } 24348fb7bfaSmrg 244b1e83836Smrg [[__nodiscard__]] 245b17d1066Smrg _GLIBCXX17_CONSTEXPR reference 2464d5abbe8Smrg front() noexcept 247b1e83836Smrg { 248b1e83836Smrg __glibcxx_requires_nonempty(); 249b1e83836Smrg return *begin(); 250b1e83836Smrg } 25148fb7bfaSmrg 252b1e83836Smrg [[__nodiscard__]] 25348fb7bfaSmrg constexpr const_reference 2544d5abbe8Smrg front() const noexcept 255b1e83836Smrg { 256b1e83836Smrg#if __cplusplus >= 201402L 257b1e83836Smrg __glibcxx_requires_nonempty(); 258b1e83836Smrg#endif 259b1e83836Smrg return _AT_Type::_S_ref(_M_elems, 0); 260b1e83836Smrg } 26148fb7bfaSmrg 262b1e83836Smrg [[__nodiscard__]] 263b17d1066Smrg _GLIBCXX17_CONSTEXPR reference 2644d5abbe8Smrg back() noexcept 265b1e83836Smrg { 266b1e83836Smrg __glibcxx_requires_nonempty(); 267b1e83836Smrg return _Nm ? *(end() - 1) : *end(); 268b1e83836Smrg } 26948fb7bfaSmrg 270b1e83836Smrg [[__nodiscard__]] 27148fb7bfaSmrg constexpr const_reference 2724d5abbe8Smrg back() const noexcept 27348fb7bfaSmrg { 274b1e83836Smrg#if __cplusplus >= 201402L 275b1e83836Smrg __glibcxx_requires_nonempty(); 276b1e83836Smrg#endif 27748fb7bfaSmrg return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) 27848fb7bfaSmrg : _AT_Type::_S_ref(_M_elems, 0); 27948fb7bfaSmrg } 28048fb7bfaSmrg 281b1e83836Smrg [[__gnu__::__const__, __nodiscard__]] 282b17d1066Smrg _GLIBCXX17_CONSTEXPR pointer 28348fb7bfaSmrg data() noexcept 2844d5abbe8Smrg { return _AT_Type::_S_ptr(_M_elems); } 28548fb7bfaSmrg 286b1e83836Smrg [[__nodiscard__]] 287b17d1066Smrg _GLIBCXX17_CONSTEXPR const_pointer 28848fb7bfaSmrg data() const noexcept 2894d5abbe8Smrg { return _AT_Type::_S_ptr(_M_elems); } 29048fb7bfaSmrg }; 29148fb7bfaSmrg 292b17d1066Smrg#if __cpp_deduction_guides >= 201606 293b17d1066Smrg template<typename _Tp, typename... _Up> 294b17d1066Smrg array(_Tp, _Up...) 295b17d1066Smrg -> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>, 296b17d1066Smrg 1 + sizeof...(_Up)>; 297b17d1066Smrg#endif 298b17d1066Smrg 29948fb7bfaSmrg // Array comparisons. 30048fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 301b1e83836Smrg [[__nodiscard__]] 302fb8a8121Smrg _GLIBCXX20_CONSTEXPR 30348fb7bfaSmrg inline bool 30448fb7bfaSmrg operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 30548fb7bfaSmrg { return std::equal(__one.begin(), __one.end(), __two.begin()); } 30648fb7bfaSmrg 307fb8a8121Smrg#if __cpp_lib_three_way_comparison && __cpp_lib_concepts 308fb8a8121Smrg template<typename _Tp, size_t _Nm> 309b1e83836Smrg [[nodiscard]] 310fb8a8121Smrg constexpr __detail::__synth3way_t<_Tp> 311fb8a8121Smrg operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) 312fb8a8121Smrg { 313fb8a8121Smrg if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value) 314b1e83836Smrg if (!std::__is_constant_evaluated()) 315fb8a8121Smrg { 316fb8a8121Smrg constexpr size_t __n = _Nm * sizeof(_Tp); 317fb8a8121Smrg return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0; 318fb8a8121Smrg } 319fb8a8121Smrg 320fb8a8121Smrg for (size_t __i = 0; __i < _Nm; ++__i) 321fb8a8121Smrg { 322fb8a8121Smrg auto __c = __detail::__synth3way(__a[__i], __b[__i]); 323fb8a8121Smrg if (__c != 0) 324fb8a8121Smrg return __c; 325fb8a8121Smrg } 326fb8a8121Smrg return strong_ordering::equal; 327fb8a8121Smrg } 328fb8a8121Smrg#else 32948fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 330b1e83836Smrg [[__nodiscard__]] 331fb8a8121Smrg _GLIBCXX20_CONSTEXPR 33248fb7bfaSmrg inline bool 33348fb7bfaSmrg operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 33448fb7bfaSmrg { return !(__one == __two); } 33548fb7bfaSmrg 33648fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 337b1e83836Smrg [[__nodiscard__]] 338fb8a8121Smrg _GLIBCXX20_CONSTEXPR 33948fb7bfaSmrg inline bool 34048fb7bfaSmrg operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) 34148fb7bfaSmrg { 34248fb7bfaSmrg return std::lexicographical_compare(__a.begin(), __a.end(), 34348fb7bfaSmrg __b.begin(), __b.end()); 34448fb7bfaSmrg } 34548fb7bfaSmrg 34648fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 347b1e83836Smrg [[__nodiscard__]] 348fb8a8121Smrg _GLIBCXX20_CONSTEXPR 34948fb7bfaSmrg inline bool 35048fb7bfaSmrg operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 35148fb7bfaSmrg { return __two < __one; } 35248fb7bfaSmrg 35348fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 354b1e83836Smrg [[__nodiscard__]] 355fb8a8121Smrg _GLIBCXX20_CONSTEXPR 35648fb7bfaSmrg inline bool 35748fb7bfaSmrg operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 35848fb7bfaSmrg { return !(__one > __two); } 35948fb7bfaSmrg 36048fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 361b1e83836Smrg [[__nodiscard__]] 362fb8a8121Smrg _GLIBCXX20_CONSTEXPR 36348fb7bfaSmrg inline bool 36448fb7bfaSmrg operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 36548fb7bfaSmrg { return !(__one < __two); } 366fb8a8121Smrg#endif // three_way_comparison && concepts 36748fb7bfaSmrg 36848fb7bfaSmrg // Specialized algorithms. 36948fb7bfaSmrg template<typename _Tp, std::size_t _Nm> 370fb8a8121Smrg _GLIBCXX20_CONSTEXPR 371b17d1066Smrg inline 372b17d1066Smrg#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 373b17d1066Smrg // Constrained free swap overload, see p0185r1 374b17d1066Smrg typename enable_if< 375b1e83836Smrg __array_traits<_Tp, _Nm>::_Is_swappable::value 376b17d1066Smrg >::type 377b17d1066Smrg#else 378b17d1066Smrg void 379b17d1066Smrg#endif 38048fb7bfaSmrg swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) 38148fb7bfaSmrg noexcept(noexcept(__one.swap(__two))) 38248fb7bfaSmrg { __one.swap(__two); } 38348fb7bfaSmrg 384b17d1066Smrg#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 385b17d1066Smrg template<typename _Tp, std::size_t _Nm> 386b17d1066Smrg typename enable_if< 387b1e83836Smrg !__array_traits<_Tp, _Nm>::_Is_swappable::value>::type 388b17d1066Smrg swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete; 389b17d1066Smrg#endif 390b17d1066Smrg 39148fb7bfaSmrg template<std::size_t _Int, typename _Tp, std::size_t _Nm> 392b1e83836Smrg [[__nodiscard__]] 39348fb7bfaSmrg constexpr _Tp& 39448fb7bfaSmrg get(array<_Tp, _Nm>& __arr) noexcept 39548fb7bfaSmrg { 396b17d1066Smrg static_assert(_Int < _Nm, "array index is within bounds"); 397b1e83836Smrg return __array_traits<_Tp, _Nm>::_S_ref(__arr._M_elems, _Int); 39848fb7bfaSmrg } 39948fb7bfaSmrg 40048fb7bfaSmrg template<std::size_t _Int, typename _Tp, std::size_t _Nm> 401b1e83836Smrg [[__nodiscard__]] 40248fb7bfaSmrg constexpr _Tp&& 40348fb7bfaSmrg get(array<_Tp, _Nm>&& __arr) noexcept 40448fb7bfaSmrg { 405b17d1066Smrg static_assert(_Int < _Nm, "array index is within bounds"); 406b1e83836Smrg return std::move(std::get<_Int>(__arr)); 40748fb7bfaSmrg } 40848fb7bfaSmrg 40948fb7bfaSmrg template<std::size_t _Int, typename _Tp, std::size_t _Nm> 410b1e83836Smrg [[__nodiscard__]] 41148fb7bfaSmrg constexpr const _Tp& 41248fb7bfaSmrg get(const array<_Tp, _Nm>& __arr) noexcept 41348fb7bfaSmrg { 414b17d1066Smrg static_assert(_Int < _Nm, "array index is within bounds"); 415b1e83836Smrg return __array_traits<_Tp, _Nm>::_S_ref(__arr._M_elems, _Int); 41648fb7bfaSmrg } 41748fb7bfaSmrg 418a3e9eb18Smrg template<std::size_t _Int, typename _Tp, std::size_t _Nm> 419b1e83836Smrg [[__nodiscard__]] 420a3e9eb18Smrg constexpr const _Tp&& 421a3e9eb18Smrg get(const array<_Tp, _Nm>&& __arr) noexcept 422a3e9eb18Smrg { 423a3e9eb18Smrg static_assert(_Int < _Nm, "array index is within bounds"); 424b1e83836Smrg return std::move(std::get<_Int>(__arr)); 425a3e9eb18Smrg } 426a3e9eb18Smrg 427*0a307195Smrg#if __cplusplus >= 202002L && __cpp_generic_lambdas >= 201707L 428fb8a8121Smrg#define __cpp_lib_to_array 201907L 429fb8a8121Smrg template<typename _Tp, size_t _Nm> 430b1e83836Smrg [[nodiscard]] 431fb8a8121Smrg constexpr array<remove_cv_t<_Tp>, _Nm> 432fb8a8121Smrg to_array(_Tp (&__a)[_Nm]) 433fb8a8121Smrg noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) 434fb8a8121Smrg { 435fb8a8121Smrg static_assert(!is_array_v<_Tp>); 436fb8a8121Smrg static_assert(is_constructible_v<_Tp, _Tp&>); 437fb8a8121Smrg if constexpr (is_constructible_v<_Tp, _Tp&>) 438*0a307195Smrg { 439*0a307195Smrg if constexpr (is_trivial_v<_Tp>) 440*0a307195Smrg { 441*0a307195Smrg array<remove_cv_t<_Tp>, _Nm> __arr; 442*0a307195Smrg if (!__is_constant_evaluated() && _Nm != 0) 443*0a307195Smrg __builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a)); 444*0a307195Smrg else 445*0a307195Smrg for (size_t __i = 0; __i < _Nm; ++__i) 446*0a307195Smrg __arr._M_elems[__i] = __a[__i]; 447*0a307195Smrg return __arr; 448*0a307195Smrg } 449*0a307195Smrg else 450*0a307195Smrg return [&__a]<size_t... _Idx>(index_sequence<_Idx...>) { 451*0a307195Smrg return array<remove_cv_t<_Tp>, _Nm>{{ __a[_Idx]... }}; 452*0a307195Smrg }(make_index_sequence<_Nm>{}); 453*0a307195Smrg } 454*0a307195Smrg else 455fb8a8121Smrg __builtin_unreachable(); // FIXME: see PR c++/91388 456fb8a8121Smrg } 457fb8a8121Smrg 458fb8a8121Smrg template<typename _Tp, size_t _Nm> 459b1e83836Smrg [[nodiscard]] 460fb8a8121Smrg constexpr array<remove_cv_t<_Tp>, _Nm> 461fb8a8121Smrg to_array(_Tp (&&__a)[_Nm]) 462fb8a8121Smrg noexcept(is_nothrow_move_constructible_v<_Tp>) 463fb8a8121Smrg { 464fb8a8121Smrg static_assert(!is_array_v<_Tp>); 465fb8a8121Smrg static_assert(is_move_constructible_v<_Tp>); 466fb8a8121Smrg if constexpr (is_move_constructible_v<_Tp>) 467*0a307195Smrg { 468*0a307195Smrg if constexpr (is_trivial_v<_Tp>) 469*0a307195Smrg { 470*0a307195Smrg array<remove_cv_t<_Tp>, _Nm> __arr; 471*0a307195Smrg if (!__is_constant_evaluated() && _Nm != 0) 472*0a307195Smrg __builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a)); 473*0a307195Smrg else 474*0a307195Smrg for (size_t __i = 0; __i < _Nm; ++__i) 475*0a307195Smrg __arr._M_elems[__i] = __a[__i]; 476*0a307195Smrg return __arr; 477*0a307195Smrg } 478*0a307195Smrg else 479*0a307195Smrg return [&__a]<size_t... _Idx>(index_sequence<_Idx...>) { 480*0a307195Smrg return array<remove_cv_t<_Tp>, _Nm>{{ std::move(__a[_Idx])... }}; 481*0a307195Smrg }(make_index_sequence<_Nm>{}); 482*0a307195Smrg } 483*0a307195Smrg else 484fb8a8121Smrg __builtin_unreachable(); // FIXME: see PR c++/91388 485fb8a8121Smrg } 486fb8a8121Smrg#endif // C++20 487fb8a8121Smrg 48848fb7bfaSmrg // Tuple interface to class template array. 48948fb7bfaSmrg 490b1e83836Smrg /// Partial specialization for std::array 491b1e83836Smrg template<typename _Tp, size_t _Nm> 492b1e83836Smrg struct tuple_size<array<_Tp, _Nm>> 493b1e83836Smrg : public integral_constant<size_t, _Nm> { }; 49448fb7bfaSmrg 4954d5abbe8Smrg /// Partial specialization for std::array 496b1e83836Smrg template<size_t _Ind, typename _Tp, size_t _Nm> 497b1e83836Smrg struct tuple_element<_Ind, array<_Tp, _Nm>> 49848fb7bfaSmrg { 499b1e83836Smrg static_assert(_Ind < _Nm, "array index is in range"); 500b1e83836Smrg using type = _Tp; 50148fb7bfaSmrg }; 50248fb7bfaSmrg 503b1e83836Smrg#if __cplusplus >= 201703L 504b1e83836Smrg template<typename _Tp, size_t _Nm> 505b1e83836Smrg inline constexpr size_t tuple_size_v<array<_Tp, _Nm>> = _Nm; 506b1e83836Smrg 507b1e83836Smrg template<typename _Tp, size_t _Nm> 508b1e83836Smrg inline constexpr size_t tuple_size_v<const array<_Tp, _Nm>> = _Nm; 509b1e83836Smrg#endif 510b1e83836Smrg 511b1e83836Smrg template<typename _Tp, size_t _Nm> 512b1e83836Smrg struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type 513f9a78e0eSmrg { }; 514f9a78e0eSmrg 51548fb7bfaSmrg_GLIBCXX_END_NAMESPACE_VERSION 51648fb7bfaSmrg} // namespace std 51748fb7bfaSmrg 51848fb7bfaSmrg#endif // C++11 5194fee23f9Smrg 5204fee23f9Smrg#endif // _GLIBCXX_ARRAY 521