3 // Copyright (C) 2007-2014 Free Software Foundation, Inc.
 
    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)
 
   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.
 
   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.
 
   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/>.
 
   25 /** @file include/array
 
   26  *  This is a Standard C++ Library header.
 
   29 #ifndef _GLIBCXX_ARRAY
 
   30 #define _GLIBCXX_ARRAY 1
 
   32 #pragma GCC system_header
 
   34 #if __cplusplus < 201103L
 
   35 # include <bits/c++0x_warning.h>
 
   39 #include <bits/stl_algobase.h>
 
   40 #include <bits/range_access.h>
 
   42 namespace std _GLIBCXX_VISIBILITY(default)
 
   44 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   46   template<typename _Tp, std::size_t _Nm>
 
   49       typedef _Tp _Type[_Nm];
 
   52       _S_ref(const _Type& __t, std::size_t __n) noexcept
 
   53       { return const_cast<_Tp&>(__t[__n]); }
 
   56  template<typename _Tp>
 
   57    struct __array_traits<_Tp, 0>
 
   62      _S_ref(const _Type&, std::size_t) noexcept
 
   63      { return *static_cast<_Tp*>(nullptr); }
 
   67    *  @brief A standard container for storing a fixed size sequence of elements.
 
   71    *  Meets the requirements of a <a href="tables.html#65">container</a>, a
 
   72    *  <a href="tables.html#66">reversible container</a>, and a
 
   73    *  <a href="tables.html#67">sequence</a>.
 
   75    *  Sets support random access iterators.
 
   77    *  @tparam  Tp  Type of element. Required to be a complete type.
 
   78    *  @tparam  N  Number of elements.
 
   80   template<typename _Tp, std::size_t _Nm>
 
   83       typedef _Tp                        value_type;
 
   84       typedef value_type*                pointer;
 
   85       typedef const value_type*                       const_pointer;
 
   86       typedef value_type&                            reference;
 
   87       typedef const value_type&                      const_reference;
 
   88       typedef value_type*                        iterator;
 
   89       typedef const value_type*                  const_iterator;
 
   90       typedef std::size_t                            size_type;
 
   91       typedef std::ptrdiff_t                             difference_type;
 
   92       typedef std::reverse_iterator<iterator>        reverse_iterator;
 
   93       typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
 
   95       // Support for zero-sized arrays mandatory.
 
   96       typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
 
   97       typename _AT_Type::_Type                         _M_elems;
 
   99       // No explicit construct/copy/destroy for aggregate type.
 
  103       fill(const value_type& __u)
 
  104       { std::fill_n(begin(), size(), __u); }
 
  108       noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
 
  109       { std::swap_ranges(begin(), end(), __other.begin()); }
 
  114       { return iterator(data()); }
 
  117       begin() const noexcept
 
  118       { return const_iterator(data()); }
 
  122       { return iterator(data() + _Nm); }
 
  126       { return const_iterator(data() + _Nm); }
 
  130       { return reverse_iterator(end()); }
 
  132       const_reverse_iterator 
 
  133       rbegin() const noexcept
 
  134       { return const_reverse_iterator(end()); }
 
  138       { return reverse_iterator(begin()); }
 
  140       const_reverse_iterator 
 
  141       rend() const noexcept
 
  142       { return const_reverse_iterator(begin()); }
 
  145       cbegin() const noexcept
 
  146       { return const_iterator(data()); }
 
  149       cend() const noexcept
 
  150       { return const_iterator(data() + _Nm); }
 
  152       const_reverse_iterator 
 
  153       crbegin() const noexcept
 
  154       { return const_reverse_iterator(end()); }
 
  156       const_reverse_iterator 
 
  157       crend() const noexcept
 
  158       { return const_reverse_iterator(begin()); }
 
  162       size() const noexcept { return _Nm; }
 
  165       max_size() const noexcept { return _Nm; }
 
  168       empty() const noexcept { return size() == 0; }
 
  172       operator[](size_type __n) noexcept
 
  173       { return _AT_Type::_S_ref(_M_elems, __n); }
 
  175       constexpr const_reference
 
  176       operator[](size_type __n) const noexcept
 
  177       { return _AT_Type::_S_ref(_M_elems, __n); }
 
  183      std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
 
  184                        ">= _Nm (which is %zu)"),
 
  186    return _AT_Type::_S_ref(_M_elems, __n);
 
  189       constexpr const_reference
 
  190       at(size_type __n) const
 
  192    // Result of conditional expression must be an lvalue so use
 
  193    // boolean ? lvalue : (throw-expr, lvalue)
 
  194    return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
 
  195      : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
 
  196                           ">= _Nm (which is %zu)"),
 
  198         _AT_Type::_S_ref(_M_elems, 0));
 
  205       constexpr const_reference 
 
  206       front() const noexcept
 
  207       { return _AT_Type::_S_ref(_M_elems, 0); }
 
  211       { return _Nm ? *(end() - 1) : *end(); }
 
  213       constexpr const_reference 
 
  214       back() const noexcept
 
  216    return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) 
 
  217               : _AT_Type::_S_ref(_M_elems, 0);
 
  222       { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
 
  225       data() const noexcept
 
  226       { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
 
  229   // Array comparisons.
 
  230   template<typename _Tp, std::size_t _Nm>
 
  232     operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
 
  233     { return std::equal(__one.begin(), __one.end(), __two.begin()); }
 
  235   template<typename _Tp, std::size_t _Nm>
 
  237     operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
 
  238     { return !(__one == __two); }
 
  240   template<typename _Tp, std::size_t _Nm>
 
  242     operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
 
  244       return std::lexicographical_compare(__a.begin(), __a.end(),
 
  245                      __b.begin(), __b.end()); 
 
  248   template<typename _Tp, std::size_t _Nm>
 
  250     operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
 
  251     { return __two < __one; }
 
  253   template<typename _Tp, std::size_t _Nm>
 
  255     operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
 
  256     { return !(__one > __two); }
 
  258   template<typename _Tp, std::size_t _Nm>
 
  260     operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
 
  261     { return !(__one < __two); }
 
  263   // Specialized algorithms.
 
  264   template<typename _Tp, std::size_t _Nm>
 
  266     swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
 
  267     noexcept(noexcept(__one.swap(__two)))
 
  268     { __one.swap(__two); }
 
  270   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
 
  272     get(array<_Tp, _Nm>& __arr) noexcept
 
  274       static_assert(_Int < _Nm, "index is out of bounds");
 
  275       return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
 
  276    _S_ref(__arr._M_elems, _Int);
 
  279   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
 
  281     get(array<_Tp, _Nm>&& __arr) noexcept
 
  283       static_assert(_Int < _Nm, "index is out of bounds");
 
  284       return std::move(get<_Int>(__arr));
 
  287   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
 
  289     get(const array<_Tp, _Nm>& __arr) noexcept
 
  291       static_assert(_Int < _Nm, "index is out of bounds");
 
  292       return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
 
  293    _S_ref(__arr._M_elems, _Int);
 
  296 _GLIBCXX_END_NAMESPACE_CONTAINER
 
  299 namespace std _GLIBCXX_VISIBILITY(default)
 
  301 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
  303   // Tuple interface to class template array.
 
  306   template<typename _Tp> 
 
  309   template<typename _Tp, std::size_t _Nm>
 
  310     struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>>
 
  311     : public integral_constant<std::size_t, _Nm> { };
 
  314   template<std::size_t _Int, typename _Tp>
 
  317   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
 
  318     struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>>
 
  320       static_assert(_Int < _Nm, "index is out of bounds");
 
  324 _GLIBCXX_END_NAMESPACE_VERSION
 
  327 #ifdef _GLIBCXX_DEBUG
 
  328 # include <debug/array>
 
  331 #ifdef _GLIBCXX_PROFILE
 
  332 # include <profile/array>
 
  337 #endif // _GLIBCXX_ARRAY