libstdc++
|
00001 // Debugging array implementation -*- C++ -*- 00002 00003 // Copyright (C) 2012-2016 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file debug/array 00026 * This is a Standard C++ Library header. 00027 */ 00028 00029 #ifndef _GLIBCXX_DEBUG_ARRAY 00030 #define _GLIBCXX_DEBUG_ARRAY 1 00031 00032 #pragma GCC system_header 00033 00034 #include <array> 00035 00036 #include <debug/formatter.h> 00037 #include <debug/macros.h> 00038 00039 namespace std _GLIBCXX_VISIBILITY(default) 00040 { 00041 namespace __debug 00042 { 00043 template<typename _Tp, std::size_t _Nm> 00044 struct array 00045 { 00046 typedef _Tp value_type; 00047 typedef value_type* pointer; 00048 typedef const value_type* const_pointer; 00049 typedef value_type& reference; 00050 typedef const value_type& const_reference; 00051 typedef value_type* iterator; 00052 typedef const value_type* const_iterator; 00053 typedef std::size_t size_type; 00054 typedef std::ptrdiff_t difference_type; 00055 typedef std::reverse_iterator<iterator> reverse_iterator; 00056 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00057 00058 // Support for zero-sized arrays mandatory. 00059 typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; 00060 typename _AT_Type::_Type _M_elems; 00061 00062 template<std::size_t _Size> 00063 struct _Array_check_subscript 00064 { 00065 std::size_t size() { return _Size; } 00066 00067 _Array_check_subscript(std::size_t __index) 00068 { __glibcxx_check_subscript(__index); } 00069 }; 00070 00071 template<std::size_t _Size> 00072 struct _Array_check_nonempty 00073 { 00074 bool empty() { return _Size == 0; } 00075 00076 _Array_check_nonempty() 00077 { __glibcxx_check_nonempty(); } 00078 }; 00079 00080 // No explicit construct/copy/destroy for aggregate type. 00081 00082 // DR 776. 00083 void 00084 fill(const value_type& __u) 00085 { std::fill_n(begin(), size(), __u); } 00086 00087 void 00088 swap(array& __other) 00089 noexcept(__is_nothrow_swappable<_Tp>::value) 00090 { std::swap_ranges(begin(), end(), __other.begin()); } 00091 00092 // Iterators. 00093 iterator 00094 begin() noexcept 00095 { return iterator(data()); } 00096 00097 const_iterator 00098 begin() const noexcept 00099 { return const_iterator(data()); } 00100 00101 iterator 00102 end() noexcept 00103 { return iterator(data() + _Nm); } 00104 00105 const_iterator 00106 end() const noexcept 00107 { return const_iterator(data() + _Nm); } 00108 00109 reverse_iterator 00110 rbegin() noexcept 00111 { return reverse_iterator(end()); } 00112 00113 const_reverse_iterator 00114 rbegin() const noexcept 00115 { return const_reverse_iterator(end()); } 00116 00117 reverse_iterator 00118 rend() noexcept 00119 { return reverse_iterator(begin()); } 00120 00121 const_reverse_iterator 00122 rend() const noexcept 00123 { return const_reverse_iterator(begin()); } 00124 00125 const_iterator 00126 cbegin() const noexcept 00127 { return const_iterator(data()); } 00128 00129 const_iterator 00130 cend() const noexcept 00131 { return const_iterator(data() + _Nm); } 00132 00133 const_reverse_iterator 00134 crbegin() const noexcept 00135 { return const_reverse_iterator(end()); } 00136 00137 const_reverse_iterator 00138 crend() const noexcept 00139 { return const_reverse_iterator(begin()); } 00140 00141 // Capacity. 00142 constexpr size_type 00143 size() const noexcept { return _Nm; } 00144 00145 constexpr size_type 00146 max_size() const noexcept { return _Nm; } 00147 00148 constexpr bool 00149 empty() const noexcept { return size() == 0; } 00150 00151 // Element access. 00152 reference 00153 operator[](size_type __n) noexcept 00154 { 00155 __glibcxx_check_subscript(__n); 00156 return _AT_Type::_S_ref(_M_elems, __n); 00157 } 00158 00159 constexpr const_reference 00160 operator[](size_type __n) const noexcept 00161 { 00162 return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) 00163 : (_GLIBCXX_THROW_OR_ABORT(_Array_check_subscript<_Nm>(__n)), 00164 _AT_Type::_S_ref(_M_elems, 0)); 00165 } 00166 00167 reference 00168 at(size_type __n) 00169 { 00170 if (__n >= _Nm) 00171 std::__throw_out_of_range_fmt(__N("array::at: __n " 00172 "(which is %zu) >= _Nm " 00173 "(which is %zu)"), 00174 __n, _Nm); 00175 return _AT_Type::_S_ref(_M_elems, __n); 00176 } 00177 00178 constexpr const_reference 00179 at(size_type __n) const 00180 { 00181 // Result of conditional expression must be an lvalue so use 00182 // boolean ? lvalue : (throw-expr, lvalue) 00183 return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) 00184 : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " 00185 ">= _Nm (which is %zu)"), 00186 __n, _Nm), 00187 _AT_Type::_S_ref(_M_elems, 0)); 00188 } 00189 00190 reference 00191 front() noexcept 00192 { 00193 __glibcxx_check_nonempty(); 00194 return *begin(); 00195 } 00196 00197 constexpr const_reference 00198 front() const noexcept 00199 { 00200 return _Nm ? _AT_Type::_S_ref(_M_elems, 0) 00201 : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()), 00202 _AT_Type::_S_ref(_M_elems, 0)); 00203 } 00204 00205 reference 00206 back() noexcept 00207 { 00208 __glibcxx_check_nonempty(); 00209 return _Nm ? *(end() - 1) : *end(); 00210 } 00211 00212 constexpr const_reference 00213 back() const noexcept 00214 { 00215 return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) 00216 : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()), 00217 _AT_Type::_S_ref(_M_elems, 0)); 00218 } 00219 00220 pointer 00221 data() noexcept 00222 { return _AT_Type::_S_ptr(_M_elems); } 00223 00224 const_pointer 00225 data() const noexcept 00226 { return _AT_Type::_S_ptr(_M_elems); } 00227 }; 00228 00229 // Array comparisons. 00230 template<typename _Tp, std::size_t _Nm> 00231 inline bool 00232 operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00233 { return std::equal(__one.begin(), __one.end(), __two.begin()); } 00234 00235 template<typename _Tp, std::size_t _Nm> 00236 inline bool 00237 operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00238 { return !(__one == __two); } 00239 00240 template<typename _Tp, std::size_t _Nm> 00241 inline bool 00242 operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) 00243 { 00244 return std::lexicographical_compare(__a.begin(), __a.end(), 00245 __b.begin(), __b.end()); 00246 } 00247 00248 template<typename _Tp, std::size_t _Nm> 00249 inline bool 00250 operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00251 { return __two < __one; } 00252 00253 template<typename _Tp, std::size_t _Nm> 00254 inline bool 00255 operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00256 { return !(__one > __two); } 00257 00258 template<typename _Tp, std::size_t _Nm> 00259 inline bool 00260 operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00261 { return !(__one < __two); } 00262 00263 // Specialized algorithms. 00264 template<typename _Tp, std::size_t _Nm> 00265 inline void 00266 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) 00267 noexcept(noexcept(__one.swap(__two))) 00268 { __one.swap(__two); } 00269 00270 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00271 constexpr _Tp& 00272 get(array<_Tp, _Nm>& __arr) noexcept 00273 { 00274 static_assert(_Int < _Nm, "index is out of bounds"); 00275 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 00276 _S_ref(__arr._M_elems, _Int); 00277 } 00278 00279 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00280 constexpr _Tp&& 00281 get(array<_Tp, _Nm>&& __arr) noexcept 00282 { 00283 static_assert(_Int < _Nm, "index is out of bounds"); 00284 return std::move(__debug::get<_Int>(__arr)); 00285 } 00286 00287 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00288 constexpr const _Tp& 00289 get(const array<_Tp, _Nm>& __arr) noexcept 00290 { 00291 static_assert(_Int < _Nm, "index is out of bounds"); 00292 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 00293 _S_ref(__arr._M_elems, _Int); 00294 } 00295 } // namespace __debug 00296 00297 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00298 // Tuple interface to class template array. 00299 00300 /// tuple_size 00301 template<typename _Tp, std::size_t _Nm> 00302 struct tuple_size<std::__debug::array<_Tp, _Nm>> 00303 : public integral_constant<std::size_t, _Nm> { }; 00304 00305 /// tuple_element 00306 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00307 struct tuple_element<_Int, std::__debug::array<_Tp, _Nm>> 00308 { 00309 static_assert(_Int < _Nm, "index is out of bounds"); 00310 typedef _Tp type; 00311 }; 00312 00313 template<typename _Tp, std::size_t _Nm> 00314 struct __is_tuple_like_impl<std::__debug::array<_Tp, _Nm>> : true_type 00315 { }; 00316 00317 _GLIBCXX_END_NAMESPACE_VERSION 00318 } // namespace std 00319 00320 #endif // _GLIBCXX_DEBUG_ARRAY