libstdc++
|
00001 // Debugging deque implementation -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 3, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // Under Section 7 of GPL version 3, you are granted additional 00018 // permissions described in the GCC Runtime Library Exception, version 00019 // 3.1, as published by the Free Software Foundation. 00020 00021 // You should have received a copy of the GNU General Public License and 00022 // a copy of the GCC Runtime Library Exception along with this program; 00023 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00024 // <http://www.gnu.org/licenses/>. 00025 00026 /** @file debug/deque 00027 * This file is a GNU debug extension to the Standard C++ Library. 00028 */ 00029 00030 #ifndef _GLIBCXX_DEBUG_DEQUE 00031 #define _GLIBCXX_DEBUG_DEQUE 1 00032 00033 #include <deque> 00034 #include <debug/safe_sequence.h> 00035 #include <debug/safe_iterator.h> 00036 00037 namespace std _GLIBCXX_VISIBILITY(default) 00038 { 00039 namespace __debug 00040 { 00041 /// Class std::deque with safety/checking/debug instrumentation. 00042 template<typename _Tp, typename _Allocator = std::allocator<_Tp> > 00043 class deque 00044 : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>, 00045 public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> > 00046 { 00047 typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base; 00048 00049 typedef typename _Base::const_iterator _Base_const_iterator; 00050 typedef typename _Base::iterator _Base_iterator; 00051 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; 00052 public: 00053 typedef typename _Base::reference reference; 00054 typedef typename _Base::const_reference const_reference; 00055 00056 typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque> 00057 iterator; 00058 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque> 00059 const_iterator; 00060 00061 typedef typename _Base::size_type size_type; 00062 typedef typename _Base::difference_type difference_type; 00063 00064 typedef _Tp value_type; 00065 typedef _Allocator allocator_type; 00066 typedef typename _Base::pointer pointer; 00067 typedef typename _Base::const_pointer const_pointer; 00068 typedef std::reverse_iterator<iterator> reverse_iterator; 00069 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00070 00071 // 23.2.1.1 construct/copy/destroy: 00072 explicit 00073 deque(const _Allocator& __a = _Allocator()) 00074 : _Base(__a) { } 00075 00076 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00077 explicit 00078 deque(size_type __n) 00079 : _Base(__n) { } 00080 00081 deque(size_type __n, const _Tp& __value, 00082 const _Allocator& __a = _Allocator()) 00083 : _Base(__n, __value, __a) { } 00084 #else 00085 explicit 00086 deque(size_type __n, const _Tp& __value = _Tp(), 00087 const _Allocator& __a = _Allocator()) 00088 : _Base(__n, __value, __a) { } 00089 #endif 00090 00091 template<class _InputIterator> 00092 deque(_InputIterator __first, _InputIterator __last, 00093 const _Allocator& __a = _Allocator()) 00094 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 00095 __last)), 00096 __gnu_debug::__base(__last), __a) 00097 { } 00098 00099 deque(const deque& __x) 00100 : _Base(__x) { } 00101 00102 deque(const _Base& __x) 00103 : _Base(__x) { } 00104 00105 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00106 deque(deque&& __x) 00107 : _Base(std::move(__x)) 00108 { this->_M_swap(__x); } 00109 00110 deque(initializer_list<value_type> __l, 00111 const allocator_type& __a = allocator_type()) 00112 : _Base(__l, __a) { } 00113 #endif 00114 00115 ~deque() _GLIBCXX_NOEXCEPT { } 00116 00117 deque& 00118 operator=(const deque& __x) 00119 { 00120 *static_cast<_Base*>(this) = __x; 00121 this->_M_invalidate_all(); 00122 return *this; 00123 } 00124 00125 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00126 deque& 00127 operator=(deque&& __x) 00128 { 00129 // NB: DR 1204. 00130 // NB: DR 675. 00131 clear(); 00132 swap(__x); 00133 return *this; 00134 } 00135 00136 deque& 00137 operator=(initializer_list<value_type> __l) 00138 { 00139 *static_cast<_Base*>(this) = __l; 00140 this->_M_invalidate_all(); 00141 return *this; 00142 } 00143 #endif 00144 00145 template<class _InputIterator> 00146 void 00147 assign(_InputIterator __first, _InputIterator __last) 00148 { 00149 __glibcxx_check_valid_range(__first, __last); 00150 _Base::assign(__gnu_debug::__base(__first), 00151 __gnu_debug::__base(__last)); 00152 this->_M_invalidate_all(); 00153 } 00154 00155 void 00156 assign(size_type __n, const _Tp& __t) 00157 { 00158 _Base::assign(__n, __t); 00159 this->_M_invalidate_all(); 00160 } 00161 00162 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00163 void 00164 assign(initializer_list<value_type> __l) 00165 { 00166 _Base::assign(__l); 00167 this->_M_invalidate_all(); 00168 } 00169 #endif 00170 00171 using _Base::get_allocator; 00172 00173 // iterators: 00174 iterator 00175 begin() _GLIBCXX_NOEXCEPT 00176 { return iterator(_Base::begin(), this); } 00177 00178 const_iterator 00179 begin() const _GLIBCXX_NOEXCEPT 00180 { return const_iterator(_Base::begin(), this); } 00181 00182 iterator 00183 end() _GLIBCXX_NOEXCEPT 00184 { return iterator(_Base::end(), this); } 00185 00186 const_iterator 00187 end() const _GLIBCXX_NOEXCEPT 00188 { return const_iterator(_Base::end(), this); } 00189 00190 reverse_iterator 00191 rbegin() _GLIBCXX_NOEXCEPT 00192 { return reverse_iterator(end()); } 00193 00194 const_reverse_iterator 00195 rbegin() const _GLIBCXX_NOEXCEPT 00196 { return const_reverse_iterator(end()); } 00197 00198 reverse_iterator 00199 rend() _GLIBCXX_NOEXCEPT 00200 { return reverse_iterator(begin()); } 00201 00202 const_reverse_iterator 00203 rend() const _GLIBCXX_NOEXCEPT 00204 { return const_reverse_iterator(begin()); } 00205 00206 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00207 const_iterator 00208 cbegin() const noexcept 00209 { return const_iterator(_Base::begin(), this); } 00210 00211 const_iterator 00212 cend() const noexcept 00213 { return const_iterator(_Base::end(), this); } 00214 00215 const_reverse_iterator 00216 crbegin() const noexcept 00217 { return const_reverse_iterator(end()); } 00218 00219 const_reverse_iterator 00220 crend() const noexcept 00221 { return const_reverse_iterator(begin()); } 00222 #endif 00223 00224 private: 00225 void 00226 _M_invalidate_after_nth(difference_type __n) 00227 { 00228 typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth; 00229 this->_M_invalidate_if(_After_nth(__n, _Base::begin())); 00230 } 00231 00232 public: 00233 // 23.2.1.2 capacity: 00234 using _Base::size; 00235 using _Base::max_size; 00236 00237 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00238 void 00239 resize(size_type __sz) 00240 { 00241 bool __invalidate_all = __sz > this->size(); 00242 if (__sz < this->size()) 00243 this->_M_invalidate_after_nth(__sz); 00244 00245 _Base::resize(__sz); 00246 00247 if (__invalidate_all) 00248 this->_M_invalidate_all(); 00249 } 00250 00251 void 00252 resize(size_type __sz, const _Tp& __c) 00253 { 00254 bool __invalidate_all = __sz > this->size(); 00255 if (__sz < this->size()) 00256 this->_M_invalidate_after_nth(__sz); 00257 00258 _Base::resize(__sz, __c); 00259 00260 if (__invalidate_all) 00261 this->_M_invalidate_all(); 00262 } 00263 #else 00264 void 00265 resize(size_type __sz, _Tp __c = _Tp()) 00266 { 00267 bool __invalidate_all = __sz > this->size(); 00268 if (__sz < this->size()) 00269 this->_M_invalidate_after_nth(__sz); 00270 00271 _Base::resize(__sz, __c); 00272 00273 if (__invalidate_all) 00274 this->_M_invalidate_all(); 00275 } 00276 #endif 00277 00278 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00279 void 00280 shrink_to_fit() 00281 { 00282 if (_Base::_M_shrink_to_fit()) 00283 this->_M_invalidate_all(); 00284 } 00285 #endif 00286 00287 using _Base::empty; 00288 00289 // element access: 00290 reference 00291 operator[](size_type __n) 00292 { 00293 __glibcxx_check_subscript(__n); 00294 return _M_base()[__n]; 00295 } 00296 00297 const_reference 00298 operator[](size_type __n) const 00299 { 00300 __glibcxx_check_subscript(__n); 00301 return _M_base()[__n]; 00302 } 00303 00304 using _Base::at; 00305 00306 reference 00307 front() 00308 { 00309 __glibcxx_check_nonempty(); 00310 return _Base::front(); 00311 } 00312 00313 const_reference 00314 front() const 00315 { 00316 __glibcxx_check_nonempty(); 00317 return _Base::front(); 00318 } 00319 00320 reference 00321 back() 00322 { 00323 __glibcxx_check_nonempty(); 00324 return _Base::back(); 00325 } 00326 00327 const_reference 00328 back() const 00329 { 00330 __glibcxx_check_nonempty(); 00331 return _Base::back(); 00332 } 00333 00334 // 23.2.1.3 modifiers: 00335 void 00336 push_front(const _Tp& __x) 00337 { 00338 _Base::push_front(__x); 00339 this->_M_invalidate_all(); 00340 } 00341 00342 void 00343 push_back(const _Tp& __x) 00344 { 00345 _Base::push_back(__x); 00346 this->_M_invalidate_all(); 00347 } 00348 00349 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00350 void 00351 push_front(_Tp&& __x) 00352 { emplace_front(std::move(__x)); } 00353 00354 void 00355 push_back(_Tp&& __x) 00356 { emplace_back(std::move(__x)); } 00357 00358 template<typename... _Args> 00359 void 00360 emplace_front(_Args&&... __args) 00361 { 00362 _Base::emplace_front(std::forward<_Args>(__args)...); 00363 this->_M_invalidate_all(); 00364 } 00365 00366 template<typename... _Args> 00367 void 00368 emplace_back(_Args&&... __args) 00369 { 00370 _Base::emplace_back(std::forward<_Args>(__args)...); 00371 this->_M_invalidate_all(); 00372 } 00373 00374 template<typename... _Args> 00375 iterator 00376 emplace(iterator __position, _Args&&... __args) 00377 { 00378 __glibcxx_check_insert(__position); 00379 _Base_iterator __res = _Base::emplace(__position.base(), 00380 std::forward<_Args>(__args)...); 00381 this->_M_invalidate_all(); 00382 return iterator(__res, this); 00383 } 00384 #endif 00385 00386 iterator 00387 insert(iterator __position, const _Tp& __x) 00388 { 00389 __glibcxx_check_insert(__position); 00390 _Base_iterator __res = _Base::insert(__position.base(), __x); 00391 this->_M_invalidate_all(); 00392 return iterator(__res, this); 00393 } 00394 00395 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 00396 iterator 00397 insert(iterator __position, _Tp&& __x) 00398 { return emplace(__position, std::move(__x)); } 00399 00400 void 00401 insert(iterator __p, initializer_list<value_type> __l) 00402 { 00403 _Base::insert(__p, __l); 00404 this->_M_invalidate_all(); 00405 } 00406 #endif 00407 00408 void 00409 insert(iterator __position, size_type __n, const _Tp& __x) 00410 { 00411 __glibcxx_check_insert(__position); 00412 _Base::insert(__position.base(), __n, __x); 00413 this->_M_invalidate_all(); 00414 } 00415 00416 template<class _InputIterator> 00417 void 00418 insert(iterator __position, 00419 _InputIterator __first, _InputIterator __last) 00420 { 00421 __glibcxx_check_insert_range(__position, __first, __last); 00422 _Base::insert(__position.base(), __gnu_debug::__base(__first), 00423 __gnu_debug::__base(__last)); 00424 this->_M_invalidate_all(); 00425 } 00426 00427 void 00428 pop_front() 00429 { 00430 __glibcxx_check_nonempty(); 00431 this->_M_invalidate_if(_Equal(_Base::begin())); 00432 _Base::pop_front(); 00433 } 00434 00435 void 00436 pop_back() 00437 { 00438 __glibcxx_check_nonempty(); 00439 this->_M_invalidate_if(_Equal(--_Base::end())); 00440 _Base::pop_back(); 00441 } 00442 00443 iterator 00444 erase(iterator __position) 00445 { 00446 __glibcxx_check_erase(__position); 00447 _Base_iterator __victim = __position.base(); 00448 if (__victim == _Base::begin() || __victim == _Base::end()-1) 00449 { 00450 this->_M_invalidate_if(_Equal(__victim)); 00451 return iterator(_Base::erase(__victim), this); 00452 } 00453 else 00454 { 00455 _Base_iterator __res = _Base::erase(__victim); 00456 this->_M_invalidate_all(); 00457 return iterator(__res, this); 00458 } 00459 } 00460 00461 iterator 00462 erase(iterator __first, iterator __last) 00463 { 00464 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00465 // 151. can't currently clear() empty container 00466 __glibcxx_check_erase_range(__first, __last); 00467 00468 if (__first.base() == __last.base()) 00469 return __first; 00470 else if (__first.base() == _Base::begin() 00471 || __last.base() == _Base::end()) 00472 { 00473 this->_M_detach_singular(); 00474 for (_Base_iterator __position = __first.base(); 00475 __position != __last.base(); ++__position) 00476 { 00477 this->_M_invalidate_if(_Equal(__position)); 00478 } 00479 __try 00480 { 00481 return iterator(_Base::erase(__first.base(), __last.base()), 00482 this); 00483 } 00484 __catch(...) 00485 { 00486 this->_M_revalidate_singular(); 00487 __throw_exception_again; 00488 } 00489 } 00490 else 00491 { 00492 _Base_iterator __res = _Base::erase(__first.base(), 00493 __last.base()); 00494 this->_M_invalidate_all(); 00495 return iterator(__res, this); 00496 } 00497 } 00498 00499 void 00500 swap(deque& __x) 00501 { 00502 _Base::swap(__x); 00503 this->_M_swap(__x); 00504 } 00505 00506 void 00507 clear() _GLIBCXX_NOEXCEPT 00508 { 00509 _Base::clear(); 00510 this->_M_invalidate_all(); 00511 } 00512 00513 _Base& 00514 _M_base() _GLIBCXX_NOEXCEPT { return *this; } 00515 00516 const _Base& 00517 _M_base() const _GLIBCXX_NOEXCEPT { return *this; } 00518 }; 00519 00520 template<typename _Tp, typename _Alloc> 00521 inline bool 00522 operator==(const deque<_Tp, _Alloc>& __lhs, 00523 const deque<_Tp, _Alloc>& __rhs) 00524 { return __lhs._M_base() == __rhs._M_base(); } 00525 00526 template<typename _Tp, typename _Alloc> 00527 inline bool 00528 operator!=(const deque<_Tp, _Alloc>& __lhs, 00529 const deque<_Tp, _Alloc>& __rhs) 00530 { return __lhs._M_base() != __rhs._M_base(); } 00531 00532 template<typename _Tp, typename _Alloc> 00533 inline bool 00534 operator<(const deque<_Tp, _Alloc>& __lhs, 00535 const deque<_Tp, _Alloc>& __rhs) 00536 { return __lhs._M_base() < __rhs._M_base(); } 00537 00538 template<typename _Tp, typename _Alloc> 00539 inline bool 00540 operator<=(const deque<_Tp, _Alloc>& __lhs, 00541 const deque<_Tp, _Alloc>& __rhs) 00542 { return __lhs._M_base() <= __rhs._M_base(); } 00543 00544 template<typename _Tp, typename _Alloc> 00545 inline bool 00546 operator>=(const deque<_Tp, _Alloc>& __lhs, 00547 const deque<_Tp, _Alloc>& __rhs) 00548 { return __lhs._M_base() >= __rhs._M_base(); } 00549 00550 template<typename _Tp, typename _Alloc> 00551 inline bool 00552 operator>(const deque<_Tp, _Alloc>& __lhs, 00553 const deque<_Tp, _Alloc>& __rhs) 00554 { return __lhs._M_base() > __rhs._M_base(); } 00555 00556 template<typename _Tp, typename _Alloc> 00557 inline void 00558 swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs) 00559 { __lhs.swap(__rhs); } 00560 00561 } // namespace __debug 00562 } // namespace std 00563 00564 #endif