1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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_unordered_container.h>
39 #include <debug/safe_iterator.h>
40 #include <debug/safe_local_iterator.h>
42 namespace std _GLIBCXX_VISIBILITY(default)
46 /// Class std::unordered_map with safety/checking/debug instrumentation.
47 template<typename _Key, typename _Tp,
48 typename _Hash = std::hash<_Key>,
49 typename _Pred = std::equal_to<_Key>,
50 typename _Alloc = std::allocator<_Key> >
52 : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
53 public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
54 _Hash, _Pred, _Alloc> >
56 typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
58 typedef __gnu_debug::_Safe_unordered_container<unordered_map> _Safe_base;
59 typedef typename _Base::const_iterator _Base_const_iterator;
60 typedef typename _Base::iterator _Base_iterator;
61 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
62 typedef typename _Base::local_iterator _Base_local_iterator;
65 typedef typename _Base::size_type size_type;
66 typedef typename _Base::hasher hasher;
67 typedef typename _Base::key_equal key_equal;
68 typedef typename _Base::allocator_type allocator_type;
70 typedef typename _Base::key_type key_type;
71 typedef typename _Base::value_type value_type;
73 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
74 unordered_map> iterator;
75 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
76 unordered_map> const_iterator;
77 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
78 unordered_map> local_iterator;
79 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
80 unordered_map> const_local_iterator;
83 unordered_map(size_type __n = 10,
84 const hasher& __hf = hasher(),
85 const key_equal& __eql = key_equal(),
86 const allocator_type& __a = allocator_type())
87 : _Base(__n, __hf, __eql, __a) { }
89 template<typename _InputIterator>
90 unordered_map(_InputIterator __first, _InputIterator __last,
92 const hasher& __hf = hasher(),
93 const key_equal& __eql = key_equal(),
94 const allocator_type& __a = allocator_type())
95 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
97 __gnu_debug::__base(__last), __n,
100 unordered_map(const unordered_map& __x)
103 unordered_map(const _Base& __x)
106 unordered_map(unordered_map&& __x)
107 : _Base(std::move(__x)) { }
109 unordered_map(initializer_list<value_type> __l,
111 const hasher& __hf = hasher(),
112 const key_equal& __eql = key_equal(),
113 const allocator_type& __a = allocator_type())
114 : _Base(__l, __n, __hf, __eql, __a) { }
116 ~unordered_map() noexcept { }
119 operator=(const unordered_map& __x)
121 *static_cast<_Base*>(this) = __x;
122 this->_M_invalidate_all();
127 operator=(unordered_map&& __x)
131 __glibcxx_check_self_move_assign(__x);
138 operator=(initializer_list<value_type> __l)
146 swap(unordered_map& __x)
149 _Safe_base::_M_swap(__x);
156 this->_M_invalidate_all();
161 { return iterator(_Base::begin(), this); }
164 begin() const noexcept
165 { return const_iterator(_Base::begin(), this); }
169 { return iterator(_Base::end(), this); }
173 { return const_iterator(_Base::end(), this); }
176 cbegin() const noexcept
177 { return const_iterator(_Base::begin(), this); }
180 cend() const noexcept
181 { return const_iterator(_Base::end(), this); }
186 { return local_iterator(_Base::begin(__b), __b, this); }
190 { return local_iterator(_Base::end(__b), __b, this); }
193 begin(size_type __b) const
194 { return const_local_iterator(_Base::begin(__b), __b, this); }
197 end(size_type __b) const
198 { return const_local_iterator(_Base::end(__b), __b, this); }
201 cbegin(size_type __b) const
202 { return const_local_iterator(_Base::cbegin(__b), __b, this); }
205 cend(size_type __b) const
206 { return const_local_iterator(_Base::cend(__b), __b, this); }
208 template<typename... _Args>
209 std::pair<iterator, bool>
210 emplace(_Args&&... __args)
212 size_type __bucket_count = this->bucket_count();
213 std::pair<_Base_iterator, bool> __res
214 = _Base::emplace(std::forward<_Args>(__args)...);
215 _M_check_rehashed(__bucket_count);
216 return std::make_pair(iterator(__res.first, this), __res.second);
219 template<typename... _Args>
221 emplace_hint(const_iterator __hint, _Args&&... __args)
223 __glibcxx_check_insert(__hint);
224 size_type __bucket_count = this->bucket_count();
225 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
226 std::forward<_Args>(__args)...);
227 _M_check_rehashed(__bucket_count);
228 return iterator(__it, this);
231 std::pair<iterator, bool>
232 insert(const value_type& __obj)
234 size_type __bucket_count = this->bucket_count();
235 std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
236 _M_check_rehashed(__bucket_count);
237 return std::make_pair(iterator(__res.first, this), __res.second);
241 insert(const_iterator __hint, const value_type& __obj)
243 __glibcxx_check_insert(__hint);
244 size_type __bucket_count = this->bucket_count();
245 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
246 _M_check_rehashed(__bucket_count);
247 return iterator(__it, this);
250 template<typename _Pair, typename = typename
251 std::enable_if<std::is_convertible<_Pair,
252 value_type>::value>::type>
253 std::pair<iterator, bool>
254 insert(_Pair&& __obj)
256 size_type __bucket_count = this->bucket_count();
257 std::pair<_Base_iterator, bool> __res =
258 _Base::insert(std::forward<_Pair>(__obj));
259 _M_check_rehashed(__bucket_count);
260 return std::make_pair(iterator(__res.first, this), __res.second);
263 template<typename _Pair, typename = typename
264 std::enable_if<std::is_convertible<_Pair,
265 value_type>::value>::type>
267 insert(const_iterator __hint, _Pair&& __obj)
269 __glibcxx_check_insert(__hint);
270 size_type __bucket_count = this->bucket_count();
271 _Base_iterator __it =
272 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
273 _M_check_rehashed(__bucket_count);
274 return iterator(__it, this);
278 insert(std::initializer_list<value_type> __l)
280 size_type __bucket_count = this->bucket_count();
282 _M_check_rehashed(__bucket_count);
285 template<typename _InputIterator>
287 insert(_InputIterator __first, _InputIterator __last)
289 __glibcxx_check_valid_range(__first, __last);
290 size_type __bucket_count = this->bucket_count();
291 _Base::insert(__gnu_debug::__base(__first),
292 __gnu_debug::__base(__last));
293 _M_check_rehashed(__bucket_count);
297 find(const key_type& __key)
298 { return iterator(_Base::find(__key), this); }
301 find(const key_type& __key) const
302 { return const_iterator(_Base::find(__key), this); }
304 std::pair<iterator, iterator>
305 equal_range(const key_type& __key)
307 std::pair<_Base_iterator, _Base_iterator> __res =
308 _Base::equal_range(__key);
309 return std::make_pair(iterator(__res.first, this),
310 iterator(__res.second, this));
313 std::pair<const_iterator, const_iterator>
314 equal_range(const key_type& __key) const
316 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
317 _Base::equal_range(__key);
318 return std::make_pair(const_iterator(__res.first, this),
319 const_iterator(__res.second, this));
323 erase(const key_type& __key)
326 _Base_iterator __victim(_Base::find(__key));
327 if (__victim != _Base::end())
329 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
330 { return __it == __victim; });
331 _Base_local_iterator __local_victim = _S_to_local(__victim);
332 this->_M_invalidate_local_if(
333 [__local_victim](_Base_const_local_iterator __it)
334 { return __it == __local_victim; });
335 size_type __bucket_count = this->bucket_count();
336 _Base::erase(__victim);
337 _M_check_rehashed(__bucket_count);
344 erase(const_iterator __it)
346 __glibcxx_check_erase(__it);
347 _Base_const_iterator __victim = __it.base();
348 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
349 { return __it == __victim; });
350 _Base_const_local_iterator __local_victim = _S_to_local(__victim);
351 this->_M_invalidate_local_if(
352 [__local_victim](_Base_const_local_iterator __it)
353 { return __it == __local_victim; });
354 size_type __bucket_count = this->bucket_count();
355 _Base_iterator __next = _Base::erase(__it.base());
356 _M_check_rehashed(__bucket_count);
357 return iterator(__next, this);
362 { return erase(const_iterator(__it)); }
365 erase(const_iterator __first, const_iterator __last)
367 __glibcxx_check_erase_range(__first, __last);
368 for (_Base_const_iterator __tmp = __first.base();
369 __tmp != __last.base(); ++__tmp)
371 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
372 _M_message(__gnu_debug::__msg_valid_range)
373 ._M_iterator(__first, "first")
374 ._M_iterator(__last, "last"));
375 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
376 { return __it == __tmp; });
377 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
378 this->_M_invalidate_local_if(
379 [__local_tmp](_Base_const_local_iterator __it)
380 { return __it == __local_tmp; });
382 size_type __bucket_count = this->bucket_count();
383 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
384 _M_check_rehashed(__bucket_count);
385 return iterator(__next, this);
389 _M_base() noexcept { return *this; }
392 _M_base() const noexcept { return *this; }
396 _M_invalidate_locals()
398 _Base_local_iterator __local_end = _Base::end(0);
399 this->_M_invalidate_local_if(
400 [__local_end](_Base_const_local_iterator __it)
401 { return __it != __local_end; });
407 _Base_iterator __end = _Base::end();
408 this->_M_invalidate_if([__end](_Base_const_iterator __it)
409 { return __it != __end; });
410 _M_invalidate_locals();
414 _M_check_rehashed(size_type __prev_count)
416 if (__prev_count != this->bucket_count())
417 _M_invalidate_locals();
420 static _Base_local_iterator
421 _S_to_local(_Base_iterator __it)
423 // The returned local iterator will not be incremented so we don't
424 // need to compute __it's node bucket
425 return _Base_local_iterator(__it._M_cur, 0, 0);
428 static _Base_const_local_iterator
429 _S_to_local(_Base_const_iterator __it)
431 // The returned local iterator will not be incremented so we don't
432 // need to compute __it's node bucket
433 return _Base_const_local_iterator(__it._M_cur, 0, 0);
437 template<typename _Key, typename _Tp, typename _Hash,
438 typename _Pred, typename _Alloc>
440 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
441 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
444 template<typename _Key, typename _Tp, typename _Hash,
445 typename _Pred, typename _Alloc>
447 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
448 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
449 { return __x._M_equal(__y); }
451 template<typename _Key, typename _Tp, typename _Hash,
452 typename _Pred, typename _Alloc>
454 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
455 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
456 { return !(__x == __y); }
459 /// Class std::unordered_multimap with safety/checking/debug instrumentation.
460 template<typename _Key, typename _Tp,
461 typename _Hash = std::hash<_Key>,
462 typename _Pred = std::equal_to<_Key>,
463 typename _Alloc = std::allocator<_Key> >
464 class unordered_multimap
465 : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
467 public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
468 _Tp, _Hash, _Pred, _Alloc> >
470 typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
471 _Pred, _Alloc> _Base;
472 typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
474 typedef typename _Base::const_iterator _Base_const_iterator;
475 typedef typename _Base::iterator _Base_iterator;
476 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
477 typedef typename _Base::local_iterator _Base_local_iterator;
480 typedef typename _Base::size_type size_type;
481 typedef typename _Base::hasher hasher;
482 typedef typename _Base::key_equal key_equal;
483 typedef typename _Base::allocator_type allocator_type;
485 typedef typename _Base::key_type key_type;
486 typedef typename _Base::value_type value_type;
488 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
489 unordered_multimap> iterator;
490 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
491 unordered_multimap> const_iterator;
492 typedef __gnu_debug::_Safe_local_iterator<
493 _Base_local_iterator, unordered_multimap> local_iterator;
494 typedef __gnu_debug::_Safe_local_iterator<
495 _Base_const_local_iterator, unordered_multimap> const_local_iterator;
498 unordered_multimap(size_type __n = 10,
499 const hasher& __hf = hasher(),
500 const key_equal& __eql = key_equal(),
501 const allocator_type& __a = allocator_type())
502 : _Base(__n, __hf, __eql, __a) { }
504 template<typename _InputIterator>
505 unordered_multimap(_InputIterator __first, _InputIterator __last,
507 const hasher& __hf = hasher(),
508 const key_equal& __eql = key_equal(),
509 const allocator_type& __a = allocator_type())
510 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
512 __gnu_debug::__base(__last), __n,
513 __hf, __eql, __a) { }
515 unordered_multimap(const unordered_multimap& __x)
518 unordered_multimap(const _Base& __x)
521 unordered_multimap(unordered_multimap&& __x)
522 : _Base(std::move(__x)) { }
524 unordered_multimap(initializer_list<value_type> __l,
526 const hasher& __hf = hasher(),
527 const key_equal& __eql = key_equal(),
528 const allocator_type& __a = allocator_type())
529 : _Base(__l, __n, __hf, __eql, __a) { }
531 ~unordered_multimap() noexcept { }
534 operator=(const unordered_multimap& __x)
536 *static_cast<_Base*>(this) = __x;
537 this->_M_invalidate_all();
542 operator=(unordered_multimap&& __x)
546 __glibcxx_check_self_move_assign(__x);
553 operator=(initializer_list<value_type> __l)
561 swap(unordered_multimap& __x)
564 _Safe_base::_M_swap(__x);
571 this->_M_invalidate_all();
576 { return iterator(_Base::begin(), this); }
579 begin() const noexcept
580 { return const_iterator(_Base::begin(), this); }
584 { return iterator(_Base::end(), this); }
588 { return const_iterator(_Base::end(), this); }
591 cbegin() const noexcept
592 { return const_iterator(_Base::begin(), this); }
595 cend() const noexcept
596 { return const_iterator(_Base::end(), this); }
601 { return local_iterator(_Base::begin(__b), __b, this); }
605 { return local_iterator(_Base::end(__b), __b, this); }
608 begin(size_type __b) const
609 { return const_local_iterator(_Base::begin(__b), __b, this); }
612 end(size_type __b) const
613 { return const_local_iterator(_Base::end(__b), __b, this); }
616 cbegin(size_type __b) const
617 { return const_local_iterator(_Base::cbegin(__b), __b, this); }
620 cend(size_type __b) const
621 { return const_local_iterator(_Base::cend(__b), __b, this); }
623 template<typename... _Args>
625 emplace(_Args&&... __args)
627 size_type __bucket_count = this->bucket_count();
629 = _Base::emplace(std::forward<_Args>(__args)...);
630 _M_check_rehashed(__bucket_count);
631 return iterator(__it, this);
634 template<typename... _Args>
636 emplace_hint(const_iterator __hint, _Args&&... __args)
638 __glibcxx_check_insert(__hint);
639 size_type __bucket_count = this->bucket_count();
640 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
641 std::forward<_Args>(__args)...);
642 _M_check_rehashed(__bucket_count);
643 return iterator(__it, this);
647 insert(const value_type& __obj)
649 size_type __bucket_count = this->bucket_count();
650 _Base_iterator __it = _Base::insert(__obj);
651 _M_check_rehashed(__bucket_count);
652 return iterator(__it, this);
656 insert(const_iterator __hint, const value_type& __obj)
658 __glibcxx_check_insert(__hint);
659 size_type __bucket_count = this->bucket_count();
660 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
661 _M_check_rehashed(__bucket_count);
662 return iterator(__it, this);
665 template<typename _Pair, typename = typename
666 std::enable_if<std::is_convertible<_Pair,
667 value_type>::value>::type>
669 insert(_Pair&& __obj)
671 size_type __bucket_count = this->bucket_count();
672 _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
673 _M_check_rehashed(__bucket_count);
674 return iterator(__it, this);
677 template<typename _Pair, typename = typename
678 std::enable_if<std::is_convertible<_Pair,
679 value_type>::value>::type>
681 insert(const_iterator __hint, _Pair&& __obj)
683 __glibcxx_check_insert(__hint);
684 size_type __bucket_count = this->bucket_count();
685 _Base_iterator __it =
686 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
687 _M_check_rehashed(__bucket_count);
688 return iterator(__it, this);
692 insert(std::initializer_list<value_type> __l)
693 { _Base::insert(__l); }
695 template<typename _InputIterator>
697 insert(_InputIterator __first, _InputIterator __last)
699 __glibcxx_check_valid_range(__first, __last);
700 size_type __bucket_count = this->bucket_count();
701 _Base::insert(__gnu_debug::__base(__first),
702 __gnu_debug::__base(__last));
703 _M_check_rehashed(__bucket_count);
707 find(const key_type& __key)
708 { return iterator(_Base::find(__key), this); }
711 find(const key_type& __key) const
712 { return const_iterator(_Base::find(__key), this); }
714 std::pair<iterator, iterator>
715 equal_range(const key_type& __key)
717 std::pair<_Base_iterator, _Base_iterator> __res =
718 _Base::equal_range(__key);
719 return std::make_pair(iterator(__res.first, this),
720 iterator(__res.second, this));
723 std::pair<const_iterator, const_iterator>
724 equal_range(const key_type& __key) const
726 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
727 _Base::equal_range(__key);
728 return std::make_pair(const_iterator(__res.first, this),
729 const_iterator(__res.second, this));
733 erase(const key_type& __key)
736 size_type __bucket_count = this->bucket_count();
737 std::pair<_Base_iterator, _Base_iterator> __pair =
738 _Base::equal_range(__key);
739 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
741 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
742 { return __it == __victim; });
743 _Base_local_iterator __local_victim = _S_to_local(__victim);
744 this->_M_invalidate_local_if(
745 [__local_victim](_Base_const_local_iterator __it)
746 { return __it == __local_victim; });
747 _Base::erase(__victim++);
750 _M_check_rehashed(__bucket_count);
755 erase(const_iterator __it)
757 __glibcxx_check_erase(__it);
758 _Base_const_iterator __victim = __it.base();
759 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
760 { return __it == __victim; });
761 _Base_const_local_iterator __local_victim = _S_to_local(__victim);
762 this->_M_invalidate_local_if(
763 [__local_victim](_Base_const_local_iterator __it)
764 { return __it == __local_victim; });
765 size_type __bucket_count = this->bucket_count();
766 _Base_iterator __next = _Base::erase(__it.base());
767 _M_check_rehashed(__bucket_count);
768 return iterator(__next, this);
773 { return erase(const_iterator(__it)); }
776 erase(const_iterator __first, const_iterator __last)
778 __glibcxx_check_erase_range(__first, __last);
779 for (_Base_const_iterator __tmp = __first.base();
780 __tmp != __last.base(); ++__tmp)
782 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
783 _M_message(__gnu_debug::__msg_valid_range)
784 ._M_iterator(__first, "first")
785 ._M_iterator(__last, "last"));
786 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
787 { return __it == __tmp; });
788 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
789 this->_M_invalidate_local_if(
790 [__local_tmp](_Base_const_local_iterator __it)
791 { return __it == __local_tmp; });
793 size_type __bucket_count = this->bucket_count();
794 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
795 _M_check_rehashed(__bucket_count);
796 return iterator(__next, this);
800 _M_base() noexcept { return *this; }
803 _M_base() const noexcept { return *this; }
807 _M_invalidate_locals()
809 _Base_local_iterator __local_end = _Base::end(0);
810 this->_M_invalidate_local_if(
811 [__local_end](_Base_const_local_iterator __it)
812 { return __it != __local_end; });
818 _Base_iterator __end = _Base::end();
819 this->_M_invalidate_if([__end](_Base_const_iterator __it)
820 { return __it != __end; });
821 _M_invalidate_locals();
825 _M_check_rehashed(size_type __prev_count)
827 if (__prev_count != this->bucket_count())
828 _M_invalidate_locals();
831 static _Base_local_iterator
832 _S_to_local(_Base_iterator __it)
834 // The returned local iterator will not be incremented so we don't
835 // need to compute __it's node bucket
836 return _Base_local_iterator(__it._M_cur, 0, 0);
839 static _Base_const_local_iterator
840 _S_to_local(_Base_const_iterator __it)
842 // The returned local iterator will not be incremented so we don't
843 // need to compute __it's node bucket
844 return _Base_const_local_iterator(__it._M_cur, 0, 0);
848 template<typename _Key, typename _Tp, typename _Hash,
849 typename _Pred, typename _Alloc>
851 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
852 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
855 template<typename _Key, typename _Tp, typename _Hash,
856 typename _Pred, typename _Alloc>
858 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
859 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
860 { return __x._M_equal(__y); }
862 template<typename _Key, typename _Tp, typename _Hash,
863 typename _Pred, typename _Alloc>
865 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
866 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
867 { return !(__x == __y); }
869 } // namespace __debug
872 #endif // __GXX_EXPERIMENTAL_CXX0X__