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