1 // Debugging deque implementation -*- C++ -*- 2 3 // Copyright (C) 2003-2013 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/deque 26 * This file is a GNU debug extension to the Standard C++ Library. 27 */ 28 29 #ifndef _GLIBCXX_DEBUG_DEQUE 30 #define _GLIBCXX_DEBUG_DEQUE 1 31 32 #include <deque> 33 #include <debug/safe_sequence.h> 34 #include <debug/safe_iterator.h> 35 36 namespace std _GLIBCXX_VISIBILITY(default) 37 { 38 namespace __debug 39 { 40 /// Class std::deque with safety/checking/debug instrumentation. 41 template<typename _Tp, typename _Allocator = std::allocator<_Tp> > 42 class deque 43 : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>, 44 public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> > 45 { 46 typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base; 47 48 typedef typename _Base::const_iterator _Base_const_iterator; 49 typedef typename _Base::iterator _Base_iterator; 50 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; 51 public: 52 typedef typename _Base::reference reference; 53 typedef typename _Base::const_reference const_reference; 54 55 typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque> 56 iterator; 57 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque> 58 const_iterator; 59 60 typedef typename _Base::size_type size_type; 61 typedef typename _Base::difference_type difference_type; 62 63 typedef _Tp value_type; 64 typedef _Allocator allocator_type; 65 typedef typename _Base::pointer pointer; 66 typedef typename _Base::const_pointer const_pointer; 67 typedef std::reverse_iterator<iterator> reverse_iterator; 68 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 69 70 // 23.2.1.1 construct/copy/destroy: 71 explicit 72 deque(const _Allocator& __a = _Allocator()) 73 : _Base(__a) { } 74 75 #if __cplusplus >= 201103L 76 explicit 77 deque(size_type __n) 78 : _Base(__n) { } 79 80 deque(size_type __n, const _Tp& __value, 81 const _Allocator& __a = _Allocator()) 82 : _Base(__n, __value, __a) { } 83 #else 84 explicit 85 deque(size_type __n, const _Tp& __value = _Tp(), 86 const _Allocator& __a = _Allocator()) 87 : _Base(__n, __value, __a) { } 88 #endif 89 90 #if __cplusplus >= 201103L 91 template<class _InputIterator, 92 typename = std::_RequireInputIter<_InputIterator>> 93 #else 94 template<class _InputIterator> 95 #endif 96 deque(_InputIterator __first, _InputIterator __last, 97 const _Allocator& __a = _Allocator()) 98 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 99 __last)), 100 __gnu_debug::__base(__last), __a) 101 { } 102 103 deque(const deque& __x) 104 : _Base(__x) { } 105 106 deque(const _Base& __x) 107 : _Base(__x) { } 108 109 #if __cplusplus >= 201103L 110 deque(deque&& __x) 111 : _Base(std::move(__x)) 112 { this->_M_swap(__x); } 113 114 deque(initializer_list<value_type> __l, 115 const allocator_type& __a = allocator_type()) 116 : _Base(__l, __a) { } 117 #endif 118 119 ~deque() _GLIBCXX_NOEXCEPT { } 120 121 deque& 122 operator=(const deque& __x) 123 { 124 *static_cast<_Base*>(this) = __x; 125 this->_M_invalidate_all(); 126 return *this; 127 } 128 129 #if __cplusplus >= 201103L 130 deque& 131 operator=(deque&& __x) 132 { 133 // NB: DR 1204. 134 // NB: DR 675. 135 __glibcxx_check_self_move_assign(__x); 136 clear(); 137 swap(__x); 138 return *this; 139 } 140 141 deque& 142 operator=(initializer_list<value_type> __l) 143 { 144 *static_cast<_Base*>(this) = __l; 145 this->_M_invalidate_all(); 146 return *this; 147 } 148 #endif 149 150 #if __cplusplus >= 201103L 151 template<class _InputIterator, 152 typename = std::_RequireInputIter<_InputIterator>> 153 #else 154 template<class _InputIterator> 155 #endif 156 void 157 assign(_InputIterator __first, _InputIterator __last) 158 { 159 __glibcxx_check_valid_range(__first, __last); 160 _Base::assign(__gnu_debug::__base(__first), 161 __gnu_debug::__base(__last)); 162 this->_M_invalidate_all(); 163 } 164 165 void 166 assign(size_type __n, const _Tp& __t) 167 { 168 _Base::assign(__n, __t); 169 this->_M_invalidate_all(); 170 } 171 172 #if __cplusplus >= 201103L 173 void 174 assign(initializer_list<value_type> __l) 175 { 176 _Base::assign(__l); 177 this->_M_invalidate_all(); 178 } 179 #endif 180 181 using _Base::get_allocator; 182 183 // iterators: 184 iterator 185 begin() _GLIBCXX_NOEXCEPT 186 { return iterator(_Base::begin(), this); } 187 188 const_iterator 189 begin() const _GLIBCXX_NOEXCEPT 190 { return const_iterator(_Base::begin(), this); } 191 192 iterator 193 end() _GLIBCXX_NOEXCEPT 194 { return iterator(_Base::end(), this); } 195 196 const_iterator 197 end() const _GLIBCXX_NOEXCEPT 198 { return const_iterator(_Base::end(), this); } 199 200 reverse_iterator 201 rbegin() _GLIBCXX_NOEXCEPT 202 { return reverse_iterator(end()); } 203 204 const_reverse_iterator 205 rbegin() const _GLIBCXX_NOEXCEPT 206 { return const_reverse_iterator(end()); } 207 208 reverse_iterator 209 rend() _GLIBCXX_NOEXCEPT 210 { return reverse_iterator(begin()); } 211 212 const_reverse_iterator 213 rend() const _GLIBCXX_NOEXCEPT 214 { return const_reverse_iterator(begin()); } 215 216 #if __cplusplus >= 201103L 217 const_iterator 218 cbegin() const noexcept 219 { return const_iterator(_Base::begin(), this); } 220 221 const_iterator 222 cend() const noexcept 223 { return const_iterator(_Base::end(), this); } 224 225 const_reverse_iterator 226 crbegin() const noexcept 227 { return const_reverse_iterator(end()); } 228 229 const_reverse_iterator 230 crend() const noexcept 231 { return const_reverse_iterator(begin()); } 232 #endif 233 234 private: 235 void 236 _M_invalidate_after_nth(difference_type __n) 237 { 238 typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth; 239 this->_M_invalidate_if(_After_nth(__n, _Base::begin())); 240 } 241 242 public: 243 // 23.2.1.2 capacity: 244 using _Base::size; 245 using _Base::max_size; 246 247 #if __cplusplus >= 201103L 248 void 249 resize(size_type __sz) 250 { 251 bool __invalidate_all = __sz > this->size(); 252 if (__sz < this->size()) 253 this->_M_invalidate_after_nth(__sz); 254 255 _Base::resize(__sz); 256 257 if (__invalidate_all) 258 this->_M_invalidate_all(); 259 } 260 261 void 262 resize(size_type __sz, const _Tp& __c) 263 { 264 bool __invalidate_all = __sz > this->size(); 265 if (__sz < this->size()) 266 this->_M_invalidate_after_nth(__sz); 267 268 _Base::resize(__sz, __c); 269 270 if (__invalidate_all) 271 this->_M_invalidate_all(); 272 } 273 #else 274 void 275 resize(size_type __sz, _Tp __c = _Tp()) 276 { 277 bool __invalidate_all = __sz > this->size(); 278 if (__sz < this->size()) 279 this->_M_invalidate_after_nth(__sz); 280 281 _Base::resize(__sz, __c); 282 283 if (__invalidate_all) 284 this->_M_invalidate_all(); 285 } 286 #endif 287 288 #if __cplusplus >= 201103L 289 void 290 shrink_to_fit() 291 { 292 if (_Base::_M_shrink_to_fit()) 293 this->_M_invalidate_all(); 294 } 295 #endif 296 297 using _Base::empty; 298 299 // element access: 300 reference 301 operator[](size_type __n) 302 { 303 __glibcxx_check_subscript(__n); 304 return _M_base()[__n]; 305 } 306 307 const_reference 308 operator[](size_type __n) const 309 { 310 __glibcxx_check_subscript(__n); 311 return _M_base()[__n]; 312 } 313 314 using _Base::at; 315 316 reference 317 front() 318 { 319 __glibcxx_check_nonempty(); 320 return _Base::front(); 321 } 322 323 const_reference 324 front() const 325 { 326 __glibcxx_check_nonempty(); 327 return _Base::front(); 328 } 329 330 reference 331 back() 332 { 333 __glibcxx_check_nonempty(); 334 return _Base::back(); 335 } 336 337 const_reference 338 back() const 339 { 340 __glibcxx_check_nonempty(); 341 return _Base::back(); 342 } 343 344 // 23.2.1.3 modifiers: 345 void 346 push_front(const _Tp& __x) 347 { 348 _Base::push_front(__x); 349 this->_M_invalidate_all(); 350 } 351 352 void 353 push_back(const _Tp& __x) 354 { 355 _Base::push_back(__x); 356 this->_M_invalidate_all(); 357 } 358 359 #if __cplusplus >= 201103L 360 void 361 push_front(_Tp&& __x) 362 { emplace_front(std::move(__x)); } 363 364 void 365 push_back(_Tp&& __x) 366 { emplace_back(std::move(__x)); } 367 368 template<typename... _Args> 369 void 370 emplace_front(_Args&&... __args) 371 { 372 _Base::emplace_front(std::forward<_Args>(__args)...); 373 this->_M_invalidate_all(); 374 } 375 376 template<typename... _Args> 377 void 378 emplace_back(_Args&&... __args) 379 { 380 _Base::emplace_back(std::forward<_Args>(__args)...); 381 this->_M_invalidate_all(); 382 } 383 384 template<typename... _Args> 385 iterator 386 emplace(iterator __position, _Args&&... __args) 387 { 388 __glibcxx_check_insert(__position); 389 _Base_iterator __res = _Base::emplace(__position.base(), 390 std::forward<_Args>(__args)...); 391 this->_M_invalidate_all(); 392 return iterator(__res, this); 393 } 394 #endif 395 396 iterator 397 insert(iterator __position, const _Tp& __x) 398 { 399 __glibcxx_check_insert(__position); 400 _Base_iterator __res = _Base::insert(__position.base(), __x); 401 this->_M_invalidate_all(); 402 return iterator(__res, this); 403 } 404 405 #if __cplusplus >= 201103L 406 iterator 407 insert(iterator __position, _Tp&& __x) 408 { return emplace(__position, std::move(__x)); } 409 410 void 411 insert(iterator __p, initializer_list<value_type> __l) 412 { 413 _Base::insert(__p, __l); 414 this->_M_invalidate_all(); 415 } 416 #endif 417 418 void 419 insert(iterator __position, size_type __n, const _Tp& __x) 420 { 421 __glibcxx_check_insert(__position); 422 _Base::insert(__position.base(), __n, __x); 423 this->_M_invalidate_all(); 424 } 425 426 #if __cplusplus >= 201103L 427 template<class _InputIterator, 428 typename = std::_RequireInputIter<_InputIterator>> 429 #else 430 template<class _InputIterator> 431 #endif 432 void 433 insert(iterator __position, 434 _InputIterator __first, _InputIterator __last) 435 { 436 __glibcxx_check_insert_range(__position, __first, __last); 437 _Base::insert(__position.base(), __gnu_debug::__base(__first), 438 __gnu_debug::__base(__last)); 439 this->_M_invalidate_all(); 440 } 441 442 void 443 pop_front() 444 { 445 __glibcxx_check_nonempty(); 446 this->_M_invalidate_if(_Equal(_Base::begin())); 447 _Base::pop_front(); 448 } 449 450 void 451 pop_back() 452 { 453 __glibcxx_check_nonempty(); 454 this->_M_invalidate_if(_Equal(--_Base::end())); 455 _Base::pop_back(); 456 } 457 458 iterator 459 erase(iterator __position) 460 { 461 __glibcxx_check_erase(__position); 462 _Base_iterator __victim = __position.base(); 463 if (__victim == _Base::begin() || __victim == _Base::end()-1) 464 { 465 this->_M_invalidate_if(_Equal(__victim)); 466 return iterator(_Base::erase(__victim), this); 467 } 468 else 469 { 470 _Base_iterator __res = _Base::erase(__victim); 471 this->_M_invalidate_all(); 472 return iterator(__res, this); 473 } 474 } 475 476 iterator 477 erase(iterator __first, iterator __last) 478 { 479 // _GLIBCXX_RESOLVE_LIB_DEFECTS 480 // 151. can't currently clear() empty container 481 __glibcxx_check_erase_range(__first, __last); 482 483 if (__first.base() == __last.base()) 484 return __first; 485 else if (__first.base() == _Base::begin() 486 || __last.base() == _Base::end()) 487 { 488 this->_M_detach_singular(); 489 for (_Base_iterator __position = __first.base(); 490 __position != __last.base(); ++__position) 491 { 492 this->_M_invalidate_if(_Equal(__position)); 493 } 494 __try 495 { 496 return iterator(_Base::erase(__first.base(), __last.base()), 497 this); 498 } 499 __catch(...) 500 { 501 this->_M_revalidate_singular(); 502 __throw_exception_again; 503 } 504 } 505 else 506 { 507 _Base_iterator __res = _Base::erase(__first.base(), 508 __last.base()); 509 this->_M_invalidate_all(); 510 return iterator(__res, this); 511 } 512 } 513 514 void 515 swap(deque& __x) 516 { 517 _Base::swap(__x); 518 this->_M_swap(__x); 519 } 520 521 void 522 clear() _GLIBCXX_NOEXCEPT 523 { 524 _Base::clear(); 525 this->_M_invalidate_all(); 526 } 527 528 _Base& 529 _M_base() _GLIBCXX_NOEXCEPT { return *this; } 530 531 const _Base& 532 _M_base() const _GLIBCXX_NOEXCEPT { return *this; } 533 }; 534 535 template<typename _Tp, typename _Alloc> 536 inline bool 537 operator==(const deque<_Tp, _Alloc>& __lhs, 538 const deque<_Tp, _Alloc>& __rhs) 539 { return __lhs._M_base() == __rhs._M_base(); } 540 541 template<typename _Tp, typename _Alloc> 542 inline bool 543 operator!=(const deque<_Tp, _Alloc>& __lhs, 544 const deque<_Tp, _Alloc>& __rhs) 545 { return __lhs._M_base() != __rhs._M_base(); } 546 547 template<typename _Tp, typename _Alloc> 548 inline bool 549 operator<(const deque<_Tp, _Alloc>& __lhs, 550 const deque<_Tp, _Alloc>& __rhs) 551 { return __lhs._M_base() < __rhs._M_base(); } 552 553 template<typename _Tp, typename _Alloc> 554 inline bool 555 operator<=(const deque<_Tp, _Alloc>& __lhs, 556 const deque<_Tp, _Alloc>& __rhs) 557 { return __lhs._M_base() <= __rhs._M_base(); } 558 559 template<typename _Tp, typename _Alloc> 560 inline bool 561 operator>=(const deque<_Tp, _Alloc>& __lhs, 562 const deque<_Tp, _Alloc>& __rhs) 563 { return __lhs._M_base() >= __rhs._M_base(); } 564 565 template<typename _Tp, typename _Alloc> 566 inline bool 567 operator>(const deque<_Tp, _Alloc>& __lhs, 568 const deque<_Tp, _Alloc>& __rhs) 569 { return __lhs._M_base() > __rhs._M_base(); } 570 571 template<typename _Tp, typename _Alloc> 572 inline void 573 swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs) 574 { __lhs.swap(__rhs); } 575 576 } // namespace __debug 577 } // namespace std 578 579 #endif 580