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