libstdc++
debug/array
Go to the documentation of this file.
1 // Debugging array implementation -*- C++ -*-
2 
3 // Copyright (C) 2012-2017 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 
39 namespace std _GLIBCXX_VISIBILITY(default)
40 {
41 namespace __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(_AT_Type::_Is_nothrow_swappable::value)
90  { std::swap_ranges(begin(), end(), __other.begin()); }
91 
92  // Iterators.
93  _GLIBCXX17_CONSTEXPR iterator
94  begin() noexcept
95  { return iterator(data()); }
96 
97  _GLIBCXX17_CONSTEXPR const_iterator
98  begin() const noexcept
99  { return const_iterator(data()); }
100 
101  _GLIBCXX17_CONSTEXPR iterator
102  end() noexcept
103  { return iterator(data() + _Nm); }
104 
105  _GLIBCXX17_CONSTEXPR const_iterator
106  end() const noexcept
107  { return const_iterator(data() + _Nm); }
108 
109  _GLIBCXX17_CONSTEXPR reverse_iterator
110  rbegin() noexcept
111  { return reverse_iterator(end()); }
112 
113  _GLIBCXX17_CONSTEXPR const_reverse_iterator
114  rbegin() const noexcept
115  { return const_reverse_iterator(end()); }
116 
117  _GLIBCXX17_CONSTEXPR reverse_iterator
118  rend() noexcept
119  { return reverse_iterator(begin()); }
120 
121  _GLIBCXX17_CONSTEXPR const_reverse_iterator
122  rend() const noexcept
123  { return const_reverse_iterator(begin()); }
124 
125  _GLIBCXX17_CONSTEXPR const_iterator
126  cbegin() const noexcept
127  { return const_iterator(data()); }
128 
129  _GLIBCXX17_CONSTEXPR const_iterator
130  cend() const noexcept
131  { return const_iterator(data() + _Nm); }
132 
133  _GLIBCXX17_CONSTEXPR const_reverse_iterator
134  crbegin() const noexcept
135  { return const_reverse_iterator(end()); }
136 
137  _GLIBCXX17_CONSTEXPR 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  _GLIBCXX17_CONSTEXPR 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  _GLIBCXX17_CONSTEXPR reference
168  at(size_type __n)
169  {
170  if (__n >= _Nm)
171  std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
172  ">= _Nm (which is %zu)"),
173  __n, _Nm);
174  return _AT_Type::_S_ref(_M_elems, __n);
175  }
176 
177  constexpr const_reference
178  at(size_type __n) const
179  {
180  // Result of conditional expression must be an lvalue so use
181  // boolean ? lvalue : (throw-expr, lvalue)
182  return __n < _Nm ? _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)"),
185  __n, _Nm),
186  _AT_Type::_S_ref(_M_elems, 0));
187  }
188 
189  _GLIBCXX17_CONSTEXPR reference
190  front() noexcept
191  {
192  __glibcxx_check_nonempty();
193  return *begin();
194  }
195 
196  constexpr const_reference
197  front() const noexcept
198  {
199  return _Nm ? _AT_Type::_S_ref(_M_elems, 0)
200  : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
201  _AT_Type::_S_ref(_M_elems, 0));
202  }
203 
204  _GLIBCXX17_CONSTEXPR reference
205  back() noexcept
206  {
207  __glibcxx_check_nonempty();
208  return _Nm ? *(end() - 1) : *end();
209  }
210 
211  constexpr const_reference
212  back() const noexcept
213  {
214  return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
215  : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
216  _AT_Type::_S_ref(_M_elems, 0));
217  }
218 
219  _GLIBCXX17_CONSTEXPR pointer
220  data() noexcept
221  { return _AT_Type::_S_ptr(_M_elems); }
222 
223  _GLIBCXX17_CONSTEXPR const_pointer
224  data() const noexcept
225  { return _AT_Type::_S_ptr(_M_elems); }
226  };
227 
228  // Array comparisons.
229  template<typename _Tp, std::size_t _Nm>
230  inline bool
231  operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
232  { return std::equal(__one.begin(), __one.end(), __two.begin()); }
233 
234  template<typename _Tp, std::size_t _Nm>
235  inline bool
236  operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
237  { return !(__one == __two); }
238 
239  template<typename _Tp, std::size_t _Nm>
240  inline bool
241  operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
242  {
243  return std::lexicographical_compare(__a.begin(), __a.end(),
244  __b.begin(), __b.end());
245  }
246 
247  template<typename _Tp, std::size_t _Nm>
248  inline bool
249  operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
250  { return __two < __one; }
251 
252  template<typename _Tp, std::size_t _Nm>
253  inline bool
254  operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
255  { return !(__one > __two); }
256 
257  template<typename _Tp, std::size_t _Nm>
258  inline bool
259  operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
260  { return !(__one < __two); }
261 
262  // Specialized algorithms.
263 
264 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
265  template<typename _Tp, size_t _Nm>
266  typename enable_if<
267  !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
268  swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
269 #endif
270 
271  template<typename _Tp, std::size_t _Nm>
272  inline void
273  swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
274  noexcept(noexcept(__one.swap(__two)))
275  { __one.swap(__two); }
276 
277  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
278  constexpr _Tp&
279  get(array<_Tp, _Nm>& __arr) noexcept
280  {
281  static_assert(_Int < _Nm, "index is out of bounds");
282  return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
283  _S_ref(__arr._M_elems, _Int);
284  }
285 
286  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
287  constexpr _Tp&&
288  get(array<_Tp, _Nm>&& __arr) noexcept
289  {
290  static_assert(_Int < _Nm, "index is out of bounds");
291  return std::move(__debug::get<_Int>(__arr));
292  }
293 
294  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
295  constexpr const _Tp&
296  get(const array<_Tp, _Nm>& __arr) noexcept
297  {
298  static_assert(_Int < _Nm, "index is out of bounds");
299  return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
300  _S_ref(__arr._M_elems, _Int);
301  }
302 } // namespace __debug
303 
304 _GLIBCXX_BEGIN_NAMESPACE_VERSION
305  // Tuple interface to class template array.
306 
307  /// tuple_size
308  template<typename _Tp, std::size_t _Nm>
309  struct tuple_size<std::__debug::array<_Tp, _Nm>>
310  : public integral_constant<std::size_t, _Nm> { };
311 
312  /// tuple_element
313  template<std::size_t _Int, typename _Tp, std::size_t _Nm>
314  struct tuple_element<_Int, std::__debug::array<_Tp, _Nm>>
315  {
316  static_assert(_Int < _Nm, "index is out of bounds");
317  typedef _Tp type;
318  };
319 
320  template<typename _Tp, std::size_t _Nm>
321  struct __is_tuple_like_impl<std::__debug::array<_Tp, _Nm>> : true_type
322  { };
323 
324 _GLIBCXX_END_NAMESPACE_VERSION
325 } // namespace std
326 
327 #endif // _GLIBCXX_DEBUG_ARRAY