1// <array> -*- C++ -*-
2
3// Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24// <http://www.gnu.org/licenses/>.
25
26/** @file include/array
27 *  This is a Standard C++ Library header.
28 */
29
30#ifndef _GLIBCXX_ARRAY
31#define _GLIBCXX_ARRAY 1
32
33#pragma GCC system_header
34
35#ifndef __GXX_EXPERIMENTAL_CXX0X__
36# include <bits/c++0x_warning.h>
37#else
38
39#include <stdexcept>
40#include <bits/stl_algobase.h>
41#include <bits/range_access.h>
42
43namespace std _GLIBCXX_VISIBILITY(default)
44{
45_GLIBCXX_BEGIN_NAMESPACE_VERSION
46
47  /**
48   *  @brief A standard container for storing a fixed size sequence of elements.
49   *
50   *  @ingroup sequences
51   *
52   *  Meets the requirements of a <a href="tables.html#65">container</a>, a
53   *  <a href="tables.html#66">reversible container</a>, and a
54   *  <a href="tables.html#67">sequence</a>.
55   *
56   *  Sets support random access iterators.
57   *
58   *  @param  Tp  Type of element. Required to be a complete type.
59   *  @param  N  Number of elements.
60  */
61  template<typename _Tp, std::size_t _Nm>
62    struct array
63    {
64      typedef _Tp 	    			      value_type;
65      typedef value_type*			      pointer;
66      typedef const value_type*                       const_pointer;
67      typedef value_type&                   	      reference;
68      typedef const value_type&             	      const_reference;
69      typedef value_type*          		      iterator;
70      typedef const value_type*			      const_iterator;
71      typedef std::size_t                    	      size_type;
72      typedef std::ptrdiff_t                   	      difference_type;
73      typedef std::reverse_iterator<iterator>	      reverse_iterator;
74      typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
75
76      // Support for zero-sized arrays mandatory.
77      value_type _M_instance[_Nm ? _Nm : 1];
78
79      // No explicit construct/copy/destroy for aggregate type.
80
81      // DR 776.
82      void
83      fill(const value_type& __u)
84      { std::fill_n(begin(), size(), __u); }
85
86      void
87      swap(array& __other)
88      noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
89      { std::swap_ranges(begin(), end(), __other.begin()); }
90
91      // Iterators.
92      iterator
93      begin() noexcept
94      { return iterator(data()); }
95
96      const_iterator
97      begin() const noexcept
98      { return const_iterator(data()); }
99
100      iterator
101      end() noexcept
102      { return iterator(data() + _Nm); }
103
104      const_iterator
105      end() const noexcept
106      { return const_iterator(data() + _Nm); }
107
108      reverse_iterator
109      rbegin() noexcept
110      { return reverse_iterator(end()); }
111
112      const_reverse_iterator
113      rbegin() const noexcept
114      { return const_reverse_iterator(end()); }
115
116      reverse_iterator
117      rend() noexcept
118      { return reverse_iterator(begin()); }
119
120      const_reverse_iterator
121      rend() const noexcept
122      { return const_reverse_iterator(begin()); }
123
124      const_iterator
125      cbegin() const noexcept
126      { return const_iterator(std::__addressof(_M_instance[0])); }
127
128      const_iterator
129      cend() const noexcept
130      { return const_iterator(std::__addressof(_M_instance[_Nm])); }
131
132      const_reverse_iterator
133      crbegin() const noexcept
134      { return const_reverse_iterator(end()); }
135
136      const_reverse_iterator
137      crend() const noexcept
138      { return const_reverse_iterator(begin()); }
139
140      // Capacity.
141      constexpr size_type
142      size() const noexcept { return _Nm; }
143
144      constexpr size_type
145      max_size() const noexcept { return _Nm; }
146
147      constexpr bool
148      empty() const noexcept { return size() == 0; }
149
150      // Element access.
151      reference
152      operator[](size_type __n)
153      { return _M_instance[__n]; }
154
155      constexpr const_reference
156      operator[](size_type __n) const noexcept
157      { return _M_instance[__n]; }
158
159      reference
160      at(size_type __n)
161      {
162	if (__n >= _Nm)
163	  std::__throw_out_of_range(__N("array::at"));
164	return _M_instance[__n];
165      }
166
167      constexpr const_reference
168      at(size_type __n) const
169      {
170	// Result of conditional expression must be an lvalue so use
171	// boolean ? lvalue : (throw-expr, lvalue)
172	return __n < _Nm ? _M_instance[__n]
173	  : (std::__throw_out_of_range(__N("array::at")), _M_instance[0]);
174      }
175
176      reference
177      front()
178      { return *begin(); }
179
180      const_reference
181      front() const
182      { return *begin(); }
183
184      reference
185      back()
186      { return _Nm ? *(end() - 1) : *end(); }
187
188      const_reference
189      back() const
190      { return _Nm ? *(end() - 1) : *end(); }
191
192      pointer
193      data() noexcept
194      { return std::__addressof(_M_instance[0]); }
195
196      const_pointer
197      data() const noexcept
198      { return std::__addressof(_M_instance[0]); }
199    };
200
201  // Array comparisons.
202  template<typename _Tp, std::size_t _Nm>
203    inline bool
204    operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
205    { return std::equal(__one.begin(), __one.end(), __two.begin()); }
206
207  template<typename _Tp, std::size_t _Nm>
208    inline bool
209    operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
210    { return !(__one == __two); }
211
212  template<typename _Tp, std::size_t _Nm>
213    inline bool
214    operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
215    {
216      return std::lexicographical_compare(__a.begin(), __a.end(),
217					  __b.begin(), __b.end());
218    }
219
220  template<typename _Tp, std::size_t _Nm>
221    inline bool
222    operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
223    { return __two < __one; }
224
225  template<typename _Tp, std::size_t _Nm>
226    inline bool
227    operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
228    { return !(__one > __two); }
229
230  template<typename _Tp, std::size_t _Nm>
231    inline bool
232    operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
233    { return !(__one < __two); }
234
235  // Specialized algorithms.
236  template<typename _Tp, std::size_t _Nm>
237    inline void
238    swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
239    noexcept(noexcept(__one.swap(__two)))
240    { __one.swap(__two); }
241
242  // Tuple interface to class template array.
243
244  /// tuple_size
245  template<typename _Tp>
246    class tuple_size;
247
248  template<typename _Tp, std::size_t _Nm>
249    struct tuple_size<array<_Tp, _Nm>>
250    : public integral_constant<std::size_t, _Nm> { };
251
252  /// tuple_element
253  template<std::size_t _Int, typename _Tp>
254    class tuple_element;
255
256  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
257    struct tuple_element<_Int, array<_Tp, _Nm> >
258    { typedef _Tp type; };
259
260  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
261    constexpr _Tp&
262    get(array<_Tp, _Nm>& __arr) noexcept
263    { return __arr._M_instance[_Int]; }
264
265  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
266    constexpr _Tp&&
267    get(array<_Tp, _Nm>&& __arr) noexcept
268    { return std::move(get<_Int>(__arr)); }
269
270  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
271    constexpr const _Tp&
272    get(const array<_Tp, _Nm>& __arr) noexcept
273    { return __arr._M_instance[_Int]; }
274
275_GLIBCXX_END_NAMESPACE_VERSION
276} // namespace
277
278#endif // __GXX_EXPERIMENTAL_CXX0X__
279
280#endif // _GLIBCXX_ARRAY
281