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