1// Debugging array implementation -*- C++ -*-
2
3// Copyright (C) 2012-2016 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 debug/array
26 *  This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_DEBUG_ARRAY
30#define _GLIBCXX_DEBUG_ARRAY 1
31
32#pragma GCC system_header
33
34#include <array>
35
36#include <debug/formatter.h>
37#include <debug/macros.h>
38
39namespace std _GLIBCXX_VISIBILITY(default)
40{
41namespace __debug
42{
43  template<typename _Tp, std::size_t _Nm>
44    struct array
45    {
46      typedef _Tp 	    			      value_type;
47      typedef value_type*			      pointer;
48      typedef const value_type*                       const_pointer;
49      typedef value_type&                   	      reference;
50      typedef const value_type&             	      const_reference;
51      typedef value_type*                             iterator;
52      typedef const value_type*                       const_iterator;
53      typedef std::size_t                    	      size_type;
54      typedef std::ptrdiff_t                   	      difference_type;
55      typedef std::reverse_iterator<iterator>	      reverse_iterator;
56      typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
57
58      // Support for zero-sized arrays mandatory.
59      typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
60      typename _AT_Type::_Type                         _M_elems;
61
62      template<std::size_t _Size>
63	struct _Array_check_subscript
64 	{
65	  std::size_t size() { return _Size; }
66
67	  _Array_check_subscript(std::size_t __index)
68	  { __glibcxx_check_subscript(__index); }
69        };
70
71      template<std::size_t _Size>
72	struct _Array_check_nonempty
73 	{
74	  bool empty() { return _Size == 0; }
75
76	  _Array_check_nonempty()
77	  { __glibcxx_check_nonempty(); }
78        };
79
80      // No explicit construct/copy/destroy for aggregate type.
81
82      // DR 776.
83      void
84      fill(const value_type& __u)
85      { std::fill_n(begin(), size(), __u); }
86
87      void
88      swap(array& __other)
89      noexcept(__is_nothrow_swappable<_Tp>::value)
90      { std::swap_ranges(begin(), end(), __other.begin()); }
91
92      // Iterators.
93      iterator
94      begin() noexcept
95      { return iterator(data()); }
96
97      const_iterator
98      begin() const noexcept
99      { return const_iterator(data()); }
100
101      iterator
102      end() noexcept
103      { return iterator(data() + _Nm); }
104
105      const_iterator
106      end() const noexcept
107      { return const_iterator(data() + _Nm); }
108
109      reverse_iterator
110      rbegin() noexcept
111      { return reverse_iterator(end()); }
112
113      const_reverse_iterator
114      rbegin() const noexcept
115      { return const_reverse_iterator(end()); }
116
117      reverse_iterator
118      rend() noexcept
119      { return reverse_iterator(begin()); }
120
121      const_reverse_iterator
122      rend() const noexcept
123      { return const_reverse_iterator(begin()); }
124
125      const_iterator
126      cbegin() const noexcept
127      { return const_iterator(data()); }
128
129      const_iterator
130      cend() const noexcept
131      { return const_iterator(data() + _Nm); }
132
133      const_reverse_iterator
134      crbegin() const noexcept
135      { return const_reverse_iterator(end()); }
136
137      const_reverse_iterator
138      crend() const noexcept
139      { return const_reverse_iterator(begin()); }
140
141      // Capacity.
142      constexpr size_type
143      size() const noexcept { return _Nm; }
144
145      constexpr size_type
146      max_size() const noexcept { return _Nm; }
147
148      constexpr bool
149      empty() const noexcept { return size() == 0; }
150
151      // Element access.
152      reference
153      operator[](size_type __n) noexcept
154      {
155	__glibcxx_check_subscript(__n);
156	return _AT_Type::_S_ref(_M_elems, __n);
157      }
158
159      constexpr const_reference
160      operator[](size_type __n) const noexcept
161      {
162	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
163	 : (_GLIBCXX_THROW_OR_ABORT(_Array_check_subscript<_Nm>(__n)),
164	    _AT_Type::_S_ref(_M_elems, 0));
165      }
166
167      reference
168      at(size_type __n)
169      {
170	if (__n >= _Nm)
171	  std::__throw_out_of_range_fmt(__N("array::at: __n "
172				            "(which is %zu) >= _Nm "
173					    "(which is %zu)"),
174					__n, _Nm);
175	return _AT_Type::_S_ref(_M_elems, __n);
176      }
177
178      constexpr const_reference
179      at(size_type __n) const
180      {
181	// Result of conditional expression must be an lvalue so use
182	// boolean ? lvalue : (throw-expr, lvalue)
183	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
184	  : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
185					       ">= _Nm (which is %zu)"),
186					   __n, _Nm),
187	     _AT_Type::_S_ref(_M_elems, 0));
188      }
189
190      reference
191      front() noexcept
192      {
193	__glibcxx_check_nonempty();
194	return *begin();
195      }
196
197      constexpr const_reference
198      front() const noexcept
199      {
200	return _Nm ? _AT_Type::_S_ref(_M_elems, 0)
201	  : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
202	     _AT_Type::_S_ref(_M_elems, 0));
203      }
204
205      reference
206      back() noexcept
207      {
208	__glibcxx_check_nonempty();
209	return _Nm ? *(end() - 1) : *end();
210      }
211
212      constexpr const_reference
213      back() const noexcept
214      {
215	return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
216	  : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
217	     _AT_Type::_S_ref(_M_elems, 0));
218      }
219
220      pointer
221      data() noexcept
222      { return _AT_Type::_S_ptr(_M_elems); }
223
224      const_pointer
225      data() const noexcept
226      { return _AT_Type::_S_ptr(_M_elems); }
227    };
228
229  // Array comparisons.
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 std::equal(__one.begin(), __one.end(), __two.begin()); }
234
235  template<typename _Tp, std::size_t _Nm>
236    inline bool
237    operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
238    { return !(__one == __two); }
239
240  template<typename _Tp, std::size_t _Nm>
241    inline bool
242    operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
243    {
244      return std::lexicographical_compare(__a.begin(), __a.end(),
245					  __b.begin(), __b.end());
246    }
247
248  template<typename _Tp, std::size_t _Nm>
249    inline bool
250    operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
251    { return __two < __one; }
252
253  template<typename _Tp, std::size_t _Nm>
254    inline bool
255    operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
256    { return !(__one > __two); }
257
258  template<typename _Tp, std::size_t _Nm>
259    inline bool
260    operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
261    { return !(__one < __two); }
262
263  // Specialized algorithms.
264  template<typename _Tp, std::size_t _Nm>
265    inline void
266    swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
267    noexcept(noexcept(__one.swap(__two)))
268    { __one.swap(__two); }
269
270  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
271    constexpr _Tp&
272    get(array<_Tp, _Nm>& __arr) noexcept
273    {
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);
277    }
278
279  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
280    constexpr _Tp&&
281    get(array<_Tp, _Nm>&& __arr) noexcept
282    {
283      static_assert(_Int < _Nm, "index is out of bounds");
284      return std::move(__debug::get<_Int>(__arr));
285    }
286
287  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
288    constexpr const _Tp&
289    get(const array<_Tp, _Nm>& __arr) noexcept
290    {
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);
294    }
295} // namespace __debug
296
297_GLIBCXX_BEGIN_NAMESPACE_VERSION
298  // Tuple interface to class template array.
299
300  /// tuple_size
301  template<typename _Tp, std::size_t _Nm>
302    struct tuple_size<std::__debug::array<_Tp, _Nm>>
303    : public integral_constant<std::size_t, _Nm> { };
304
305  /// tuple_element
306  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
307    struct tuple_element<_Int, std::__debug::array<_Tp, _Nm>>
308    {
309      static_assert(_Int < _Nm, "index is out of bounds");
310      typedef _Tp type;
311    };
312
313  template<typename _Tp, std::size_t _Nm>
314    struct __is_tuple_like_impl<std::__debug::array<_Tp, _Nm>> : true_type
315    { };
316
317_GLIBCXX_END_NAMESPACE_VERSION
318} // namespace std
319
320#endif // _GLIBCXX_DEBUG_ARRAY
321