1// Debugging map implementation -*- C++ -*- 2 3// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 4// Free Software Foundation, Inc. 5// 6// This file is part of the GNU ISO C++ Library. This library is free 7// software; you can redistribute it and/or modify it under the 8// terms of the GNU General Public License as published by the 9// Free Software Foundation; either version 3, or (at your option) 10// any later version. 11 12// This library is distributed in the hope that it will be useful, 13// but WITHOUT ANY WARRANTY; without even the implied warranty of 14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15// GNU General Public License for more details. 16 17// Under Section 7 of GPL version 3, you are granted additional 18// permissions described in the GCC Runtime Library Exception, version 19// 3.1, as published by the Free Software Foundation. 20 21// You should have received a copy of the GNU General Public License and 22// a copy of the GCC Runtime Library Exception along with this program; 23// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24// <http://www.gnu.org/licenses/>. 25 26/** @file debug/map.h 27 * This file is a GNU debug extension to the Standard C++ Library. 28 */ 29 30#ifndef _GLIBCXX_DEBUG_MAP_H 31#define _GLIBCXX_DEBUG_MAP_H 1 32 33#include <debug/safe_sequence.h> 34#include <debug/safe_iterator.h> 35#include <utility> 36 37namespace std _GLIBCXX_VISIBILITY(default) 38{ 39namespace __debug 40{ 41 /// Class std::map with safety/checking/debug instrumentation. 42 template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>, 43 typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > > 44 class map 45 : public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>, 46 public __gnu_debug::_Safe_sequence<map<_Key, _Tp, _Compare, _Allocator> > 47 { 48 typedef _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator> _Base; 49 50 typedef typename _Base::const_iterator _Base_const_iterator; 51 typedef typename _Base::iterator _Base_iterator; 52 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; 53 public: 54 // types: 55 typedef _Key key_type; 56 typedef _Tp mapped_type; 57 typedef std::pair<const _Key, _Tp> value_type; 58 typedef _Compare key_compare; 59 typedef _Allocator allocator_type; 60 typedef typename _Base::reference reference; 61 typedef typename _Base::const_reference const_reference; 62 63 typedef __gnu_debug::_Safe_iterator<_Base_iterator, map> 64 iterator; 65 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, map> 66 const_iterator; 67 68 typedef typename _Base::size_type size_type; 69 typedef typename _Base::difference_type difference_type; 70 typedef typename _Base::pointer pointer; 71 typedef typename _Base::const_pointer const_pointer; 72 typedef std::reverse_iterator<iterator> reverse_iterator; 73 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 74 75 // 23.3.1.1 construct/copy/destroy: 76 explicit map(const _Compare& __comp = _Compare(), 77 const _Allocator& __a = _Allocator()) 78 : _Base(__comp, __a) { } 79 80 template<typename _InputIterator> 81 map(_InputIterator __first, _InputIterator __last, 82 const _Compare& __comp = _Compare(), 83 const _Allocator& __a = _Allocator()) 84 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 85 __last)), 86 __gnu_debug::__base(__last), 87 __comp, __a) { } 88 89 map(const map& __x) 90 : _Base(__x) { } 91 92 map(const _Base& __x) 93 : _Base(__x) { } 94 95#ifdef __GXX_EXPERIMENTAL_CXX0X__ 96 map(map&& __x) 97 noexcept(is_nothrow_copy_constructible<_Compare>::value) 98 : _Base(std::move(__x)) 99 { this->_M_swap(__x); } 100 101 map(initializer_list<value_type> __l, 102 const _Compare& __c = _Compare(), 103 const allocator_type& __a = allocator_type()) 104 : _Base(__l, __c, __a) { } 105#endif 106 107 ~map() _GLIBCXX_NOEXCEPT { } 108 109 map& 110 operator=(const map& __x) 111 { 112 *static_cast<_Base*>(this) = __x; 113 this->_M_invalidate_all(); 114 return *this; 115 } 116 117#ifdef __GXX_EXPERIMENTAL_CXX0X__ 118 map& 119 operator=(map&& __x) 120 { 121 // NB: DR 1204. 122 // NB: DR 675. 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#ifdef __GXX_EXPERIMENTAL_CXX0X__ 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 std::pair<iterator, bool> 206 insert(const value_type& __x) 207 { 208 std::pair<_Base_iterator, bool> __res = _Base::insert(__x); 209 return std::pair<iterator, bool>(iterator(__res.first, this), 210 __res.second); 211 } 212 213#ifdef __GXX_EXPERIMENTAL_CXX0X__ 214 template<typename _Pair, typename = typename 215 std::enable_if<std::is_constructible<value_type, 216 _Pair&&>::value>::type> 217 std::pair<iterator, bool> 218 insert(_Pair&& __x) 219 { 220 std::pair<_Base_iterator, bool> __res 221 = _Base::insert(std::forward<_Pair>(__x)); 222 return std::pair<iterator, bool>(iterator(__res.first, this), 223 __res.second); 224 } 225#endif 226 227#ifdef __GXX_EXPERIMENTAL_CXX0X__ 228 void 229 insert(std::initializer_list<value_type> __list) 230 { _Base::insert(__list); } 231#endif 232 233 iterator 234#ifdef __GXX_EXPERIMENTAL_CXX0X__ 235 insert(const_iterator __position, const value_type& __x) 236#else 237 insert(iterator __position, const value_type& __x) 238#endif 239 { 240 __glibcxx_check_insert(__position); 241 return iterator(_Base::insert(__position.base(), __x), this); 242 } 243 244#ifdef __GXX_EXPERIMENTAL_CXX0X__ 245 template<typename _Pair, typename = typename 246 std::enable_if<std::is_constructible<value_type, 247 _Pair&&>::value>::type> 248 iterator 249 insert(const_iterator __position, _Pair&& __x) 250 { 251 __glibcxx_check_insert(__position); 252 return iterator(_Base::insert(__position.base(), 253 std::forward<_Pair>(__x)), this); 254 } 255#endif 256 257 template<typename _InputIterator> 258 void 259 insert(_InputIterator __first, _InputIterator __last) 260 { 261 __glibcxx_check_valid_range(__first, __last); 262 _Base::insert(__gnu_debug::__base(__first), 263 __gnu_debug::__base(__last)); 264 } 265 266#ifdef __GXX_EXPERIMENTAL_CXX0X__ 267 iterator 268 erase(const_iterator __position) 269 { 270 __glibcxx_check_erase(__position); 271 this->_M_invalidate_if(_Equal(__position.base())); 272 return iterator(_Base::erase(__position.base()), this); 273 } 274 275 iterator 276 erase(iterator __position) 277 { return erase(const_iterator(__position)); } 278#else 279 void 280 erase(iterator __position) 281 { 282 __glibcxx_check_erase(__position); 283 this->_M_invalidate_if(_Equal(__position.base())); 284 _Base::erase(__position.base()); 285 } 286#endif 287 288 size_type 289 erase(const key_type& __x) 290 { 291 _Base_iterator __victim = _Base::find(__x); 292 if (__victim == _Base::end()) 293 return 0; 294 else 295 { 296 this->_M_invalidate_if(_Equal(__victim)); 297 _Base::erase(__victim); 298 return 1; 299 } 300 } 301 302#ifdef __GXX_EXPERIMENTAL_CXX0X__ 303 iterator 304 erase(const_iterator __first, const_iterator __last) 305 { 306 // _GLIBCXX_RESOLVE_LIB_DEFECTS 307 // 151. can't currently clear() empty container 308 __glibcxx_check_erase_range(__first, __last); 309 for (_Base_const_iterator __victim = __first.base(); 310 __victim != __last.base(); ++__victim) 311 { 312 _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), 313 _M_message(__gnu_debug::__msg_valid_range) 314 ._M_iterator(__first, "first") 315 ._M_iterator(__last, "last")); 316 this->_M_invalidate_if(_Equal(__victim)); 317 } 318 return iterator(_Base::erase(__first.base(), __last.base()), this); 319 } 320#else 321 void 322 erase(iterator __first, iterator __last) 323 { 324 // _GLIBCXX_RESOLVE_LIB_DEFECTS 325 // 151. can't currently clear() empty container 326 __glibcxx_check_erase_range(__first, __last); 327 for (_Base_iterator __victim = __first.base(); 328 __victim != __last.base(); ++__victim) 329 { 330 _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), 331 _M_message(__gnu_debug::__msg_valid_range) 332 ._M_iterator(__first, "first") 333 ._M_iterator(__last, "last")); 334 this->_M_invalidate_if(_Equal(__victim)); 335 } 336 _Base::erase(__first.base(), __last.base()); 337 } 338#endif 339 340 void 341 swap(map& __x) 342 { 343 _Base::swap(__x); 344 this->_M_swap(__x); 345 } 346 347 void 348 clear() _GLIBCXX_NOEXCEPT 349 { 350 this->_M_invalidate_all(); 351 _Base::clear(); 352 } 353 354 // observers: 355 using _Base::key_comp; 356 using _Base::value_comp; 357 358 // 23.3.1.3 map operations: 359 iterator 360 find(const key_type& __x) 361 { return iterator(_Base::find(__x), this); } 362 363 const_iterator 364 find(const key_type& __x) const 365 { return const_iterator(_Base::find(__x), this); } 366 367 using _Base::count; 368 369 iterator 370 lower_bound(const key_type& __x) 371 { return iterator(_Base::lower_bound(__x), this); } 372 373 const_iterator 374 lower_bound(const key_type& __x) const 375 { return const_iterator(_Base::lower_bound(__x), this); } 376 377 iterator 378 upper_bound(const key_type& __x) 379 { return iterator(_Base::upper_bound(__x), this); } 380 381 const_iterator 382 upper_bound(const key_type& __x) const 383 { return const_iterator(_Base::upper_bound(__x), this); } 384 385 std::pair<iterator,iterator> 386 equal_range(const key_type& __x) 387 { 388 std::pair<_Base_iterator, _Base_iterator> __res = 389 _Base::equal_range(__x); 390 return std::make_pair(iterator(__res.first, this), 391 iterator(__res.second, this)); 392 } 393 394 std::pair<const_iterator,const_iterator> 395 equal_range(const key_type& __x) const 396 { 397 std::pair<_Base_const_iterator, _Base_const_iterator> __res = 398 _Base::equal_range(__x); 399 return std::make_pair(const_iterator(__res.first, this), 400 const_iterator(__res.second, this)); 401 } 402 403 _Base& 404 _M_base() _GLIBCXX_NOEXCEPT { return *this; } 405 406 const _Base& 407 _M_base() const _GLIBCXX_NOEXCEPT { return *this; } 408 409 private: 410 void 411 _M_invalidate_all() 412 { 413 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; 414 this->_M_invalidate_if(_Not_equal(_M_base().end())); 415 } 416 }; 417 418 template<typename _Key, typename _Tp, 419 typename _Compare, typename _Allocator> 420 inline bool 421 operator==(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, 422 const map<_Key, _Tp, _Compare, _Allocator>& __rhs) 423 { return __lhs._M_base() == __rhs._M_base(); } 424 425 template<typename _Key, typename _Tp, 426 typename _Compare, typename _Allocator> 427 inline bool 428 operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, 429 const map<_Key, _Tp, _Compare, _Allocator>& __rhs) 430 { return __lhs._M_base() != __rhs._M_base(); } 431 432 template<typename _Key, typename _Tp, 433 typename _Compare, typename _Allocator> 434 inline bool 435 operator<(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, 436 const map<_Key, _Tp, _Compare, _Allocator>& __rhs) 437 { return __lhs._M_base() < __rhs._M_base(); } 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 void 463 swap(map<_Key, _Tp, _Compare, _Allocator>& __lhs, 464 map<_Key, _Tp, _Compare, _Allocator>& __rhs) 465 { __lhs.swap(__rhs); } 466 467} // namespace __debug 468} // namespace std 469 470#endif 471