libstdc++
|
00001 // Debugging array implementation -*- C++ -*- 00002 00003 // Copyright (C) 2012-2019 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 _GLIBCXX_NODISCARD 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(_AT_Type::_Is_nothrow_swappable::value) 00090 { std::swap_ranges(begin(), end(), __other.begin()); } 00091 00092 // Iterators. 00093 _GLIBCXX17_CONSTEXPR iterator 00094 begin() noexcept 00095 { return iterator(data()); } 00096 00097 _GLIBCXX17_CONSTEXPR const_iterator 00098 begin() const noexcept 00099 { return const_iterator(data()); } 00100 00101 _GLIBCXX17_CONSTEXPR iterator 00102 end() noexcept 00103 { return iterator(data() + _Nm); } 00104 00105 _GLIBCXX17_CONSTEXPR const_iterator 00106 end() const noexcept 00107 { return const_iterator(data() + _Nm); } 00108 00109 _GLIBCXX17_CONSTEXPR reverse_iterator 00110 rbegin() noexcept 00111 { return reverse_iterator(end()); } 00112 00113 _GLIBCXX17_CONSTEXPR const_reverse_iterator 00114 rbegin() const noexcept 00115 { return const_reverse_iterator(end()); } 00116 00117 _GLIBCXX17_CONSTEXPR reverse_iterator 00118 rend() noexcept 00119 { return reverse_iterator(begin()); } 00120 00121 _GLIBCXX17_CONSTEXPR const_reverse_iterator 00122 rend() const noexcept 00123 { return const_reverse_iterator(begin()); } 00124 00125 _GLIBCXX17_CONSTEXPR const_iterator 00126 cbegin() const noexcept 00127 { return const_iterator(data()); } 00128 00129 _GLIBCXX17_CONSTEXPR const_iterator 00130 cend() const noexcept 00131 { return const_iterator(data() + _Nm); } 00132 00133 _GLIBCXX17_CONSTEXPR const_reverse_iterator 00134 crbegin() const noexcept 00135 { return const_reverse_iterator(end()); } 00136 00137 _GLIBCXX17_CONSTEXPR 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 _GLIBCXX_NODISCARD constexpr bool 00149 empty() const noexcept { return size() == 0; } 00150 00151 // Element access. 00152 _GLIBCXX17_CONSTEXPR 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 _GLIBCXX17_CONSTEXPR reference 00168 at(size_type __n) 00169 { 00170 if (__n >= _Nm) 00171 std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " 00172 ">= _Nm (which is %zu)"), 00173 __n, _Nm); 00174 return _AT_Type::_S_ref(_M_elems, __n); 00175 } 00176 00177 constexpr const_reference 00178 at(size_type __n) const 00179 { 00180 // Result of conditional expression must be an lvalue so use 00181 // boolean ? lvalue : (throw-expr, lvalue) 00182 return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) 00183 : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " 00184 ">= _Nm (which is %zu)"), 00185 __n, _Nm), 00186 _AT_Type::_S_ref(_M_elems, 0)); 00187 } 00188 00189 _GLIBCXX17_CONSTEXPR reference 00190 front() noexcept 00191 { 00192 __glibcxx_check_nonempty(); 00193 return *begin(); 00194 } 00195 00196 constexpr const_reference 00197 front() const noexcept 00198 { 00199 return _Nm ? _AT_Type::_S_ref(_M_elems, 0) 00200 : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()), 00201 _AT_Type::_S_ref(_M_elems, 0)); 00202 } 00203 00204 _GLIBCXX17_CONSTEXPR reference 00205 back() noexcept 00206 { 00207 __glibcxx_check_nonempty(); 00208 return _Nm ? *(end() - 1) : *end(); 00209 } 00210 00211 constexpr const_reference 00212 back() const noexcept 00213 { 00214 return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) 00215 : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()), 00216 _AT_Type::_S_ref(_M_elems, 0)); 00217 } 00218 00219 _GLIBCXX17_CONSTEXPR pointer 00220 data() noexcept 00221 { return _AT_Type::_S_ptr(_M_elems); } 00222 00223 _GLIBCXX17_CONSTEXPR const_pointer 00224 data() const noexcept 00225 { return _AT_Type::_S_ptr(_M_elems); } 00226 }; 00227 00228 #if __cpp_deduction_guides >= 201606 00229 template<typename _Tp, typename... _Up> 00230 array(_Tp, _Up...) 00231 -> array<std::enable_if_t<(std::is_same_v<_Tp, _Up> && ...), _Tp>, 00232 1 + sizeof...(_Up)>; 00233 #endif 00234 00235 // Array comparisons. 00236 template<typename _Tp, std::size_t _Nm> 00237 inline bool 00238 operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00239 { return std::equal(__one.begin(), __one.end(), __two.begin()); } 00240 00241 template<typename _Tp, std::size_t _Nm> 00242 inline bool 00243 operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00244 { return !(__one == __two); } 00245 00246 template<typename _Tp, std::size_t _Nm> 00247 inline bool 00248 operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) 00249 { 00250 return std::lexicographical_compare(__a.begin(), __a.end(), 00251 __b.begin(), __b.end()); 00252 } 00253 00254 template<typename _Tp, std::size_t _Nm> 00255 inline bool 00256 operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00257 { return __two < __one; } 00258 00259 template<typename _Tp, std::size_t _Nm> 00260 inline bool 00261 operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00262 { return !(__one > __two); } 00263 00264 template<typename _Tp, std::size_t _Nm> 00265 inline bool 00266 operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) 00267 { return !(__one < __two); } 00268 00269 // Specialized algorithms. 00270 00271 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 00272 template<typename _Tp, size_t _Nm> 00273 typename enable_if< 00274 !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type 00275 swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete; 00276 #endif 00277 00278 template<typename _Tp, std::size_t _Nm> 00279 inline void 00280 swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) 00281 noexcept(noexcept(__one.swap(__two))) 00282 { __one.swap(__two); } 00283 00284 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00285 constexpr _Tp& 00286 get(array<_Tp, _Nm>& __arr) noexcept 00287 { 00288 static_assert(_Int < _Nm, "index is out of bounds"); 00289 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 00290 _S_ref(__arr._M_elems, _Int); 00291 } 00292 00293 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00294 constexpr _Tp&& 00295 get(array<_Tp, _Nm>&& __arr) noexcept 00296 { 00297 static_assert(_Int < _Nm, "index is out of bounds"); 00298 return std::move(__debug::get<_Int>(__arr)); 00299 } 00300 00301 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00302 constexpr const _Tp& 00303 get(const array<_Tp, _Nm>& __arr) noexcept 00304 { 00305 static_assert(_Int < _Nm, "index is out of bounds"); 00306 return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: 00307 _S_ref(__arr._M_elems, _Int); 00308 } 00309 00310 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00311 constexpr const _Tp&& 00312 get(const array<_Tp, _Nm>&& __arr) noexcept 00313 { 00314 static_assert(_Int < _Nm, "index is out of bounds"); 00315 return std::move(__debug::get<_Int>(__arr)); 00316 } 00317 } // namespace __debug 00318 00319 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00320 // Tuple interface to class template array. 00321 00322 /// tuple_size 00323 template<typename _Tp, std::size_t _Nm> 00324 struct tuple_size<std::__debug::array<_Tp, _Nm>> 00325 : public integral_constant<std::size_t, _Nm> { }; 00326 00327 /// tuple_element 00328 template<std::size_t _Int, typename _Tp, std::size_t _Nm> 00329 struct tuple_element<_Int, std::__debug::array<_Tp, _Nm>> 00330 { 00331 static_assert(_Int < _Nm, "index is out of bounds"); 00332 typedef _Tp type; 00333 }; 00334 00335 template<typename _Tp, std::size_t _Nm> 00336 struct __is_tuple_like_impl<std::__debug::array<_Tp, _Nm>> : true_type 00337 { }; 00338 00339 _GLIBCXX_END_NAMESPACE_VERSION 00340 } // namespace std 00341 00342 #endif // _GLIBCXX_DEBUG_ARRAY