]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/debug/array
re PR libstdc++/51850 (debug mode for std::array and tr1::array)
[thirdparty/gcc.git] / libstdc++-v3 / include / debug / array
CommitLineData
0611ce44
PC
1// Debugging array implementation -*- C++ -*-
2
3// Copyright (C) 2012 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 <debug/safe_sequence.h>
35
36#ifndef _GLIBCXX_THROW_OR_ABORT
37# if __EXCEPTIONS
38# define _GLIBCXX_THROW_OR_ABORT(_Exc) (throw (_Exc))
39# else
40# define _GLIBCXX_THROW_OR_ABORT(_Exc) (__builtin_abort())
41# endif
42#endif
43
44namespace std _GLIBCXX_VISIBILITY(default)
45{
46namespace __debug
47{
48 template<typename _Tp, std::size_t _Nm>
49 struct array
50 {
51 typedef _Tp value_type;
52 typedef value_type* pointer;
53 typedef const value_type* const_pointer;
54 typedef value_type& reference;
55 typedef const value_type& const_reference;
56 typedef value_type* iterator;
57 typedef const value_type* const_iterator;
58 typedef std::size_t size_type;
59 typedef std::ptrdiff_t difference_type;
60 typedef std::reverse_iterator<iterator> reverse_iterator;
61 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
62
63 // Support for zero-sized arrays mandatory.
64 typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
65 typename _AT_Type::_Type _M_elems;
66
67 template<std::size_t _Size>
68 struct _Array_check_subscript
69 {
70 std::size_t size() { return _Size; }
71
72 _Array_check_subscript(std::size_t __index)
73 { __glibcxx_check_subscript(__index); }
74 };
75
76 template<std::size_t _Size>
77 struct _Array_check_nonempty
78 {
79 bool empty() { return _Size == 0; }
80
81 _Array_check_nonempty()
82 { __glibcxx_check_nonempty(); }
83 };
84
85 // No explicit construct/copy/destroy for aggregate type.
86
87 // DR 776.
88 void
89 fill(const value_type& __u)
90 { std::fill_n(begin(), size(), __u); }
91
92 void
93 swap(array& __other)
94 noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
95 { std::swap_ranges(begin(), end(), __other.begin()); }
96
97 // Iterators.
98 iterator
99 begin() noexcept
100 { return iterator(data()); }
101
102 const_iterator
103 begin() const noexcept
104 { return const_iterator(data()); }
105
106 iterator
107 end() noexcept
108 { return iterator(data() + _Nm); }
109
110 const_iterator
111 end() const noexcept
112 { return const_iterator(data() + _Nm); }
113
114 reverse_iterator
115 rbegin() noexcept
116 { return reverse_iterator(end()); }
117
118 const_reverse_iterator
119 rbegin() const noexcept
120 { return const_reverse_iterator(end()); }
121
122 reverse_iterator
123 rend() noexcept
124 { return reverse_iterator(begin()); }
125
126 const_reverse_iterator
127 rend() const noexcept
128 { return const_reverse_iterator(begin()); }
129
130 const_iterator
131 cbegin() const noexcept
132 { return const_iterator(data()); }
133
134 const_iterator
135 cend() const noexcept
136 { return const_iterator(data() + _Nm); }
137
138 const_reverse_iterator
139 crbegin() const noexcept
140 { return const_reverse_iterator(end()); }
141
142 const_reverse_iterator
143 crend() const noexcept
144 { return const_reverse_iterator(begin()); }
145
146 // Capacity.
147 constexpr size_type
148 size() const noexcept { return _Nm; }
149
150 constexpr size_type
151 max_size() const noexcept { return _Nm; }
152
153 constexpr bool
154 empty() const noexcept { return size() == 0; }
155
156 // Element access.
157 reference
158 operator[](size_type __n)
159 {
160 __glibcxx_check_subscript(__n);
161 return _AT_Type::_S_ref(_M_elems, __n);
162 }
163
164 constexpr const_reference
165 operator[](size_type __n) const noexcept
166 {
167 return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
168 : (_GLIBCXX_THROW_OR_ABORT (_Array_check_subscript<_Nm>(__n)),
169 _AT_Type::_S_ref(_M_elems, 0));
170 }
171
172 reference
173 at(size_type __n)
174 {
175 if (__n >= _Nm)
176 std::__throw_out_of_range(__N("array::at"));
177 return _AT_Type::_S_ref(_M_elems, __n);
178 }
179
180 constexpr const_reference
181 at(size_type __n) const
182 {
183 // Result of conditional expression must be an lvalue so use
184 // boolean ? lvalue : (throw-expr, lvalue)
185 return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
186 : (std::__throw_out_of_range(__N("array::at")),
187 _AT_Type::_S_ref(_M_elems, 0));
188 }
189
190 reference
191 front()
192 {
193 __glibcxx_check_nonempty();
194 return *begin();
195 }
196
197 constexpr const_reference
198 front() const
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()
207 {
208 __glibcxx_check_nonempty();
209 return _Nm ? *(end() - 1) : *end();
210 }
211
212 constexpr const_reference
213 back() const
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 std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
223
224 const_pointer
225 data() const noexcept
226 { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
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(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 // Tuple interface to class template array.
298
299 /// tuple_size
300 template<typename _Tp>
301 class tuple_size;
302
303 template<typename _Tp, std::size_t _Nm>
304 struct tuple_size<__debug::array<_Tp, _Nm>>
305 : public integral_constant<std::size_t, _Nm> { };
306
307 /// tuple_element
308 template<std::size_t _Int, typename _Tp>
309 class tuple_element;
310
311 template<std::size_t _Int, typename _Tp, std::size_t _Nm>
312 struct tuple_element<_Int, __debug::array<_Tp, _Nm>>
313 {
314 static_assert(_Int < _Nm, "index is out of bounds");
315 typedef _Tp type;
316 };
317} // namespace std
318
319#undef _GLIBCXX_THROW_OR_ABORT
320
321#endif // _GLIBCXX_DEBUG_ARRAY