1 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
3 // Copyright (C) 2003-2013 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_set
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_UNORDERED_SET
30 #define _GLIBCXX_DEBUG_UNORDERED_SET 1
32 #if __cplusplus < 201103L
33 # include <bits/c++0x_warning.h>
35 # include <unordered_set>
37 #include <debug/safe_unordered_container.h>
38 #include <debug/safe_iterator.h>
39 #include <debug/safe_local_iterator.h>
41 namespace std _GLIBCXX_VISIBILITY(default)
45 /// Class std::unordered_set with safety/checking/debug instrumentation.
46 template<typename _Value,
47 typename _Hash = std::hash<_Value>,
48 typename _Pred = std::equal_to<_Value>,
49 typename _Alloc = std::allocator<_Value> >
51 : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>,
52 public __gnu_debug::_Safe_unordered_container<unordered_set<_Value, _Hash,
55 typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash,
57 typedef __gnu_debug::_Safe_unordered_container<unordered_set> _Safe_base;
58 typedef typename _Base::const_iterator _Base_const_iterator;
59 typedef typename _Base::iterator _Base_iterator;
60 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
61 typedef typename _Base::local_iterator _Base_local_iterator;
64 typedef typename _Base::size_type size_type;
65 typedef typename _Base::hasher hasher;
66 typedef typename _Base::key_equal key_equal;
67 typedef typename _Base::allocator_type allocator_type;
69 typedef typename _Base::key_type key_type;
70 typedef typename _Base::value_type value_type;
72 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
73 unordered_set> iterator;
74 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
75 unordered_set> const_iterator;
76 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
77 unordered_set> local_iterator;
78 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
79 unordered_set> const_local_iterator;
82 unordered_set(size_type __n = 10,
83 const hasher& __hf = hasher(),
84 const key_equal& __eql = key_equal(),
85 const allocator_type& __a = allocator_type())
86 : _Base(__n, __hf, __eql, __a) { }
88 template<typename _InputIterator>
89 unordered_set(_InputIterator __first, _InputIterator __last,
91 const hasher& __hf = hasher(),
92 const key_equal& __eql = key_equal(),
93 const allocator_type& __a = allocator_type())
94 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
96 __gnu_debug::__base(__last), __n,
99 unordered_set(const unordered_set& __x) = default;
101 unordered_set(const _Base& __x)
104 unordered_set(unordered_set&& __x) = default;
106 unordered_set(initializer_list<value_type> __l,
108 const hasher& __hf = hasher(),
109 const key_equal& __eql = key_equal(),
110 const allocator_type& __a = allocator_type())
111 : _Base(__l, __n, __hf, __eql, __a) { }
113 ~unordered_set() noexcept { }
116 operator=(const unordered_set& __x)
118 *static_cast<_Base*>(this) = __x;
119 this->_M_invalidate_all();
124 operator=(unordered_set&& __x)
128 __glibcxx_check_self_move_assign(__x);
135 operator=(initializer_list<value_type> __l)
143 swap(unordered_set& __x)
146 _Safe_base::_M_swap(__x);
153 this->_M_invalidate_all();
158 { return iterator(_Base::begin(), this); }
161 begin() const noexcept
162 { return const_iterator(_Base::begin(), this); }
166 { return iterator(_Base::end(), this); }
170 { return const_iterator(_Base::end(), this); }
173 cbegin() const noexcept
174 { return const_iterator(_Base::begin(), this); }
177 cend() const noexcept
178 { return const_iterator(_Base::end(), this); }
184 __glibcxx_check_bucket_index(__b);
185 return local_iterator(_Base::begin(__b), __b, this);
191 __glibcxx_check_bucket_index(__b);
192 return local_iterator(_Base::end(__b), __b, this);
196 begin(size_type __b) const
198 __glibcxx_check_bucket_index(__b);
199 return const_local_iterator(_Base::begin(__b), __b, this);
203 end(size_type __b) const
205 __glibcxx_check_bucket_index(__b);
206 return const_local_iterator(_Base::end(__b), __b, this);
210 cbegin(size_type __b) const
212 __glibcxx_check_bucket_index(__b);
213 return const_local_iterator(_Base::cbegin(__b), __b, this);
217 cend(size_type __b) const
219 __glibcxx_check_bucket_index(__b);
220 return const_local_iterator(_Base::cend(__b), __b, this);
224 bucket_size(size_type __b) const
226 __glibcxx_check_bucket_index(__b);
227 return _Base::bucket_size(__b);
231 max_load_factor() const noexcept
232 { return _Base::max_load_factor(); }
235 max_load_factor(float __f)
237 __glibcxx_check_max_load_factor(__f);
238 _Base::max_load_factor(__f);
241 template<typename... _Args>
242 std::pair<iterator, bool>
243 emplace(_Args&&... __args)
245 size_type __bucket_count = this->bucket_count();
246 std::pair<_Base_iterator, bool> __res
247 = _Base::emplace(std::forward<_Args>(__args)...);
248 _M_check_rehashed(__bucket_count);
249 return std::make_pair(iterator(__res.first, this), __res.second);
252 template<typename... _Args>
254 emplace_hint(const_iterator __hint, _Args&&... __args)
256 __glibcxx_check_insert(__hint);
257 size_type __bucket_count = this->bucket_count();
258 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
259 std::forward<_Args>(__args)...);
260 _M_check_rehashed(__bucket_count);
261 return iterator(__it, this);
264 std::pair<iterator, bool>
265 insert(const value_type& __obj)
267 size_type __bucket_count = this->bucket_count();
268 typedef std::pair<_Base_iterator, bool> __pair_type;
269 __pair_type __res = _Base::insert(__obj);
270 _M_check_rehashed(__bucket_count);
271 return std::make_pair(iterator(__res.first, this), __res.second);
275 insert(const_iterator __hint, const value_type& __obj)
277 __glibcxx_check_insert(__hint);
278 size_type __bucket_count = this->bucket_count();
279 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
280 _M_check_rehashed(__bucket_count);
281 return iterator(__it, this);
284 std::pair<iterator, bool>
285 insert(value_type&& __obj)
287 size_type __bucket_count = this->bucket_count();
288 typedef std::pair<typename _Base::iterator, bool> __pair_type;
289 __pair_type __res = _Base::insert(std::move(__obj));
290 _M_check_rehashed(__bucket_count);
291 return std::make_pair(iterator(__res.first, this), __res.second);
295 insert(const_iterator __hint, value_type&& __obj)
297 __glibcxx_check_insert(__hint);
298 size_type __bucket_count = this->bucket_count();
299 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
300 _M_check_rehashed(__bucket_count);
301 return iterator(__it, this);
305 insert(std::initializer_list<value_type> __l)
307 size_type __bucket_count = this->bucket_count();
309 _M_check_rehashed(__bucket_count);
312 template<typename _InputIterator>
314 insert(_InputIterator __first, _InputIterator __last)
316 __glibcxx_check_valid_range(__first, __last);
317 size_type __bucket_count = this->bucket_count();
318 _Base::insert(__gnu_debug::__base(__first),
319 __gnu_debug::__base(__last));
320 _M_check_rehashed(__bucket_count);
324 find(const key_type& __key)
325 { return iterator(_Base::find(__key), this); }
328 find(const key_type& __key) const
329 { return const_iterator(_Base::find(__key), this); }
331 std::pair<iterator, iterator>
332 equal_range(const key_type& __key)
334 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
335 __pair_type __res = _Base::equal_range(__key);
336 return std::make_pair(iterator(__res.first, this),
337 iterator(__res.second, this));
340 std::pair<const_iterator, const_iterator>
341 equal_range(const key_type& __key) const
343 std::pair<_Base_const_iterator, _Base_const_iterator>
344 __res = _Base::equal_range(__key);
345 return std::make_pair(const_iterator(__res.first, this),
346 const_iterator(__res.second, this));
350 erase(const key_type& __key)
353 _Base_iterator __victim(_Base::find(__key));
354 if (__victim != _Base::end())
356 this->_M_invalidate_if(
357 [__victim](_Base_const_iterator __it)
358 { return __it == __victim; });
359 this->_M_invalidate_local_if(
360 [__victim](_Base_const_local_iterator __it)
361 { return __it._M_cur == __victim._M_cur; });
362 size_type __bucket_count = this->bucket_count();
363 _Base::erase(__victim);
364 _M_check_rehashed(__bucket_count);
371 erase(const_iterator __it)
373 __glibcxx_check_erase(__it);
374 _Base_const_iterator __victim = __it.base();
375 this->_M_invalidate_if(
376 [__victim](_Base_const_iterator __it)
377 { return __it == __victim; });
378 this->_M_invalidate_local_if(
379 [__victim](_Base_const_local_iterator __it)
380 { return __it._M_cur == __victim._M_cur; });
381 size_type __bucket_count = this->bucket_count();
382 _Base_iterator __next = _Base::erase(__it.base());
383 _M_check_rehashed(__bucket_count);
384 return iterator(__next, this);
389 { return erase(const_iterator(__it)); }
392 erase(const_iterator __first, const_iterator __last)
394 __glibcxx_check_erase_range(__first, __last);
395 for (_Base_const_iterator __tmp = __first.base();
396 __tmp != __last.base(); ++__tmp)
398 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
399 _M_message(__gnu_debug::__msg_valid_range)
400 ._M_iterator(__first, "first")
401 ._M_iterator(__last, "last"));
402 this->_M_invalidate_if(
403 [__tmp](_Base_const_iterator __it)
404 { return __it == __tmp; });
405 this->_M_invalidate_local_if(
406 [__tmp](_Base_const_local_iterator __it)
407 { return __it._M_cur == __tmp._M_cur; });
409 size_type __bucket_count = this->bucket_count();
410 _Base_iterator __next = _Base::erase(__first.base(),
412 _M_check_rehashed(__bucket_count);
413 return iterator(__next, this);
417 _M_base() noexcept { return *this; }
420 _M_base() const noexcept { return *this; }
424 _M_invalidate_locals()
426 _Base_local_iterator __local_end = _Base::end(0);
427 this->_M_invalidate_local_if(
428 [__local_end](_Base_const_local_iterator __it)
429 { return __it != __local_end; });
435 _Base_iterator __end = _Base::end();
436 this->_M_invalidate_if(
437 [__end](_Base_const_iterator __it)
438 { return __it != __end; });
439 _M_invalidate_locals();
443 _M_check_rehashed(size_type __prev_count)
445 if (__prev_count != this->bucket_count())
446 _M_invalidate_locals();
450 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
452 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
453 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
456 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
458 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
459 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
460 { return __x._M_base() == __y._M_base(); }
462 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
464 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
465 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
466 { return !(__x == __y); }
469 /// Class std::unordered_multiset with safety/checking/debug instrumentation.
470 template<typename _Value,
471 typename _Hash = std::hash<_Value>,
472 typename _Pred = std::equal_to<_Value>,
473 typename _Alloc = std::allocator<_Value> >
474 class unordered_multiset
475 : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
476 public __gnu_debug::_Safe_unordered_container<
477 unordered_multiset<_Value, _Hash, _Pred, _Alloc> >
479 typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash,
480 _Pred, _Alloc> _Base;
481 typedef __gnu_debug::_Safe_unordered_container<unordered_multiset>
483 typedef typename _Base::const_iterator _Base_const_iterator;
484 typedef typename _Base::iterator _Base_iterator;
485 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
486 typedef typename _Base::local_iterator _Base_local_iterator;
489 typedef typename _Base::size_type size_type;
490 typedef typename _Base::hasher hasher;
491 typedef typename _Base::key_equal key_equal;
492 typedef typename _Base::allocator_type allocator_type;
494 typedef typename _Base::key_type key_type;
495 typedef typename _Base::value_type value_type;
497 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
498 unordered_multiset> iterator;
499 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
500 unordered_multiset> const_iterator;
501 typedef __gnu_debug::_Safe_local_iterator<
502 _Base_local_iterator, unordered_multiset> local_iterator;
503 typedef __gnu_debug::_Safe_local_iterator<
504 _Base_const_local_iterator, unordered_multiset> const_local_iterator;
507 unordered_multiset(size_type __n = 10,
508 const hasher& __hf = hasher(),
509 const key_equal& __eql = key_equal(),
510 const allocator_type& __a = allocator_type())
511 : _Base(__n, __hf, __eql, __a) { }
513 template<typename _InputIterator>
514 unordered_multiset(_InputIterator __first, _InputIterator __last,
516 const hasher& __hf = hasher(),
517 const key_equal& __eql = key_equal(),
518 const allocator_type& __a = allocator_type())
519 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
521 __gnu_debug::__base(__last), __n,
522 __hf, __eql, __a) { }
524 unordered_multiset(const unordered_multiset& __x) = default;
526 unordered_multiset(const _Base& __x)
529 unordered_multiset(unordered_multiset&& __x) = default;
531 unordered_multiset(initializer_list<value_type> __l,
533 const hasher& __hf = hasher(),
534 const key_equal& __eql = key_equal(),
535 const allocator_type& __a = allocator_type())
536 : _Base(__l, __n, __hf, __eql, __a) { }
538 ~unordered_multiset() noexcept { }
541 operator=(const unordered_multiset& __x)
543 *static_cast<_Base*>(this) = __x;
544 this->_M_invalidate_all();
549 operator=(unordered_multiset&& __x)
553 __glibcxx_check_self_move_assign(__x);
560 operator=(initializer_list<value_type> __l)
568 swap(unordered_multiset& __x)
571 _Safe_base::_M_swap(__x);
578 this->_M_invalidate_all();
583 { return iterator(_Base::begin(), this); }
586 begin() const noexcept
587 { return const_iterator(_Base::begin(), this); }
591 { return iterator(_Base::end(), this); }
595 { return const_iterator(_Base::end(), this); }
598 cbegin() const noexcept
599 { return const_iterator(_Base::begin(), this); }
602 cend() const noexcept
603 { return const_iterator(_Base::end(), this); }
609 __glibcxx_check_bucket_index(__b);
610 return local_iterator(_Base::begin(__b), __b, this);
616 __glibcxx_check_bucket_index(__b);
617 return local_iterator(_Base::end(__b), __b, this);
621 begin(size_type __b) const
623 __glibcxx_check_bucket_index(__b);
624 return const_local_iterator(_Base::begin(__b), __b, this);
628 end(size_type __b) const
630 __glibcxx_check_bucket_index(__b);
631 return const_local_iterator(_Base::end(__b), __b, this);
635 cbegin(size_type __b) const
637 __glibcxx_check_bucket_index(__b);
638 return const_local_iterator(_Base::cbegin(__b), __b, this);
642 cend(size_type __b) const
644 __glibcxx_check_bucket_index(__b);
645 return const_local_iterator(_Base::cend(__b), __b, this);
649 bucket_size(size_type __b) const
651 __glibcxx_check_bucket_index(__b);
652 return _Base::bucket_size(__b);
656 max_load_factor() const noexcept
657 { return _Base::max_load_factor(); }
660 max_load_factor(float __f)
662 __glibcxx_check_max_load_factor(__f);
663 _Base::max_load_factor(__f);
666 template<typename... _Args>
668 emplace(_Args&&... __args)
670 size_type __bucket_count = this->bucket_count();
672 = _Base::emplace(std::forward<_Args>(__args)...);
673 _M_check_rehashed(__bucket_count);
674 return iterator(__it, this);
677 template<typename... _Args>
679 emplace_hint(const_iterator __hint, _Args&&... __args)
681 __glibcxx_check_insert(__hint);
682 size_type __bucket_count = this->bucket_count();
683 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
684 std::forward<_Args>(__args)...);
685 _M_check_rehashed(__bucket_count);
686 return iterator(__it, this);
690 insert(const value_type& __obj)
692 size_type __bucket_count = this->bucket_count();
693 _Base_iterator __it = _Base::insert(__obj);
694 _M_check_rehashed(__bucket_count);
695 return iterator(__it, this);
699 insert(const_iterator __hint, const value_type& __obj)
701 __glibcxx_check_insert(__hint);
702 size_type __bucket_count = this->bucket_count();
703 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
704 _M_check_rehashed(__bucket_count);
705 return iterator(__it, this);
709 insert(value_type&& __obj)
711 size_type __bucket_count = this->bucket_count();
712 _Base_iterator __it = _Base::insert(std::move(__obj));
713 _M_check_rehashed(__bucket_count);
714 return iterator(__it, this);
718 insert(const_iterator __hint, value_type&& __obj)
720 __glibcxx_check_insert(__hint);
721 size_type __bucket_count = this->bucket_count();
722 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
723 _M_check_rehashed(__bucket_count);
724 return iterator(__it, this);
728 insert(std::initializer_list<value_type> __l)
730 size_type __bucket_count = this->bucket_count();
732 _M_check_rehashed(__bucket_count);
735 template<typename _InputIterator>
737 insert(_InputIterator __first, _InputIterator __last)
739 __glibcxx_check_valid_range(__first, __last);
740 size_type __bucket_count = this->bucket_count();
741 _Base::insert(__gnu_debug::__base(__first),
742 __gnu_debug::__base(__last));
743 _M_check_rehashed(__bucket_count);
747 find(const key_type& __key)
748 { return iterator(_Base::find(__key), this); }
751 find(const key_type& __key) const
752 { return const_iterator(_Base::find(__key), this); }
754 std::pair<iterator, iterator>
755 equal_range(const key_type& __key)
757 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
758 __pair_type __res = _Base::equal_range(__key);
759 return std::make_pair(iterator(__res.first, this),
760 iterator(__res.second, this));
763 std::pair<const_iterator, const_iterator>
764 equal_range(const key_type& __key) const
766 std::pair<_Base_const_iterator, _Base_const_iterator>
767 __res = _Base::equal_range(__key);
768 return std::make_pair(const_iterator(__res.first, this),
769 const_iterator(__res.second, this));
773 erase(const key_type& __key)
776 std::pair<_Base_iterator, _Base_iterator> __pair =
777 _Base::equal_range(__key);
778 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
780 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
781 { return __it == __victim; });
782 this->_M_invalidate_local_if(
783 [__victim](_Base_const_local_iterator __it)
784 { return __it._M_cur == __victim._M_cur; });
785 _Base::erase(__victim++);
792 erase(const_iterator __it)
794 __glibcxx_check_erase(__it);
795 _Base_const_iterator __victim = __it.base();
796 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
797 { return __it == __victim; });
798 this->_M_invalidate_local_if(
799 [__victim](_Base_const_local_iterator __it)
800 { return __it._M_cur == __victim._M_cur; });
801 return iterator(_Base::erase(__it.base()), this);
806 { return erase(const_iterator(__it)); }
809 erase(const_iterator __first, const_iterator __last)
811 __glibcxx_check_erase_range(__first, __last);
812 for (_Base_const_iterator __tmp = __first.base();
813 __tmp != __last.base(); ++__tmp)
815 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
816 _M_message(__gnu_debug::__msg_valid_range)
817 ._M_iterator(__first, "first")
818 ._M_iterator(__last, "last"));
819 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
820 { return __it == __tmp; });
821 this->_M_invalidate_local_if(
822 [__tmp](_Base_const_local_iterator __it)
823 { return __it._M_cur == __tmp._M_cur; });
825 return iterator(_Base::erase(__first.base(),
826 __last.base()), this);
830 _M_base() noexcept { return *this; }
833 _M_base() const noexcept { return *this; }
837 _M_invalidate_locals()
839 _Base_local_iterator __local_end = _Base::end(0);
840 this->_M_invalidate_local_if(
841 [__local_end](_Base_const_local_iterator __it)
842 { return __it != __local_end; });
848 _Base_iterator __end = _Base::end();
849 this->_M_invalidate_if([__end](_Base_const_iterator __it)
850 { return __it != __end; });
851 _M_invalidate_locals();
855 _M_check_rehashed(size_type __prev_count)
857 if (__prev_count != this->bucket_count())
858 _M_invalidate_locals();
862 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
864 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
865 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
868 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
870 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
871 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
872 { return __x._M_base() == __y._M_base(); }
874 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
876 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
877 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
878 { return !(__x == __y); }
880 } // namespace __debug