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>
41 namespace std _GLIBCXX_VISIBILITY(default)
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_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
52 public __gnu_debug::_Safe_sequence<unordered_map<_Key, _Tp, _Hash,
55 typedef _GLIBCXX_STD_C::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); }
155 begin() const noexcept
156 { return const_iterator(_Base::begin(), this); }
160 { return iterator(_Base::end(), this); }
164 { return const_iterator(_Base::end(), this); }
167 cbegin() const noexcept
168 { return const_iterator(_Base::begin(), this); }
171 cend() const noexcept
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 __hint, const value_type& __obj)
190 __glibcxx_check_insert(__hint);
191 return iterator(_Base::insert(__hint.base(), __obj), this);
194 template<typename _Pair, typename = typename
195 std::enable_if<std::is_convertible<_Pair,
196 value_type>::value>::type>
197 std::pair<iterator, bool>
198 insert(_Pair&& __obj)
200 std::pair<_Base_iterator, bool> __res =
201 _Base::insert(std::forward<_Pair>(__obj));
202 return std::make_pair(iterator(__res.first, this), __res.second);
205 template<typename _Pair, typename = typename
206 std::enable_if<std::is_convertible<_Pair,
207 value_type>::value>::type>
209 insert(const_iterator __hint, _Pair&& __obj)
211 __glibcxx_check_insert(__hint);
212 return iterator(_Base::insert(__hint.base(),
213 std::forward<_Pair>(__obj)),
218 insert(std::initializer_list<value_type> __l)
219 { _Base::insert(__l); }
221 template<typename _InputIterator>
223 insert(_InputIterator __first, _InputIterator __last)
225 __glibcxx_check_valid_range(__first, __last);
226 _Base::insert(__gnu_debug::__base(__first),
227 __gnu_debug::__base(__last));
231 find(const key_type& __key)
232 { return iterator(_Base::find(__key), this); }
235 find(const key_type& __key) const
236 { return const_iterator(_Base::find(__key), this); }
238 std::pair<iterator, iterator>
239 equal_range(const key_type& __key)
241 std::pair<_Base_iterator, _Base_iterator> __res =
242 _Base::equal_range(__key);
243 return std::make_pair(iterator(__res.first, this),
244 iterator(__res.second, this));
247 std::pair<const_iterator, const_iterator>
248 equal_range(const key_type& __key) const
250 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
251 _Base::equal_range(__key);
252 return std::make_pair(const_iterator(__res.first, this),
253 const_iterator(__res.second, this));
257 erase(const key_type& __key)
260 _Base_iterator __victim(_Base::find(__key));
261 if (__victim != _Base::end())
263 this->_M_invalidate_if(_Equal(__victim));
264 _Base::erase(__victim);
271 erase(const_iterator __it)
273 __glibcxx_check_erase(__it);
274 this->_M_invalidate_if(_Equal(__it.base()));
275 return iterator(_Base::erase(__it.base()), this);
279 erase(const_iterator __first, const_iterator __last)
281 __glibcxx_check_erase_range(__first, __last);
282 for (_Base_const_iterator __tmp = __first.base();
283 __tmp != __last.base(); ++__tmp)
285 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
286 _M_message(__gnu_debug::__msg_valid_range)
287 ._M_iterator(__first, "first")
288 ._M_iterator(__last, "last"));
289 this->_M_invalidate_if(_Equal(__tmp));
291 return iterator(_Base::erase(__first.base(),
292 __last.base()), this);
296 _M_base() noexcept { return *this; }
299 _M_base() const noexcept { return *this; }
305 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
306 this->_M_invalidate_if(_Not_equal(_Base::end()));
310 template<typename _Key, typename _Tp, typename _Hash,
311 typename _Pred, typename _Alloc>
313 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
314 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
317 template<typename _Key, typename _Tp, typename _Hash,
318 typename _Pred, typename _Alloc>
320 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
321 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
322 { return __x._M_equal(__y); }
324 template<typename _Key, typename _Tp, typename _Hash,
325 typename _Pred, typename _Alloc>
327 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
328 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
329 { return !(__x == __y); }
332 /// Class std::unordered_multimap with safety/checking/debug instrumentation.
333 template<typename _Key, typename _Tp,
334 typename _Hash = std::hash<_Key>,
335 typename _Pred = std::equal_to<_Key>,
336 typename _Alloc = std::allocator<_Key> >
337 class unordered_multimap
338 : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
340 public __gnu_debug::_Safe_sequence<unordered_multimap<_Key, _Tp, _Hash,
343 typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
344 _Pred, _Alloc> _Base;
345 typedef __gnu_debug::_Safe_sequence<unordered_multimap> _Safe_base;
346 typedef typename _Base::const_iterator _Base_const_iterator;
347 typedef typename _Base::iterator _Base_iterator;
348 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
351 typedef typename _Base::size_type size_type;
352 typedef typename _Base::hasher hasher;
353 typedef typename _Base::key_equal key_equal;
354 typedef typename _Base::allocator_type allocator_type;
356 typedef typename _Base::key_type key_type;
357 typedef typename _Base::value_type value_type;
359 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
360 unordered_multimap> iterator;
361 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
362 unordered_multimap> const_iterator;
365 unordered_multimap(size_type __n = 10,
366 const hasher& __hf = hasher(),
367 const key_equal& __eql = key_equal(),
368 const allocator_type& __a = allocator_type())
369 : _Base(__n, __hf, __eql, __a) { }
371 template<typename _InputIterator>
372 unordered_multimap(_InputIterator __first, _InputIterator __last,
374 const hasher& __hf = hasher(),
375 const key_equal& __eql = key_equal(),
376 const allocator_type& __a = allocator_type())
377 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
379 __gnu_debug::__base(__last), __n,
380 __hf, __eql, __a), _Safe_base() { }
382 unordered_multimap(const unordered_multimap& __x)
383 : _Base(__x), _Safe_base() { }
385 unordered_multimap(const _Base& __x)
386 : _Base(__x), _Safe_base() { }
388 unordered_multimap(unordered_multimap&& __x)
389 : _Base(std::move(__x)), _Safe_base() { }
391 unordered_multimap(initializer_list<value_type> __l,
393 const hasher& __hf = hasher(),
394 const key_equal& __eql = key_equal(),
395 const allocator_type& __a = allocator_type())
396 : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
399 operator=(const unordered_multimap& __x)
401 *static_cast<_Base*>(this) = __x;
402 this->_M_invalidate_all();
407 operator=(unordered_multimap&& __x)
417 operator=(initializer_list<value_type> __l)
425 swap(unordered_multimap& __x)
428 _Safe_base::_M_swap(__x);
435 this->_M_invalidate_all();
440 { return iterator(_Base::begin(), this); }
443 begin() const noexcept
444 { return const_iterator(_Base::begin(), this); }
448 { return iterator(_Base::end(), this); }
452 { return const_iterator(_Base::end(), this); }
455 cbegin() const noexcept
456 { return const_iterator(_Base::begin(), this); }
459 cend() const noexcept
460 { return const_iterator(_Base::end(), this); }
469 insert(const value_type& __obj)
470 { return iterator(_Base::insert(__obj), this); }
473 insert(const_iterator __hint, const value_type& __obj)
475 __glibcxx_check_insert(__hint);
476 return iterator(_Base::insert(__hint.base(), __obj), this);
479 template<typename _Pair, typename = typename
480 std::enable_if<std::is_convertible<_Pair,
481 value_type>::value>::type>
483 insert(_Pair&& __obj)
484 { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); }
486 template<typename _Pair, typename = typename
487 std::enable_if<std::is_convertible<_Pair,
488 value_type>::value>::type>
490 insert(const_iterator __hint, _Pair&& __obj)
492 __glibcxx_check_insert(__hint);
493 return iterator(_Base::insert(__hint.base(),
494 std::forward<_Pair>(__obj)),
499 insert(std::initializer_list<value_type> __l)
500 { _Base::insert(__l); }
502 template<typename _InputIterator>
504 insert(_InputIterator __first, _InputIterator __last)
506 __glibcxx_check_valid_range(__first, __last);
507 _Base::insert(__gnu_debug::__base(__first),
508 __gnu_debug::__base(__last));
512 find(const key_type& __key)
513 { return iterator(_Base::find(__key), this); }
516 find(const key_type& __key) const
517 { return const_iterator(_Base::find(__key), this); }
519 std::pair<iterator, iterator>
520 equal_range(const key_type& __key)
522 std::pair<_Base_iterator, _Base_iterator> __res =
523 _Base::equal_range(__key);
524 return std::make_pair(iterator(__res.first, this),
525 iterator(__res.second, this));
528 std::pair<const_iterator, const_iterator>
529 equal_range(const key_type& __key) const
531 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
532 _Base::equal_range(__key);
533 return std::make_pair(const_iterator(__res.first, this),
534 const_iterator(__res.second, this));
538 erase(const key_type& __key)
541 std::pair<_Base_iterator, _Base_iterator> __pair =
542 _Base::equal_range(__key);
543 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
545 this->_M_invalidate_if(_Equal(__victim));
546 _Base::erase(__victim++);
553 erase(const_iterator __it)
555 __glibcxx_check_erase(__it);
556 this->_M_invalidate_if(_Equal(__it.base()));
557 return iterator(_Base::erase(__it.base()), this);
561 erase(const_iterator __first, const_iterator __last)
563 __glibcxx_check_erase_range(__first, __last);
564 for (_Base_const_iterator __tmp = __first.base();
565 __tmp != __last.base(); ++__tmp)
567 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
568 _M_message(__gnu_debug::__msg_valid_range)
569 ._M_iterator(__first, "first")
570 ._M_iterator(__last, "last"));
571 this->_M_invalidate_if(_Equal(__tmp));
573 return iterator(_Base::erase(__first.base(),
574 __last.base()), this);
578 _M_base() noexcept { return *this; }
581 _M_base() const noexcept { return *this; }
587 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
588 this->_M_invalidate_if(_Not_equal(_Base::end()));
592 template<typename _Key, typename _Tp, typename _Hash,
593 typename _Pred, typename _Alloc>
595 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
596 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
599 template<typename _Key, typename _Tp, typename _Hash,
600 typename _Pred, typename _Alloc>
602 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
603 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
604 { return __x._M_equal(__y); }
606 template<typename _Key, typename _Tp, typename _Hash,
607 typename _Pred, typename _Alloc>
609 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
610 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
611 { return !(__x == __y); }
613 } // namespace __debug
616 #endif // __GXX_EXPERIMENTAL_CXX0X__