1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25 /** @file debug/unordered_map
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
30 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
32 #if __cplusplus < 201103L
33 # include <bits/c++0x_warning.h>
35 # include <unordered_map>
37 #include <debug/safe_unordered_container.h>
38 #include <debug/safe_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<std::pair<const _Key, _Tp> > >
52 : public __gnu_debug::_Safe_container<
53 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
54 __gnu_debug::_Safe_unordered_container>,
55 public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
57 typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
59 typedef __gnu_debug::_Safe_container<unordered_map,
60 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
61 typedef typename _Base::const_iterator _Base_const_iterator;
62 typedef typename _Base::iterator _Base_iterator;
63 typedef typename _Base::const_local_iterator
64 _Base_const_local_iterator;
65 typedef typename _Base::local_iterator _Base_local_iterator;
68 typedef typename _Base::size_type size_type;
69 typedef typename _Base::hasher hasher;
70 typedef typename _Base::key_equal key_equal;
71 typedef typename _Base::allocator_type allocator_type;
73 typedef typename _Base::key_type key_type;
74 typedef typename _Base::value_type value_type;
76 typedef __gnu_debug::_Safe_iterator<
77 _Base_iterator, unordered_map> iterator;
78 typedef __gnu_debug::_Safe_iterator<
79 _Base_const_iterator, unordered_map> const_iterator;
80 typedef __gnu_debug::_Safe_local_iterator<
81 _Base_local_iterator, unordered_map> local_iterator;
82 typedef __gnu_debug::_Safe_local_iterator<
83 _Base_const_local_iterator, unordered_map> const_local_iterator;
86 unordered_map(size_type __n = 10,
87 const hasher& __hf = hasher(),
88 const key_equal& __eql = key_equal(),
89 const allocator_type& __a = allocator_type())
90 : _Base(__n, __hf, __eql, __a) { }
92 template<typename _InputIterator>
93 unordered_map(_InputIterator __first, _InputIterator __last,
95 const hasher& __hf = hasher(),
96 const key_equal& __eql = key_equal(),
97 const allocator_type& __a = allocator_type())
98 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
100 __gnu_debug::__base(__last), __n,
101 __hf, __eql, __a) { }
103 unordered_map(const unordered_map&) = default;
105 unordered_map(const _Base& __x)
108 unordered_map(unordered_map&&) = default;
111 unordered_map(const allocator_type& __a)
114 unordered_map(const unordered_map& __umap,
115 const allocator_type& __a)
116 : _Base(__umap, __a) { }
118 unordered_map(unordered_map&& __umap,
119 const allocator_type& __a)
120 : _Safe(std::move(__umap._M_safe()), __a),
121 _Base(std::move(__umap._M_base()), __a) { }
123 unordered_map(initializer_list<value_type> __l,
125 const hasher& __hf = hasher(),
126 const key_equal& __eql = key_equal(),
127 const allocator_type& __a = allocator_type())
128 : _Base(__l, __n, __hf, __eql, __a) { }
130 ~unordered_map() = default;
133 operator=(const unordered_map&) = default;
136 operator=(unordered_map&&) = default;
139 operator=(initializer_list<value_type> __l)
142 this->_M_invalidate_all();
147 swap(unordered_map& __x)
148 noexcept( noexcept(declval<_Base>().swap(__x)) )
158 this->_M_invalidate_all();
163 { return iterator(_Base::begin(), this); }
166 begin() const noexcept
167 { return const_iterator(_Base::begin(), this); }
171 { return iterator(_Base::end(), this); }
175 { return const_iterator(_Base::end(), this); }
178 cbegin() const noexcept
179 { return const_iterator(_Base::begin(), this); }
182 cend() const noexcept
183 { return const_iterator(_Base::end(), this); }
189 __glibcxx_check_bucket_index(__b);
190 return local_iterator(_Base::begin(__b), this);
196 __glibcxx_check_bucket_index(__b);
197 return local_iterator(_Base::end(__b), this);
201 begin(size_type __b) const
203 __glibcxx_check_bucket_index(__b);
204 return const_local_iterator(_Base::begin(__b), this);
208 end(size_type __b) const
210 __glibcxx_check_bucket_index(__b);
211 return const_local_iterator(_Base::end(__b), this);
215 cbegin(size_type __b) const
217 __glibcxx_check_bucket_index(__b);
218 return const_local_iterator(_Base::cbegin(__b), this);
222 cend(size_type __b) const
224 __glibcxx_check_bucket_index(__b);
225 return const_local_iterator(_Base::cend(__b), this);
229 bucket_size(size_type __b) const
231 __glibcxx_check_bucket_index(__b);
232 return _Base::bucket_size(__b);
236 max_load_factor() const noexcept
237 { return _Base::max_load_factor(); }
240 max_load_factor(float __f)
242 __glibcxx_check_max_load_factor(__f);
243 _Base::max_load_factor(__f);
246 template<typename... _Args>
247 std::pair<iterator, bool>
248 emplace(_Args&&... __args)
250 size_type __bucket_count = this->bucket_count();
251 std::pair<_Base_iterator, bool> __res
252 = _Base::emplace(std::forward<_Args>(__args)...);
253 _M_check_rehashed(__bucket_count);
254 return std::make_pair(iterator(__res.first, this), __res.second);
257 template<typename... _Args>
259 emplace_hint(const_iterator __hint, _Args&&... __args)
261 __glibcxx_check_insert(__hint);
262 size_type __bucket_count = this->bucket_count();
263 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
264 std::forward<_Args>(__args)...);
265 _M_check_rehashed(__bucket_count);
266 return iterator(__it, this);
269 std::pair<iterator, bool>
270 insert(const value_type& __obj)
272 size_type __bucket_count = this->bucket_count();
273 std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
274 _M_check_rehashed(__bucket_count);
275 return std::make_pair(iterator(__res.first, this), __res.second);
279 insert(const_iterator __hint, const value_type& __obj)
281 __glibcxx_check_insert(__hint);
282 size_type __bucket_count = this->bucket_count();
283 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
284 _M_check_rehashed(__bucket_count);
285 return iterator(__it, this);
288 template<typename _Pair, typename = typename
289 std::enable_if<std::is_constructible<value_type,
290 _Pair&&>::value>::type>
291 std::pair<iterator, bool>
292 insert(_Pair&& __obj)
294 size_type __bucket_count = this->bucket_count();
295 std::pair<_Base_iterator, bool> __res =
296 _Base::insert(std::forward<_Pair>(__obj));
297 _M_check_rehashed(__bucket_count);
298 return std::make_pair(iterator(__res.first, this), __res.second);
301 template<typename _Pair, typename = typename
302 std::enable_if<std::is_constructible<value_type,
303 _Pair&&>::value>::type>
305 insert(const_iterator __hint, _Pair&& __obj)
307 __glibcxx_check_insert(__hint);
308 size_type __bucket_count = this->bucket_count();
309 _Base_iterator __it =
310 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
311 _M_check_rehashed(__bucket_count);
312 return iterator(__it, this);
316 insert(std::initializer_list<value_type> __l)
318 size_type __bucket_count = this->bucket_count();
320 _M_check_rehashed(__bucket_count);
323 template<typename _InputIterator>
325 insert(_InputIterator __first, _InputIterator __last)
327 __glibcxx_check_valid_range(__first, __last);
328 size_type __bucket_count = this->bucket_count();
329 _Base::insert(__gnu_debug::__base(__first),
330 __gnu_debug::__base(__last));
331 _M_check_rehashed(__bucket_count);
335 find(const key_type& __key)
336 { return iterator(_Base::find(__key), this); }
339 find(const key_type& __key) const
340 { return const_iterator(_Base::find(__key), this); }
342 std::pair<iterator, iterator>
343 equal_range(const key_type& __key)
345 std::pair<_Base_iterator, _Base_iterator> __res =
346 _Base::equal_range(__key);
347 return std::make_pair(iterator(__res.first, this),
348 iterator(__res.second, this));
351 std::pair<const_iterator, const_iterator>
352 equal_range(const key_type& __key) const
354 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
355 _Base::equal_range(__key);
356 return std::make_pair(const_iterator(__res.first, this),
357 const_iterator(__res.second, this));
361 erase(const key_type& __key)
364 _Base_iterator __victim(_Base::find(__key));
365 if (__victim != _Base::end())
367 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
368 { return __it == __victim; });
369 this->_M_invalidate_local_if(
370 [__victim](_Base_const_local_iterator __it)
371 { return __it._M_curr() == __victim._M_cur; });
372 size_type __bucket_count = this->bucket_count();
373 _Base::erase(__victim);
374 _M_check_rehashed(__bucket_count);
381 erase(const_iterator __it)
383 __glibcxx_check_erase(__it);
384 _Base_const_iterator __victim = __it.base();
385 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
386 { return __it == __victim; });
387 this->_M_invalidate_local_if(
388 [__victim](_Base_const_local_iterator __it)
389 { return __it._M_curr() == __victim._M_cur; });
390 size_type __bucket_count = this->bucket_count();
391 _Base_iterator __next = _Base::erase(__it.base());
392 _M_check_rehashed(__bucket_count);
393 return iterator(__next, this);
398 { return erase(const_iterator(__it)); }
401 erase(const_iterator __first, const_iterator __last)
403 __glibcxx_check_erase_range(__first, __last);
404 for (_Base_const_iterator __tmp = __first.base();
405 __tmp != __last.base(); ++__tmp)
407 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
408 _M_message(__gnu_debug::__msg_valid_range)
409 ._M_iterator(__first, "first")
410 ._M_iterator(__last, "last"));
411 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
412 { return __it == __tmp; });
413 this->_M_invalidate_local_if(
414 [__tmp](_Base_const_local_iterator __it)
415 { return __it._M_curr() == __tmp._M_cur; });
417 size_type __bucket_count = this->bucket_count();
418 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
419 _M_check_rehashed(__bucket_count);
420 return iterator(__next, this);
424 _M_base() noexcept { return *this; }
427 _M_base() const noexcept { return *this; }
431 _M_check_rehashed(size_type __prev_count)
433 if (__prev_count != this->bucket_count())
434 this->_M_invalidate_locals();
438 template<typename _Key, typename _Tp, typename _Hash,
439 typename _Pred, typename _Alloc>
441 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
442 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
445 template<typename _Key, typename _Tp, typename _Hash,
446 typename _Pred, typename _Alloc>
448 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
449 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
450 { return __x._M_base() == __y._M_base(); }
452 template<typename _Key, typename _Tp, typename _Hash,
453 typename _Pred, typename _Alloc>
455 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
456 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
457 { return !(__x == __y); }
460 /// Class std::unordered_multimap with safety/checking/debug instrumentation.
461 template<typename _Key, typename _Tp,
462 typename _Hash = std::hash<_Key>,
463 typename _Pred = std::equal_to<_Key>,
464 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
465 class unordered_multimap
466 : public __gnu_debug::_Safe_container<
467 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
468 __gnu_debug::_Safe_unordered_container>,
469 public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
471 typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
472 _Pred, _Alloc> _Base;
473 typedef __gnu_debug::_Safe_container<unordered_multimap,
474 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
475 typedef typename _Base::const_iterator _Base_const_iterator;
476 typedef typename _Base::iterator _Base_iterator;
477 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
478 typedef typename _Base::local_iterator _Base_local_iterator;
481 typedef typename _Base::size_type size_type;
482 typedef typename _Base::hasher hasher;
483 typedef typename _Base::key_equal key_equal;
484 typedef typename _Base::allocator_type allocator_type;
486 typedef typename _Base::key_type key_type;
487 typedef typename _Base::value_type value_type;
489 typedef __gnu_debug::_Safe_iterator<
490 _Base_iterator, unordered_multimap> iterator;
491 typedef __gnu_debug::_Safe_iterator<
492 _Base_const_iterator, unordered_multimap> const_iterator;
493 typedef __gnu_debug::_Safe_local_iterator<
494 _Base_local_iterator, unordered_multimap> local_iterator;
495 typedef __gnu_debug::_Safe_local_iterator<
496 _Base_const_local_iterator, unordered_multimap> const_local_iterator;
499 unordered_multimap(size_type __n = 10,
500 const hasher& __hf = hasher(),
501 const key_equal& __eql = key_equal(),
502 const allocator_type& __a = allocator_type())
503 : _Base(__n, __hf, __eql, __a) { }
505 template<typename _InputIterator>
506 unordered_multimap(_InputIterator __first, _InputIterator __last,
508 const hasher& __hf = hasher(),
509 const key_equal& __eql = key_equal(),
510 const allocator_type& __a = allocator_type())
511 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
513 __gnu_debug::__base(__last), __n,
514 __hf, __eql, __a) { }
516 unordered_multimap(const unordered_multimap&) = default;
518 unordered_multimap(const _Base& __x)
521 unordered_multimap(unordered_multimap&&) = default;
524 unordered_multimap(const allocator_type& __a)
527 unordered_multimap(const unordered_multimap& __umap,
528 const allocator_type& __a)
529 : _Base(__umap, __a) { }
531 unordered_multimap(unordered_multimap&& __umap,
532 const allocator_type& __a)
533 : _Safe(std::move(__umap._M_safe()), __a),
534 _Base(std::move(__umap._M_base()), __a) { }
536 unordered_multimap(initializer_list<value_type> __l,
538 const hasher& __hf = hasher(),
539 const key_equal& __eql = key_equal(),
540 const allocator_type& __a = allocator_type())
541 : _Base(__l, __n, __hf, __eql, __a) { }
543 ~unordered_multimap() = default;
546 operator=(const unordered_multimap&) = default;
549 operator=(unordered_multimap&&) = default;
552 operator=(initializer_list<value_type> __l)
554 this->_M_base() = __l;
555 this->_M_invalidate_all();
560 swap(unordered_multimap& __x)
561 noexcept( noexcept(declval<_Base>().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); }
602 __glibcxx_check_bucket_index(__b);
603 return local_iterator(_Base::begin(__b), this);
609 __glibcxx_check_bucket_index(__b);
610 return local_iterator(_Base::end(__b), this);
614 begin(size_type __b) const
616 __glibcxx_check_bucket_index(__b);
617 return const_local_iterator(_Base::begin(__b), this);
621 end(size_type __b) const
623 __glibcxx_check_bucket_index(__b);
624 return const_local_iterator(_Base::end(__b), this);
628 cbegin(size_type __b) const
630 __glibcxx_check_bucket_index(__b);
631 return const_local_iterator(_Base::cbegin(__b), this);
635 cend(size_type __b) const
637 __glibcxx_check_bucket_index(__b);
638 return const_local_iterator(_Base::cend(__b), this);
642 bucket_size(size_type __b) const
644 __glibcxx_check_bucket_index(__b);
645 return _Base::bucket_size(__b);
649 max_load_factor() const noexcept
650 { return _Base::max_load_factor(); }
653 max_load_factor(float __f)
655 __glibcxx_check_max_load_factor(__f);
656 _Base::max_load_factor(__f);
659 template<typename... _Args>
661 emplace(_Args&&... __args)
663 size_type __bucket_count = this->bucket_count();
665 = _Base::emplace(std::forward<_Args>(__args)...);
666 _M_check_rehashed(__bucket_count);
667 return iterator(__it, this);
670 template<typename... _Args>
672 emplace_hint(const_iterator __hint, _Args&&... __args)
674 __glibcxx_check_insert(__hint);
675 size_type __bucket_count = this->bucket_count();
676 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
677 std::forward<_Args>(__args)...);
678 _M_check_rehashed(__bucket_count);
679 return iterator(__it, this);
683 insert(const value_type& __obj)
685 size_type __bucket_count = this->bucket_count();
686 _Base_iterator __it = _Base::insert(__obj);
687 _M_check_rehashed(__bucket_count);
688 return iterator(__it, this);
692 insert(const_iterator __hint, const value_type& __obj)
694 __glibcxx_check_insert(__hint);
695 size_type __bucket_count = this->bucket_count();
696 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
697 _M_check_rehashed(__bucket_count);
698 return iterator(__it, this);
701 template<typename _Pair, typename = typename
702 std::enable_if<std::is_constructible<value_type,
703 _Pair&&>::value>::type>
705 insert(_Pair&& __obj)
707 size_type __bucket_count = this->bucket_count();
708 _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
709 _M_check_rehashed(__bucket_count);
710 return iterator(__it, this);
713 template<typename _Pair, typename = typename
714 std::enable_if<std::is_constructible<value_type,
715 _Pair&&>::value>::type>
717 insert(const_iterator __hint, _Pair&& __obj)
719 __glibcxx_check_insert(__hint);
720 size_type __bucket_count = this->bucket_count();
721 _Base_iterator __it =
722 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
723 _M_check_rehashed(__bucket_count);
724 return iterator(__it, this);
728 insert(std::initializer_list<value_type> __l)
729 { _Base::insert(__l); }
731 template<typename _InputIterator>
733 insert(_InputIterator __first, _InputIterator __last)
735 __glibcxx_check_valid_range(__first, __last);
736 size_type __bucket_count = this->bucket_count();
737 _Base::insert(__gnu_debug::__base(__first),
738 __gnu_debug::__base(__last));
739 _M_check_rehashed(__bucket_count);
743 find(const key_type& __key)
744 { return iterator(_Base::find(__key), this); }
747 find(const key_type& __key) const
748 { return const_iterator(_Base::find(__key), this); }
750 std::pair<iterator, iterator>
751 equal_range(const key_type& __key)
753 std::pair<_Base_iterator, _Base_iterator> __res =
754 _Base::equal_range(__key);
755 return std::make_pair(iterator(__res.first, this),
756 iterator(__res.second, this));
759 std::pair<const_iterator, const_iterator>
760 equal_range(const key_type& __key) const
762 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
763 _Base::equal_range(__key);
764 return std::make_pair(const_iterator(__res.first, this),
765 const_iterator(__res.second, this));
769 erase(const key_type& __key)
772 size_type __bucket_count = this->bucket_count();
773 std::pair<_Base_iterator, _Base_iterator> __pair =
774 _Base::equal_range(__key);
775 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
777 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
778 { return __it == __victim; });
779 this->_M_invalidate_local_if(
780 [__victim](_Base_const_local_iterator __it)
781 { return __it._M_curr() == __victim._M_cur; });
782 _Base::erase(__victim++);
785 _M_check_rehashed(__bucket_count);
790 erase(const_iterator __it)
792 __glibcxx_check_erase(__it);
793 _Base_const_iterator __victim = __it.base();
794 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
795 { return __it == __victim; });
796 this->_M_invalidate_local_if(
797 [__victim](_Base_const_local_iterator __it)
798 { return __it._M_curr() == __victim._M_cur; });
799 size_type __bucket_count = this->bucket_count();
800 _Base_iterator __next = _Base::erase(__it.base());
801 _M_check_rehashed(__bucket_count);
802 return iterator(__next, this);
807 { return erase(const_iterator(__it)); }
810 erase(const_iterator __first, const_iterator __last)
812 __glibcxx_check_erase_range(__first, __last);
813 for (_Base_const_iterator __tmp = __first.base();
814 __tmp != __last.base(); ++__tmp)
816 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
817 _M_message(__gnu_debug::__msg_valid_range)
818 ._M_iterator(__first, "first")
819 ._M_iterator(__last, "last"));
820 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
821 { return __it == __tmp; });
822 this->_M_invalidate_local_if(
823 [__tmp](_Base_const_local_iterator __it)
824 { return __it._M_curr() == __tmp._M_cur; });
826 size_type __bucket_count = this->bucket_count();
827 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
828 _M_check_rehashed(__bucket_count);
829 return iterator(__next, this);
833 _M_base() noexcept { return *this; }
836 _M_base() const noexcept { return *this; }
840 _M_check_rehashed(size_type __prev_count)
842 if (__prev_count != this->bucket_count())
843 this->_M_invalidate_locals();
847 template<typename _Key, typename _Tp, typename _Hash,
848 typename _Pred, typename _Alloc>
850 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
851 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
854 template<typename _Key, typename _Tp, typename _Hash,
855 typename _Pred, typename _Alloc>
857 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
858 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
859 { return __x._M_base() == __y._M_base(); }
861 template<typename _Key, typename _Tp, typename _Hash,
862 typename _Pred, typename _Alloc>
864 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
865 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
866 { return !(__x == __y); }
868 } // namespace __debug