xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/array (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
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