1    	// <array> -*- C++ -*-
2    	
3    	// Copyright (C) 2007-2013 Free Software Foundation, Inc.
4    	//
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)
9    	// any later version.
10   	
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.
15   	
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.
19   	
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/>.
24   	
25   	/** @file include/array
26   	 *  This is a Standard C++ Library header.
27   	 */
28   	
29   	#ifndef _GLIBCXX_ARRAY
30   	#define _GLIBCXX_ARRAY 1
31   	
32   	#pragma GCC system_header
33   	
34   	#if __cplusplus < 201103L
35   	# include <bits/c++0x_warning.h>
36   	#else
37   	
38   	#include <stdexcept>
39   	#include <bits/stl_algobase.h>
40   	#include <bits/range_access.h>
41   	
42   	namespace std _GLIBCXX_VISIBILITY(default)
43   	{
44   	_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
45   	
46   	  template<typename _Tp, std::size_t _Nm>
47   	    struct __array_traits
48   	    {
49   	      typedef _Tp _Type[_Nm];
50   	
51   	      static constexpr _Tp&
52   	      _S_ref(const _Type& __t, std::size_t __n) noexcept
53   	      { return const_cast<_Tp&>(__t[__n]); }
54   	    };
55   	
56   	 template<typename _Tp>
57   	   struct __array_traits<_Tp, 0>
58   	   {
59   	     struct _Type { };
60   	
61   	     static constexpr _Tp&
62   	     _S_ref(const _Type&, std::size_t) noexcept
63   	     { return *static_cast<_Tp*>(nullptr); }
64   	   };
65   	
66   	  /**
67   	   *  @brief A standard container for storing a fixed size sequence of elements.
68   	   *
69   	   *  @ingroup sequences
70   	   *
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>.
74   	   *
75   	   *  Sets support random access iterators.
76   	   *
77   	   *  @tparam  Tp  Type of element. Required to be a complete type.
78   	   *  @tparam  N  Number of elements.
79   	  */
80   	  template<typename _Tp, std::size_t _Nm>
81   	    struct array
82   	    {
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;
94   	
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;
98   	
99   	      // No explicit construct/copy/destroy for aggregate type.
100  	
101  	      // DR 776.
102  	      void
103  	      fill(const value_type& __u)
104  	      { std::fill_n(begin(), size(), __u); }
105  	
106  	      void
107  	      swap(array& __other)
108  	      noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
109  	      { std::swap_ranges(begin(), end(), __other.begin()); }
110  	
111  	      // Iterators.
112  	      iterator
113  	      begin() noexcept
114  	      { return iterator(data()); }
115  	
116  	      const_iterator
117  	      begin() const noexcept
118  	      { return const_iterator(data()); }
119  	
120  	      iterator
121  	      end() noexcept
122  	      { return iterator(data() + _Nm); }
123  	
124  	      const_iterator
125  	      end() const noexcept
126  	      { return const_iterator(data() + _Nm); }
127  	
128  	      reverse_iterator 
129  	      rbegin() noexcept
130  	      { return reverse_iterator(end()); }
131  	
132  	      const_reverse_iterator 
133  	      rbegin() const noexcept
134  	      { return const_reverse_iterator(end()); }
135  	
136  	      reverse_iterator 
137  	      rend() noexcept
138  	      { return reverse_iterator(begin()); }
139  	
140  	      const_reverse_iterator 
141  	      rend() const noexcept
142  	      { return const_reverse_iterator(begin()); }
143  	
144  	      const_iterator
145  	      cbegin() const noexcept
146  	      { return const_iterator(data()); }
147  	
148  	      const_iterator
149  	      cend() const noexcept
150  	      { return const_iterator(data() + _Nm); }
151  	
152  	      const_reverse_iterator 
153  	      crbegin() const noexcept
154  	      { return const_reverse_iterator(end()); }
155  	
156  	      const_reverse_iterator 
157  	      crend() const noexcept
158  	      { return const_reverse_iterator(begin()); }
159  	
160  	      // Capacity.
161  	      constexpr size_type 
162  	      size() const noexcept { return _Nm; }
163  	
164  	      constexpr size_type 
165  	      max_size() const noexcept { return _Nm; }
166  	
167  	      constexpr bool 
168  	      empty() const noexcept { return size() == 0; }
169  	
170  	      // Element access.
171  	      reference
172  	      operator[](size_type __n)
173  	      { return _AT_Type::_S_ref(_M_elems, __n); }
174  	
175  	      constexpr const_reference
176  	      operator[](size_type __n) const noexcept
177  	      { return _AT_Type::_S_ref(_M_elems, __n); }
178  	
179  	      reference
180  	      at(size_type __n)
181  	      {
182  		if (__n >= _Nm)
183  		  std::__throw_out_of_range(__N("array::at"));
184  		return _AT_Type::_S_ref(_M_elems, __n);
185  	      }
186  	
187  	      constexpr const_reference
188  	      at(size_type __n) const
189  	      {
190  		// Result of conditional expression must be an lvalue so use
191  		// boolean ? lvalue : (throw-expr, lvalue)
192  		return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
193  		  : (std::__throw_out_of_range(__N("array::at")),
194  		     _AT_Type::_S_ref(_M_elems, 0));
195  	      }
196  	
197  	      reference 
198  	      front()
199  	      { return *begin(); }
200  	
201  	      constexpr const_reference 
202  	      front() const
203  	      { return _AT_Type::_S_ref(_M_elems, 0); }
204  	
205  	      reference 
206  	      back()
207  	      { return _Nm ? *(end() - 1) : *end(); }
208  	
209  	      constexpr const_reference 
210  	      back() const
211  	      { 
212  		return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) 
213  	 	           : _AT_Type::_S_ref(_M_elems, 0);
214  	      }
215  	
216  	      pointer
217  	      data() noexcept
218  	      { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
219  	
220  	      const_pointer
221  	      data() const noexcept
222  	      { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
223  	    };
224  	
225  	  // Array comparisons.
226  	  template<typename _Tp, std::size_t _Nm>
227  	    inline bool 
228  	    operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
229  	    { return std::equal(__one.begin(), __one.end(), __two.begin()); }
230  	
231  	  template<typename _Tp, std::size_t _Nm>
232  	    inline bool
233  	    operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
234  	    { return !(__one == __two); }
235  	
236  	  template<typename _Tp, std::size_t _Nm>
237  	    inline bool
238  	    operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
239  	    { 
240  	      return std::lexicographical_compare(__a.begin(), __a.end(),
241  						  __b.begin(), __b.end()); 
242  	    }
243  	
244  	  template<typename _Tp, std::size_t _Nm>
245  	    inline bool
246  	    operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
247  	    { return __two < __one; }
248  	
249  	  template<typename _Tp, std::size_t _Nm>
250  	    inline bool
251  	    operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
252  	    { return !(__one > __two); }
253  	
254  	  template<typename _Tp, std::size_t _Nm>
255  	    inline bool
256  	    operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
257  	    { return !(__one < __two); }
258  	
259  	  // Specialized algorithms.
260  	  template<typename _Tp, std::size_t _Nm>
261  	    inline void
262  	    swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
263  	    noexcept(noexcept(__one.swap(__two)))
264  	    { __one.swap(__two); }
265  	
266  	  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
267  	    constexpr _Tp&
268  	    get(array<_Tp, _Nm>& __arr) noexcept
269  	    {
270  	      static_assert(_Int < _Nm, "index is out of bounds");
271  	      return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
272  		_S_ref(__arr._M_elems, _Int);
273  	    }
274  	
275  	  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
276  	    constexpr _Tp&&
277  	    get(array<_Tp, _Nm>&& __arr) noexcept
278  	    {
279  	      static_assert(_Int < _Nm, "index is out of bounds");
280  	      return std::move(get<_Int>(__arr));
281  	    }
282  	
283  	  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
284  	    constexpr const _Tp&
285  	    get(const array<_Tp, _Nm>& __arr) noexcept
286  	    {
287  	      static_assert(_Int < _Nm, "index is out of bounds");
288  	      return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
289  		_S_ref(__arr._M_elems, _Int);
290  	    }
291  	
292  	_GLIBCXX_END_NAMESPACE_CONTAINER
293  	} // namespace std
294  	
295  	namespace std _GLIBCXX_VISIBILITY(default)
296  	{
297  	_GLIBCXX_BEGIN_NAMESPACE_VERSION
298  	
299  	  // Tuple interface to class template array.
300  	
301  	  /// tuple_size
302  	  template<typename _Tp> 
303  	    class tuple_size;
304  	
305  	  template<typename _Tp, std::size_t _Nm>
306  	    struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>>
307  	    : public integral_constant<std::size_t, _Nm> { };
308  	
309  	  /// tuple_element
310  	  template<std::size_t _Int, typename _Tp>
311  	    class tuple_element;
312  	
313  	  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
314  	    struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>>
315  	    {
316  	      static_assert(_Int < _Nm, "index is out of bounds");
317  	      typedef _Tp type;
318  	    };
319  	
320  	_GLIBCXX_END_NAMESPACE_VERSION
321  	} // namespace std
322  	
323  	#ifdef _GLIBCXX_DEBUG
324  	# include <debug/array>
325  	#endif
326  	
327  	#ifdef _GLIBCXX_PROFILE
328  	# include <profile/array>
329  	#endif
330  	
331  	#endif // C++11
332  	
333  	#endif // _GLIBCXX_ARRAY
334