1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 // Free Software Foundation, Inc.
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)
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.
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.
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/>.
26 /** @file debug/unordered_map
27 * This file is a GNU debug extension to the Standard C++ Library.
30 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
31 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
33 #ifndef __GXX_EXPERIMENTAL_CXX0X__
34 # include <bits/c++0x_warning.h>
36 # include <unordered_map>
38 #include <debug/safe_sequence.h>
39 #include <debug/safe_iterator.h>
45 /// Class std::unordered_map with safety/checking/debug instrumentation.
46 template<typename _Key, typename _Tp,
47 typename _Hash = std::hash<_Key>,
48 typename _Pred = std::equal_to<_Key>,
49 typename _Alloc = std::allocator<_Key> >
51 : public _GLIBCXX_STD_D::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
52 public __gnu_debug::_Safe_sequence<unordered_map<_Key, _Tp, _Hash,
55 typedef _GLIBCXX_STD_D::unordered_map<_Key, _Tp, _Hash,
57 typedef __gnu_debug::_Safe_sequence<unordered_map> _Safe_base;
58 typedef typename _Base::const_iterator _Base_const_iterator;
59 typedef typename _Base::iterator _Base_iterator;
60 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
63 typedef typename _Base::size_type size_type;
64 typedef typename _Base::hasher hasher;
65 typedef typename _Base::key_equal key_equal;
66 typedef typename _Base::allocator_type allocator_type;
68 typedef typename _Base::key_type key_type;
69 typedef typename _Base::value_type value_type;
71 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
72 unordered_map> iterator;
73 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
74 unordered_map> const_iterator;
77 unordered_map(size_type __n = 10,
78 const hasher& __hf = hasher(),
79 const key_equal& __eql = key_equal(),
80 const allocator_type& __a = allocator_type())
81 : _Base(__n, __hf, __eql, __a) { }
83 template<typename _InputIterator>
84 unordered_map(_InputIterator __first, _InputIterator __last,
86 const hasher& __hf = hasher(),
87 const key_equal& __eql = key_equal(),
88 const allocator_type& __a = allocator_type())
89 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
91 __gnu_debug::__base(__last), __n,
92 __hf, __eql, __a), _Safe_base() { }
94 unordered_map(const unordered_map& __x)
95 : _Base(__x), _Safe_base() { }
97 unordered_map(const _Base& __x)
98 : _Base(__x), _Safe_base() { }
100 unordered_map(unordered_map&& __x)
101 : _Base(std::move(__x)), _Safe_base() { }
103 unordered_map(initializer_list<value_type> __l,
105 const hasher& __hf = hasher(),
106 const key_equal& __eql = key_equal(),
107 const allocator_type& __a = allocator_type())
108 : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
111 operator=(const unordered_map& __x)
113 *static_cast<_Base*>(this) = __x;
114 this->_M_invalidate_all();
119 operator=(unordered_map&& __x)
129 operator=(initializer_list<value_type> __l)
137 swap(unordered_map& __x)
140 _Safe_base::_M_swap(__x);
147 this->_M_invalidate_all();
152 { return iterator(_Base::begin(), this); }
156 { return const_iterator(_Base::begin(), this); }
160 { return iterator(_Base::end(), this); }
164 { return const_iterator(_Base::end(), this); }
168 { return const_iterator(_Base::begin(), this); }
172 { return const_iterator(_Base::end(), this); }
180 std::pair<iterator, bool>
181 insert(const value_type& __obj)
183 std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
184 return std::make_pair(iterator(__res.first, this), __res.second);
188 insert(const_iterator, const value_type& __obj)
190 return iterator(_Base::insert(__obj).first, this);
193 template<typename _Pair, typename = typename
194 std::enable_if<std::is_convertible<_Pair,
195 value_type>::value>::type>
196 std::pair<iterator, bool>
197 insert(_Pair&& __obj)
199 std::pair<_Base_iterator, bool> __res =
200 _Base::insert(std::forward<_Pair>(__obj));
201 return std::make_pair(iterator(__res.first, this), __res.second);
204 template<typename _Pair, typename = typename
205 std::enable_if<std::is_convertible<_Pair,
206 value_type>::value>::type>
208 insert(const_iterator, _Pair&& __obj)
210 return iterator(_Base::insert(std::forward<_Pair>(__obj)).first,
215 insert(std::initializer_list<value_type> __l)
216 { _Base::insert(__l); }
218 template<typename _InputIterator>
220 insert(_InputIterator __first, _InputIterator __last)
222 __glibcxx_check_valid_range(__first, __last);
223 _Base::insert(__gnu_debug::__base(__first),
224 __gnu_debug::__base(__last));
228 find(const key_type& __key)
229 { return iterator(_Base::find(__key), this); }
232 find(const key_type& __key) const
233 { return const_iterator(_Base::find(__key), this); }
235 std::pair<iterator, iterator>
236 equal_range(const key_type& __key)
238 std::pair<_Base_iterator, _Base_iterator> __res =
239 _Base::equal_range(__key);
240 return std::make_pair(iterator(__res.first, this),
241 iterator(__res.second, this));
244 std::pair<const_iterator, const_iterator>
245 equal_range(const key_type& __key) const
247 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
248 _Base::equal_range(__key);
249 return std::make_pair(const_iterator(__res.first, this),
250 const_iterator(__res.second, this));
254 erase(const key_type& __key)
257 _Base_iterator __victim(_Base::find(__key));
258 if (__victim != _Base::end())
260 this->_M_invalidate_if(_Equal(__victim));
261 _Base::erase(__victim);
268 erase(const_iterator __it)
270 __glibcxx_check_erase(__it);
271 this->_M_invalidate_if(_Equal(__it.base()));
272 return iterator(_Base::erase(__it.base()), this);
276 erase(const_iterator __first, const_iterator __last)
278 __glibcxx_check_erase_range(__first, __last);
279 for (_Base_const_iterator __tmp = __first.base();
280 __tmp != __last.base(); ++__tmp)
282 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
283 _M_message(__gnu_debug::__msg_valid_range)
284 ._M_iterator(__first, "first")
285 ._M_iterator(__last, "last"));
286 this->_M_invalidate_if(_Equal(__tmp));
288 return iterator(_Base::erase(__first.base(),
289 __last.base()), this);
293 _M_base() { return *this; }
296 _M_base() const { return *this; }
302 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
303 this->_M_invalidate_if(_Not_equal(_Base::end()));
307 template<typename _Key, typename _Tp, typename _Hash,
308 typename _Pred, typename _Alloc>
310 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
311 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
314 template<typename _Key, typename _Tp, typename _Hash,
315 typename _Pred, typename _Alloc>
317 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
318 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
319 { return __x._M_equal(__y); }
321 template<typename _Key, typename _Tp, typename _Hash,
322 typename _Pred, typename _Alloc>
324 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
325 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
326 { return !(__x == __y); }
329 /// Class std::unordered_multimap with safety/checking/debug instrumentation.
330 template<typename _Key, typename _Tp,
331 typename _Hash = std::hash<_Key>,
332 typename _Pred = std::equal_to<_Key>,
333 typename _Alloc = std::allocator<_Key> >
334 class unordered_multimap
335 : public _GLIBCXX_STD_D::unordered_multimap<_Key, _Tp, _Hash,
337 public __gnu_debug::_Safe_sequence<unordered_multimap<_Key, _Tp, _Hash,
340 typedef _GLIBCXX_STD_D::unordered_multimap<_Key, _Tp, _Hash,
341 _Pred, _Alloc> _Base;
342 typedef __gnu_debug::_Safe_sequence<unordered_multimap> _Safe_base;
343 typedef typename _Base::const_iterator _Base_const_iterator;
344 typedef typename _Base::iterator _Base_iterator;
345 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
348 typedef typename _Base::size_type size_type;
349 typedef typename _Base::hasher hasher;
350 typedef typename _Base::key_equal key_equal;
351 typedef typename _Base::allocator_type allocator_type;
353 typedef typename _Base::key_type key_type;
354 typedef typename _Base::value_type value_type;
356 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
357 unordered_multimap> iterator;
358 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
359 unordered_multimap> const_iterator;
362 unordered_multimap(size_type __n = 10,
363 const hasher& __hf = hasher(),
364 const key_equal& __eql = key_equal(),
365 const allocator_type& __a = allocator_type())
366 : _Base(__n, __hf, __eql, __a) { }
368 template<typename _InputIterator>
369 unordered_multimap(_InputIterator __first, _InputIterator __last,
371 const hasher& __hf = hasher(),
372 const key_equal& __eql = key_equal(),
373 const allocator_type& __a = allocator_type())
374 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
376 __gnu_debug::__base(__last), __n,
377 __hf, __eql, __a), _Safe_base() { }
379 unordered_multimap(const unordered_multimap& __x)
380 : _Base(__x), _Safe_base() { }
382 unordered_multimap(const _Base& __x)
383 : _Base(__x), _Safe_base() { }
385 unordered_multimap(unordered_multimap&& __x)
386 : _Base(std::move(__x)), _Safe_base() { }
388 unordered_multimap(initializer_list<value_type> __l,
390 const hasher& __hf = hasher(),
391 const key_equal& __eql = key_equal(),
392 const allocator_type& __a = allocator_type())
393 : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
396 operator=(const unordered_multimap& __x)
398 *static_cast<_Base*>(this) = __x;
399 this->_M_invalidate_all();
404 operator=(unordered_multimap&& __x)
414 operator=(initializer_list<value_type> __l)
422 swap(unordered_multimap& __x)
425 _Safe_base::_M_swap(__x);
432 this->_M_invalidate_all();
437 { return iterator(_Base::begin(), this); }
441 { return const_iterator(_Base::begin(), this); }
445 { return iterator(_Base::end(), this); }
449 { return const_iterator(_Base::end(), this); }
453 { return const_iterator(_Base::begin(), this); }
457 { return const_iterator(_Base::end(), this); }
466 insert(const value_type& __obj)
467 { return iterator(_Base::insert(__obj), this); }
470 insert(const_iterator, const value_type& __obj)
471 { return iterator(_Base::insert(__obj), this); }
473 template<typename _Pair, typename = typename
474 std::enable_if<std::is_convertible<_Pair,
475 value_type>::value>::type>
477 insert(_Pair&& __obj)
478 { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); }
480 template<typename _Pair, typename = typename
481 std::enable_if<std::is_convertible<_Pair,
482 value_type>::value>::type>
484 insert(const_iterator, _Pair&& __obj)
485 { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); }
488 insert(std::initializer_list<value_type> __l)
489 { _Base::insert(__l); }
491 template<typename _InputIterator>
493 insert(_InputIterator __first, _InputIterator __last)
495 __glibcxx_check_valid_range(__first, __last);
496 _Base::insert(__gnu_debug::__base(__first),
497 __gnu_debug::__base(__last));
501 find(const key_type& __key)
502 { return iterator(_Base::find(__key), this); }
505 find(const key_type& __key) const
506 { return const_iterator(_Base::find(__key), this); }
508 std::pair<iterator, iterator>
509 equal_range(const key_type& __key)
511 std::pair<_Base_iterator, _Base_iterator> __res =
512 _Base::equal_range(__key);
513 return std::make_pair(iterator(__res.first, this),
514 iterator(__res.second, this));
517 std::pair<const_iterator, const_iterator>
518 equal_range(const key_type& __key) const
520 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
521 _Base::equal_range(__key);
522 return std::make_pair(const_iterator(__res.first, this),
523 const_iterator(__res.second, this));
527 erase(const key_type& __key)
530 _Base_iterator __victim(_Base::find(__key));
531 if (__victim != _Base::end())
533 this->_M_invalidate_if(_Equal(__victim));
534 _Base::erase(__victim);
541 erase(const_iterator __it)
543 __glibcxx_check_erase(__it);
544 this->_M_invalidate_if(_Equal(__it.base()));
545 return iterator(_Base::erase(__it.base()), this);
549 erase(const_iterator __first, const_iterator __last)
551 __glibcxx_check_erase_range(__first, __last);
552 for (_Base_const_iterator __tmp = __first.base();
553 __tmp != __last.base(); ++__tmp)
555 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
556 _M_message(__gnu_debug::__msg_valid_range)
557 ._M_iterator(__first, "first")
558 ._M_iterator(__last, "last"));
559 this->_M_invalidate_if(_Equal(__tmp));
561 return iterator(_Base::erase(__first.base(),
562 __last.base()), this);
566 _M_base() { return *this; }
569 _M_base() const { return *this; }
575 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
576 this->_M_invalidate_if(_Not_equal(_Base::end()));
580 template<typename _Key, typename _Tp, typename _Hash,
581 typename _Pred, typename _Alloc>
583 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
584 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
587 template<typename _Key, typename _Tp, typename _Hash,
588 typename _Pred, typename _Alloc>
590 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
591 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
592 { return __x._M_equal(__y); }
594 template<typename _Key, typename _Tp, typename _Hash,
595 typename _Pred, typename _Alloc>
597 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
598 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
599 { return !(__x == __y); }
601 } // namespace __debug
604 #endif // __GXX_EXPERIMENTAL_CXX0X__