1// Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
2
3// Copyright (C) 2003-2021 Free Software Foundation, Inc.
4//
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)
9// any later version.
10
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.
15
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.
19
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/>.
24
25/** @file debug/unordered_set
26 *  This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_UNORDERED_SET
30#define _GLIBCXX_DEBUG_UNORDERED_SET 1
31
32#pragma GCC system_header
33
34#if __cplusplus < 201103L
35# include <bits/c++0x_warning.h>
36#else
37# include <bits/c++config.h>
38namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {
39  template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
40    class unordered_set;
41  template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
42    class unordered_multiset;
43} } // namespace std::__debug
44# include <unordered_set>
45
46#include <debug/safe_unordered_container.h>
47#include <debug/safe_container.h>
48#include <debug/safe_iterator.h>
49#include <debug/safe_local_iterator.h>
50
51namespace std _GLIBCXX_VISIBILITY(default)
52{
53namespace __debug
54{
55  /// Class std::unordered_set with safety/checking/debug instrumentation.
56  template<typename _Value,
57	   typename _Hash = std::hash<_Value>,
58	   typename _Pred = std::equal_to<_Value>,
59	   typename _Alloc = std::allocator<_Value> >
60    class unordered_set
61    : public __gnu_debug::_Safe_container<
62	unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc,
63	__gnu_debug::_Safe_unordered_container>,
64      public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>
65    {
66      typedef _GLIBCXX_STD_C::unordered_set<
67	_Value, _Hash, _Pred, _Alloc>					_Base;
68      typedef __gnu_debug::_Safe_container<
69	unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container>	_Safe;
70
71      typedef typename _Base::const_iterator	   _Base_const_iterator;
72      typedef typename _Base::iterator		   _Base_iterator;
73      typedef typename _Base::const_local_iterator _Base_const_local_iterator;
74      typedef typename _Base::local_iterator	   _Base_local_iterator;
75
76      template<typename _ItT, typename _SeqT, typename _CatT>
77	friend class ::__gnu_debug::_Safe_iterator;
78      template<typename _ItT, typename _SeqT>
79	friend class ::__gnu_debug::_Safe_local_iterator;
80
81      // Reference wrapper for base class. See PR libstdc++/90102.
82      struct _Base_ref
83      {
84	_Base_ref(const _Base& __r) : _M_ref(__r) { }
85
86	const _Base& _M_ref;
87      };
88
89    public:
90      typedef typename _Base::size_type			size_type;
91      typedef typename _Base::hasher			hasher;
92      typedef typename _Base::key_equal			key_equal;
93      typedef typename _Base::allocator_type		allocator_type;
94
95      typedef typename _Base::key_type			key_type;
96      typedef typename _Base::value_type		value_type;
97
98      typedef __gnu_debug::_Safe_iterator<
99	_Base_iterator, unordered_set>			iterator;
100      typedef __gnu_debug::_Safe_iterator<
101	_Base_const_iterator, unordered_set>		const_iterator;
102      typedef __gnu_debug::_Safe_local_iterator<
103	_Base_local_iterator, unordered_set>		local_iterator;
104      typedef __gnu_debug::_Safe_local_iterator<
105	_Base_const_local_iterator, unordered_set>	const_local_iterator;
106
107      unordered_set() = default;
108
109      explicit
110      unordered_set(size_type __n,
111		    const hasher& __hf = hasher(),
112		    const key_equal& __eql = key_equal(),
113		    const allocator_type& __a = allocator_type())
114      : _Base(__n, __hf, __eql, __a) { }
115
116      template<typename _InputIterator>
117	unordered_set(_InputIterator __first, _InputIterator __last,
118		      size_type __n = 0,
119		      const hasher& __hf = hasher(),
120		      const key_equal& __eql = key_equal(),
121		      const allocator_type& __a = allocator_type())
122	: _Base(__gnu_debug::__base(
123		  __glibcxx_check_valid_constructor_range(__first, __last)),
124		__gnu_debug::__base(__last), __n,
125		__hf, __eql, __a) { }
126
127      unordered_set(const unordered_set&) = default;
128
129      unordered_set(_Base_ref __x)
130      : _Base(__x._M_ref) { }
131
132      unordered_set(unordered_set&&) = default;
133
134      explicit
135      unordered_set(const allocator_type& __a)
136      : _Base(__a) { }
137
138      unordered_set(const unordered_set& __uset,
139		    const allocator_type& __a)
140      : _Base(__uset, __a) { }
141
142      unordered_set(unordered_set&& __uset,
143		    const allocator_type& __a)
144      noexcept( noexcept(_Base(std::move(__uset._M_base()), __a)) )
145      : _Safe(std::move(__uset._M_safe()), __a),
146	_Base(std::move(__uset._M_base()), __a) { }
147
148      unordered_set(initializer_list<value_type> __l,
149		    size_type __n = 0,
150		    const hasher& __hf = hasher(),
151		    const key_equal& __eql = key_equal(),
152		    const allocator_type& __a = allocator_type())
153      : _Base(__l, __n, __hf, __eql, __a) { }
154
155      unordered_set(size_type __n, const allocator_type& __a)
156      : unordered_set(__n, hasher(), key_equal(), __a)
157      { }
158
159      unordered_set(size_type __n, const hasher& __hf,
160		    const allocator_type& __a)
161      : unordered_set(__n, __hf, key_equal(), __a)
162      { }
163
164      template<typename _InputIterator>
165	unordered_set(_InputIterator __first, _InputIterator __last,
166		      size_type __n,
167		      const allocator_type& __a)
168	: unordered_set(__first, __last, __n, hasher(), key_equal(), __a)
169	{ }
170
171      template<typename _InputIterator>
172	unordered_set(_InputIterator __first, _InputIterator __last,
173		      size_type __n, const hasher& __hf,
174		      const allocator_type& __a)
175	: unordered_set(__first, __last, __n, __hf, key_equal(), __a)
176	{ }
177
178      unordered_set(initializer_list<value_type> __l,
179		    size_type __n,
180		    const allocator_type& __a)
181      : unordered_set(__l, __n, hasher(), key_equal(), __a)
182      { }
183
184      unordered_set(initializer_list<value_type> __l,
185		    size_type __n, const hasher& __hf,
186		    const allocator_type& __a)
187      : unordered_set(__l, __n, __hf, key_equal(), __a)
188      { }
189
190      ~unordered_set() = default;
191
192      unordered_set&
193      operator=(const unordered_set&) = default;
194
195      unordered_set&
196      operator=(unordered_set&&) = default;
197
198      unordered_set&
199      operator=(initializer_list<value_type> __l)
200      {
201	_M_base() = __l;
202	this->_M_invalidate_all();
203	return *this;
204      }
205
206      void
207      swap(unordered_set& __x)
208	noexcept( noexcept(declval<_Base&>().swap(__x)) )
209      {
210	_Safe::_M_swap(__x);
211	_Base::swap(__x);
212      }
213
214      void
215      clear() noexcept
216      {
217	_Base::clear();
218	this->_M_invalidate_all();
219      }
220
221      iterator
222      begin() noexcept
223      { return { _Base::begin(), this }; }
224
225      const_iterator
226      begin() const noexcept
227      { return { _Base::begin(), this }; }
228
229      iterator
230      end() noexcept
231      { return { _Base::end(), this }; }
232
233      const_iterator
234      end() const noexcept
235      { return { _Base::end(), this }; }
236
237      const_iterator
238      cbegin() const noexcept
239      { return { _Base::cbegin(), this }; }
240
241      const_iterator
242      cend() const noexcept
243      { return { _Base::cend(), this }; }
244
245      // local versions
246      local_iterator
247      begin(size_type __b)
248      {
249	__glibcxx_check_bucket_index(__b);
250	return { _Base::begin(__b), this };
251      }
252
253      local_iterator
254      end(size_type __b)
255      {
256	__glibcxx_check_bucket_index(__b);
257	return { _Base::end(__b), this };
258      }
259
260      const_local_iterator
261      begin(size_type __b) const
262      {
263	__glibcxx_check_bucket_index(__b);
264	return { _Base::begin(__b), this };
265      }
266
267      const_local_iterator
268      end(size_type __b) const
269      {
270	__glibcxx_check_bucket_index(__b);
271	return { _Base::end(__b), this };
272      }
273
274      const_local_iterator
275      cbegin(size_type __b) const
276      {
277	__glibcxx_check_bucket_index(__b);
278	return { _Base::cbegin(__b), this };
279      }
280
281      const_local_iterator
282      cend(size_type __b) const
283      {
284	__glibcxx_check_bucket_index(__b);
285	return { _Base::cend(__b), this };
286      }
287
288      size_type
289      bucket_size(size_type __b) const
290      {
291	__glibcxx_check_bucket_index(__b);
292	return _Base::bucket_size(__b);
293      }
294
295      float
296      max_load_factor() const noexcept
297      { return _Base::max_load_factor(); }
298
299      void
300      max_load_factor(float __f)
301      {
302	__glibcxx_check_max_load_factor(__f);
303	_Base::max_load_factor(__f);
304      }
305
306      template<typename... _Args>
307	std::pair<iterator, bool>
308	emplace(_Args&&... __args)
309	{
310	  size_type __bucket_count = this->bucket_count();
311	  auto __res = _Base::emplace(std::forward<_Args>(__args)...);
312	  _M_check_rehashed(__bucket_count);
313	  return { { __res.first, this }, __res.second };
314	}
315
316      template<typename... _Args>
317	iterator
318	emplace_hint(const_iterator __hint, _Args&&... __args)
319	{
320	  __glibcxx_check_insert(__hint);
321	  size_type __bucket_count = this->bucket_count();
322	  auto __it = _Base::emplace_hint(__hint.base(),
323					  std::forward<_Args>(__args)...);
324	  _M_check_rehashed(__bucket_count);
325	  return { __it, this };
326	}
327
328      std::pair<iterator, bool>
329      insert(const value_type& __obj)
330      {
331	size_type __bucket_count = this->bucket_count();
332	auto __res = _Base::insert(__obj);
333	_M_check_rehashed(__bucket_count);
334	return { { __res.first, this }, __res.second };
335      }
336
337      iterator
338      insert(const_iterator __hint, const value_type& __obj)
339      {
340	__glibcxx_check_insert(__hint);
341	size_type __bucket_count = this->bucket_count();
342	auto __it = _Base::insert(__hint.base(), __obj);
343	_M_check_rehashed(__bucket_count);
344	return { __it, this };
345      }
346
347      std::pair<iterator, bool>
348      insert(value_type&& __obj)
349      {
350	size_type __bucket_count = this->bucket_count();
351	auto __res = _Base::insert(std::move(__obj));
352	_M_check_rehashed(__bucket_count);
353	return { { __res.first, this }, __res.second };
354      }
355
356      iterator
357      insert(const_iterator __hint, value_type&& __obj)
358      {
359	__glibcxx_check_insert(__hint);
360	size_type __bucket_count = this->bucket_count();
361	auto __it = _Base::insert(__hint.base(), std::move(__obj));
362	_M_check_rehashed(__bucket_count);
363	return { __it, this };
364      }
365
366      void
367      insert(std::initializer_list<value_type> __l)
368      {
369	size_type __bucket_count = this->bucket_count();
370	_Base::insert(__l);
371	_M_check_rehashed(__bucket_count);
372      }
373
374      template<typename _InputIterator>
375	void
376	insert(_InputIterator __first, _InputIterator __last)
377	{
378	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
379	  __glibcxx_check_valid_range2(__first, __last, __dist);
380	  size_type __bucket_count = this->bucket_count();
381
382	  if (__dist.second >= __gnu_debug::__dp_sign)
383	    _Base::insert(__gnu_debug::__unsafe(__first),
384			  __gnu_debug::__unsafe(__last));
385	  else
386	    _Base::insert(__first, __last);
387
388	  _M_check_rehashed(__bucket_count);
389	}
390
391#if __cplusplus > 201402L
392      using node_type = typename _Base::node_type;
393      using insert_return_type = _Node_insert_return<iterator, node_type>;
394
395      node_type
396      extract(const_iterator __position)
397      {
398	__glibcxx_check_erase(__position);
399	return _M_extract(__position.base());
400      }
401
402      node_type
403      extract(const key_type& __key)
404      {
405	const auto __position = _Base::find(__key);
406	if (__position != _Base::end())
407	  return _M_extract(__position);
408	return {};
409      }
410
411      insert_return_type
412      insert(node_type&& __nh)
413      {
414	auto __ret = _Base::insert(std::move(__nh));
415	return
416	  { { __ret.position, this }, __ret.inserted, std::move(__ret.node) };
417      }
418
419      iterator
420      insert(const_iterator __hint, node_type&& __nh)
421      {
422	__glibcxx_check_insert(__hint);
423	return { _Base::insert(__hint.base(), std::move(__nh)), this };
424      }
425
426      using _Base::merge;
427#endif // C++17
428
429      iterator
430      find(const key_type& __key)
431      { return { _Base::find(__key), this }; }
432
433#if __cplusplus > 201703L
434      template<typename _Kt,
435	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
436	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
437	iterator
438	find(const _Kt& __k)
439	{ return { _Base::find(__k), this }; }
440#endif
441
442      const_iterator
443      find(const key_type& __key) const
444      { return { _Base::find(__key), this }; }
445
446#if __cplusplus > 201703L
447      template<typename _Kt,
448	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
449	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
450	const_iterator
451	find(const _Kt& __k) const
452	{ return { _Base::find(__k), this }; }
453#endif
454
455      std::pair<iterator, iterator>
456      equal_range(const key_type& __key)
457      {
458	auto __res = _Base::equal_range(__key);
459	return { { __res.first, this }, { __res.second, this } };
460      }
461
462#if __cplusplus > 201703L
463      template<typename _Kt,
464	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
465	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
466	std::pair<iterator, iterator>
467	equal_range(const _Kt& __k)
468	{
469	  auto __res = _Base::equal_range(__k);
470	  return { { __res.first, this }, { __res.second, this } };
471	}
472#endif
473
474      std::pair<const_iterator, const_iterator>
475      equal_range(const key_type& __key) const
476      {
477	auto __res = _Base::equal_range(__key);
478	return { { __res.first, this }, { __res.second, this } };
479      }
480
481#if __cplusplus > 201703L
482      template<typename _Kt,
483	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
484	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
485	std::pair<const_iterator, const_iterator>
486	equal_range(const _Kt& __k) const
487	{
488	  auto __res = _Base::equal_range(__k);
489	  return { { __res.first, this }, { __res.second, this } };
490	}
491#endif
492
493      size_type
494      erase(const key_type& __key)
495      {
496	size_type __ret(0);
497	auto __victim = _Base::find(__key);
498	if (__victim != _Base::end())
499	  {
500	    _M_erase(__victim);
501	    __ret = 1;
502	  }
503	return __ret;
504      }
505
506      iterator
507      erase(const_iterator __it)
508      {
509	__glibcxx_check_erase(__it);
510	return { _M_erase(__it.base()), this };
511      }
512
513      iterator
514      erase(iterator __it)
515      {
516	__glibcxx_check_erase(__it);
517	return { _M_erase(__it.base()), this };
518      }
519
520      iterator
521      erase(const_iterator __first, const_iterator __last)
522      {
523	__glibcxx_check_erase_range(__first, __last);
524	for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
525	  {
526	    _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
527				  _M_message(__gnu_debug::__msg_valid_range)
528				  ._M_iterator(__first, "first")
529				  ._M_iterator(__last, "last"));
530	    _M_invalidate(__tmp);
531	  }
532
533	size_type __bucket_count = this->bucket_count();
534	auto __next = _Base::erase(__first.base(), __last.base());
535	_M_check_rehashed(__bucket_count);
536	return { __next, this };
537      }
538
539      _Base&
540      _M_base() noexcept { return *this; }
541
542      const _Base&
543      _M_base() const noexcept { return *this; }
544
545    private:
546      void
547      _M_check_rehashed(size_type __prev_count)
548      {
549	if (__prev_count != this->bucket_count())
550	  this->_M_invalidate_all();
551      }
552
553      void
554      _M_invalidate(_Base_const_iterator __victim)
555      {
556	this->_M_invalidate_if(
557	  [__victim](_Base_const_iterator __it) { return __it == __victim; });
558	this->_M_invalidate_local_if(
559	  [__victim](_Base_const_local_iterator __it)
560	  { return __it == __victim; });
561      }
562
563      _Base_iterator
564      _M_erase(_Base_const_iterator __victim)
565      {
566	_M_invalidate(__victim);
567	size_type __bucket_count = this->bucket_count();
568	_Base_iterator __next = _Base::erase(__victim);
569	_M_check_rehashed(__bucket_count);
570	return __next;
571      }
572
573#if __cplusplus > 201402L
574      node_type
575      _M_extract(_Base_const_iterator __victim)
576      {
577	_M_invalidate(__victim);
578	return _Base::extract(__victim);
579      }
580#endif
581    };
582
583#if __cpp_deduction_guides >= 201606
584
585  template<typename _InputIterator,
586	   typename _Hash =
587	     hash<typename iterator_traits<_InputIterator>::value_type>,
588	   typename _Pred =
589	     equal_to<typename iterator_traits<_InputIterator>::value_type>,
590	   typename _Allocator =
591	     allocator<typename iterator_traits<_InputIterator>::value_type>,
592	   typename = _RequireInputIter<_InputIterator>,
593	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
594	   typename = _RequireNotAllocator<_Pred>,
595	   typename = _RequireAllocator<_Allocator>>
596    unordered_set(_InputIterator, _InputIterator,
597		  unordered_set<int>::size_type = {},
598		  _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
599    -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
600		     _Hash, _Pred, _Allocator>;
601
602  template<typename _Tp, typename _Hash = hash<_Tp>,
603	   typename _Pred = equal_to<_Tp>,
604	   typename _Allocator = allocator<_Tp>,
605	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
606	   typename = _RequireNotAllocator<_Pred>,
607	   typename = _RequireAllocator<_Allocator>>
608    unordered_set(initializer_list<_Tp>,
609		  unordered_set<int>::size_type = {},
610		  _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
611    -> unordered_set<_Tp, _Hash, _Pred, _Allocator>;
612
613  template<typename _InputIterator, typename _Allocator,
614	   typename = _RequireInputIter<_InputIterator>,
615	   typename = _RequireAllocator<_Allocator>>
616    unordered_set(_InputIterator, _InputIterator,
617		  unordered_set<int>::size_type, _Allocator)
618    -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
619		     hash<
620		       typename iterator_traits<_InputIterator>::value_type>,
621		     equal_to<
622		       typename iterator_traits<_InputIterator>::value_type>,
623		     _Allocator>;
624
625  template<typename _InputIterator, typename _Hash, typename _Allocator,
626	   typename = _RequireInputIter<_InputIterator>,
627	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
628	   typename = _RequireAllocator<_Allocator>>
629    unordered_set(_InputIterator, _InputIterator,
630		  unordered_set<int>::size_type,
631		  _Hash, _Allocator)
632    -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
633		     _Hash,
634		     equal_to<
635		       typename iterator_traits<_InputIterator>::value_type>,
636		     _Allocator>;
637
638  template<typename _Tp, typename _Allocator,
639	   typename = _RequireAllocator<_Allocator>>
640    unordered_set(initializer_list<_Tp>,
641		  unordered_set<int>::size_type, _Allocator)
642    -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
643
644  template<typename _Tp, typename _Hash, typename _Allocator,
645	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
646	   typename = _RequireAllocator<_Allocator>>
647    unordered_set(initializer_list<_Tp>,
648		  unordered_set<int>::size_type, _Hash, _Allocator)
649    -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
650
651#endif
652
653  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
654    inline void
655    swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
656	 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
657    noexcept(noexcept(__x.swap(__y)))
658    { __x.swap(__y); }
659
660  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
661    inline bool
662    operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
663	       const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
664    { return __x._M_base() == __y._M_base(); }
665
666#if __cpp_impl_three_way_comparison < 201907L
667  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
668    inline bool
669    operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
670	       const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
671    { return !(__x == __y); }
672#endif
673
674  /// Class std::unordered_multiset with safety/checking/debug instrumentation.
675  template<typename _Value,
676	   typename _Hash = std::hash<_Value>,
677	   typename _Pred = std::equal_to<_Value>,
678	   typename _Alloc = std::allocator<_Value> >
679    class unordered_multiset
680    : public __gnu_debug::_Safe_container<
681	unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc,
682	__gnu_debug::_Safe_unordered_container>,
683      public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>
684    {
685      typedef _GLIBCXX_STD_C::unordered_multiset<
686	_Value, _Hash, _Pred, _Alloc>				_Base;
687      typedef __gnu_debug::_Safe_container<unordered_multiset,
688	_Alloc, __gnu_debug::_Safe_unordered_container>		_Safe;
689      typedef typename _Base::const_iterator	_Base_const_iterator;
690      typedef typename _Base::iterator		_Base_iterator;
691      typedef typename _Base::const_local_iterator
692						_Base_const_local_iterator;
693      typedef typename _Base::local_iterator	_Base_local_iterator;
694
695      template<typename _ItT, typename _SeqT, typename _CatT>
696	friend class ::__gnu_debug::_Safe_iterator;
697      template<typename _ItT, typename _SeqT>
698	friend class ::__gnu_debug::_Safe_local_iterator;
699
700      // Reference wrapper for base class. See PR libstdc++/90102.
701      struct _Base_ref
702      {
703	_Base_ref(const _Base& __r) : _M_ref(__r) { }
704
705	const _Base& _M_ref;
706      };
707
708    public:
709      typedef typename _Base::size_type			size_type;
710      typedef typename _Base::hasher			hasher;
711      typedef typename _Base::key_equal			key_equal;
712      typedef typename _Base::allocator_type		allocator_type;
713
714      typedef typename _Base::key_type			key_type;
715      typedef typename _Base::value_type		value_type;
716
717      typedef __gnu_debug::_Safe_iterator<
718	_Base_iterator, unordered_multiset>		iterator;
719      typedef __gnu_debug::_Safe_iterator<
720	_Base_const_iterator, unordered_multiset>	const_iterator;
721      typedef __gnu_debug::_Safe_local_iterator<
722	_Base_local_iterator, unordered_multiset>	local_iterator;
723      typedef __gnu_debug::_Safe_local_iterator<
724	_Base_const_local_iterator, unordered_multiset>	const_local_iterator;
725
726      unordered_multiset() = default;
727
728      explicit
729      unordered_multiset(size_type __n,
730			 const hasher& __hf = hasher(),
731			 const key_equal& __eql = key_equal(),
732			 const allocator_type& __a = allocator_type())
733      : _Base(__n, __hf, __eql, __a) { }
734
735      template<typename _InputIterator>
736	unordered_multiset(_InputIterator __first, _InputIterator __last,
737			   size_type __n = 0,
738			   const hasher& __hf = hasher(),
739			   const key_equal& __eql = key_equal(),
740			   const allocator_type& __a = allocator_type())
741	: _Base(__gnu_debug::__base(
742		  __glibcxx_check_valid_constructor_range(__first, __last)),
743		__gnu_debug::__base(__last), __n,
744		__hf, __eql, __a) { }
745
746      unordered_multiset(const unordered_multiset&) = default;
747
748      unordered_multiset(_Base_ref __x)
749      : _Base(__x._M_ref) { }
750
751      unordered_multiset(unordered_multiset&&) = default;
752
753      explicit
754      unordered_multiset(const allocator_type& __a)
755      : _Base(__a) { }
756
757      unordered_multiset(const unordered_multiset& __uset,
758			 const allocator_type& __a)
759      : _Base(__uset, __a) { }
760
761      unordered_multiset(unordered_multiset&& __uset,
762			 const allocator_type& __a)
763      noexcept( noexcept(_Base(std::move(__uset._M_base()), __a)) )
764      : _Safe(std::move(__uset._M_safe()), __a),
765	_Base(std::move(__uset._M_base()), __a) { }
766
767      unordered_multiset(initializer_list<value_type> __l,
768			 size_type __n = 0,
769			 const hasher& __hf = hasher(),
770			 const key_equal& __eql = key_equal(),
771			 const allocator_type& __a = allocator_type())
772      : _Base(__l, __n, __hf, __eql, __a) { }
773
774      unordered_multiset(size_type __n, const allocator_type& __a)
775      : unordered_multiset(__n, hasher(), key_equal(), __a)
776      { }
777
778      unordered_multiset(size_type __n, const hasher& __hf,
779			 const allocator_type& __a)
780      : unordered_multiset(__n, __hf, key_equal(), __a)
781      { }
782
783      template<typename _InputIterator>
784	unordered_multiset(_InputIterator __first, _InputIterator __last,
785			   size_type __n,
786			   const allocator_type& __a)
787	: unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a)
788	{ }
789
790      template<typename _InputIterator>
791	unordered_multiset(_InputIterator __first, _InputIterator __last,
792			   size_type __n, const hasher& __hf,
793			   const allocator_type& __a)
794	: unordered_multiset(__first, __last, __n, __hf, key_equal(), __a)
795	{ }
796
797      unordered_multiset(initializer_list<value_type> __l,
798			 size_type __n,
799			 const allocator_type& __a)
800      : unordered_multiset(__l, __n, hasher(), key_equal(), __a)
801      { }
802
803      unordered_multiset(initializer_list<value_type> __l,
804			 size_type __n, const hasher& __hf,
805			 const allocator_type& __a)
806      : unordered_multiset(__l, __n, __hf, key_equal(), __a)
807      { }
808
809      ~unordered_multiset() = default;
810
811      unordered_multiset&
812      operator=(const unordered_multiset&) = default;
813
814      unordered_multiset&
815      operator=(unordered_multiset&&) = default;
816
817      unordered_multiset&
818      operator=(initializer_list<value_type> __l)
819      {
820	this->_M_base() = __l;
821	this->_M_invalidate_all();
822	return *this;
823      }
824
825      void
826      swap(unordered_multiset& __x)
827	noexcept( noexcept(declval<_Base&>().swap(__x)) )
828      {
829	_Safe::_M_swap(__x);
830	_Base::swap(__x);
831      }
832
833      void
834      clear() noexcept
835      {
836	_Base::clear();
837	this->_M_invalidate_all();
838      }
839
840      iterator
841      begin() noexcept
842      { return { _Base::begin(), this }; }
843
844      const_iterator
845      begin() const noexcept
846      { return { _Base::begin(), this }; }
847
848      iterator
849      end() noexcept
850      { return { _Base::end(), this }; }
851
852      const_iterator
853      end() const noexcept
854      { return { _Base::end(), this }; }
855
856      const_iterator
857      cbegin() const noexcept
858      { return { _Base::cbegin(), this }; }
859
860      const_iterator
861      cend() const noexcept
862      { return { _Base::cend(), this }; }
863
864      // local versions
865      local_iterator
866      begin(size_type __b)
867      {
868	__glibcxx_check_bucket_index(__b);
869	return { _Base::begin(__b), this };
870      }
871
872      local_iterator
873      end(size_type __b)
874      {
875	__glibcxx_check_bucket_index(__b);
876	return { _Base::end(__b), this };
877      }
878
879      const_local_iterator
880      begin(size_type __b) const
881      {
882	__glibcxx_check_bucket_index(__b);
883	return { _Base::begin(__b), this };
884      }
885
886      const_local_iterator
887      end(size_type __b) const
888      {
889	__glibcxx_check_bucket_index(__b);
890	return { _Base::end(__b), this };
891      }
892
893      const_local_iterator
894      cbegin(size_type __b) const
895      {
896	__glibcxx_check_bucket_index(__b);
897	return { _Base::cbegin(__b), this };
898      }
899
900      const_local_iterator
901      cend(size_type __b) const
902      {
903	__glibcxx_check_bucket_index(__b);
904	return { _Base::cend(__b), this };
905      }
906
907      size_type
908      bucket_size(size_type __b) const
909      {
910	__glibcxx_check_bucket_index(__b);
911	return _Base::bucket_size(__b);
912      }
913
914      float
915      max_load_factor() const noexcept
916      { return _Base::max_load_factor(); }
917
918      void
919      max_load_factor(float __f)
920      {
921	__glibcxx_check_max_load_factor(__f);
922	_Base::max_load_factor(__f);
923      }
924
925      template<typename... _Args>
926	iterator
927	emplace(_Args&&... __args)
928	{
929	  size_type __bucket_count = this->bucket_count();
930	  auto __it = _Base::emplace(std::forward<_Args>(__args)...);
931	  _M_check_rehashed(__bucket_count);
932	  return { __it, this };
933	}
934
935      template<typename... _Args>
936	iterator
937	emplace_hint(const_iterator __hint, _Args&&... __args)
938	{
939	  __glibcxx_check_insert(__hint);
940	  size_type __bucket_count = this->bucket_count();
941	  auto __it = _Base::emplace_hint(__hint.base(),
942					  std::forward<_Args>(__args)...);
943	  _M_check_rehashed(__bucket_count);
944	  return { __it, this };
945	}
946
947      iterator
948      insert(const value_type& __obj)
949      {
950	size_type __bucket_count = this->bucket_count();
951	auto __it = _Base::insert(__obj);
952	_M_check_rehashed(__bucket_count);
953	return { __it, this };
954      }
955
956      iterator
957      insert(const_iterator __hint, const value_type& __obj)
958      {
959	__glibcxx_check_insert(__hint);
960	size_type __bucket_count = this->bucket_count();
961	auto __it = _Base::insert(__hint.base(), __obj);
962	_M_check_rehashed(__bucket_count);
963	return { __it, this };
964      }
965
966      iterator
967      insert(value_type&& __obj)
968      {
969	size_type __bucket_count = this->bucket_count();
970	auto __it = _Base::insert(std::move(__obj));
971	_M_check_rehashed(__bucket_count);
972	return { __it, this };
973      }
974
975      iterator
976      insert(const_iterator __hint, value_type&& __obj)
977      {
978	__glibcxx_check_insert(__hint);
979	size_type __bucket_count = this->bucket_count();
980	auto __it = _Base::insert(__hint.base(), std::move(__obj));
981	_M_check_rehashed(__bucket_count);
982	return { __it, this };
983      }
984
985      void
986      insert(std::initializer_list<value_type> __l)
987      {
988	size_type __bucket_count = this->bucket_count();
989	_Base::insert(__l);
990	_M_check_rehashed(__bucket_count);
991      }
992
993      template<typename _InputIterator>
994	void
995	insert(_InputIterator __first, _InputIterator __last)
996	{
997	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
998	  __glibcxx_check_valid_range2(__first, __last, __dist);
999	  size_type __bucket_count = this->bucket_count();
1000
1001	  if (__dist.second >= __gnu_debug::__dp_sign)
1002	    _Base::insert(__gnu_debug::__unsafe(__first),
1003			  __gnu_debug::__unsafe(__last));
1004	  else
1005	    _Base::insert(__first, __last);
1006
1007	  _M_check_rehashed(__bucket_count);
1008	}
1009
1010#if __cplusplus > 201402L
1011      using node_type = typename _Base::node_type;
1012
1013      node_type
1014      extract(const_iterator __position)
1015      {
1016	__glibcxx_check_erase(__position);
1017	return _M_extract(__position.base());
1018      }
1019
1020      node_type
1021      extract(const key_type& __key)
1022      {
1023	const auto __position = _Base::find(__key);
1024	if (__position != _Base::end())
1025	  return _M_extract(__position);
1026	return {};
1027      }
1028
1029      iterator
1030      insert(node_type&& __nh)
1031      { return { _Base::insert(std::move(__nh)), this }; }
1032
1033      iterator
1034      insert(const_iterator __hint, node_type&& __nh)
1035      {
1036	__glibcxx_check_insert(__hint);
1037	return { _Base::insert(__hint.base(), std::move(__nh)), this };
1038      }
1039
1040      using _Base::merge;
1041#endif // C++17
1042
1043      iterator
1044      find(const key_type& __key)
1045      { return { _Base::find(__key), this }; }
1046
1047#if __cplusplus > 201703L
1048      template<typename _Kt,
1049	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
1050	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
1051	iterator
1052	find(const _Kt& __k)
1053	{ return { _Base::find(__k), this }; }
1054#endif
1055
1056      const_iterator
1057      find(const key_type& __key) const
1058      { return { _Base::find(__key), this }; }
1059
1060#if __cplusplus > 201703L
1061      template<typename _Kt,
1062	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
1063	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
1064	const_iterator
1065	find(const _Kt& __k) const
1066	{ return { _Base::find(__k), this }; }
1067#endif
1068
1069      std::pair<iterator, iterator>
1070      equal_range(const key_type& __key)
1071      {
1072	auto __res = _Base::equal_range(__key);
1073	return { { __res.first, this }, { __res.second, this } };
1074      }
1075
1076#if __cplusplus > 201703L
1077      template<typename _Kt,
1078	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
1079	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
1080	std::pair<iterator, iterator>
1081	equal_range(const _Kt& __k)
1082	{
1083	  auto __res = _Base::equal_range(__k);
1084	  return { { __res.first, this }, { __res.second, this } };
1085	}
1086#endif
1087
1088      std::pair<const_iterator, const_iterator>
1089      equal_range(const key_type& __key) const
1090      {
1091	auto __res = _Base::equal_range(__key);
1092	return { { __res.first, this }, { __res.second, this } };
1093      }
1094
1095#if __cplusplus > 201703L
1096      template<typename _Kt,
1097	       typename = std::__has_is_transparent_t<_Hash, _Kt>,
1098	       typename = std::__has_is_transparent_t<_Pred, _Kt>>
1099	std::pair<const_iterator, const_iterator>
1100	equal_range(const _Kt& __k) const
1101	{
1102	  auto __res = _Base::equal_range(__k);
1103	  return { { __res.first, this }, { __res.second, this } };
1104	}
1105#endif
1106
1107      size_type
1108      erase(const key_type& __key)
1109      {
1110	size_type __ret(0);
1111	auto __pair = _Base::equal_range(__key);
1112	for (auto __victim = __pair.first; __victim != __pair.second;)
1113	  {
1114	    _M_invalidate(__victim);
1115	    __victim = _Base::erase(__victim);
1116	    ++__ret;
1117	  }
1118
1119	return __ret;
1120      }
1121
1122      iterator
1123      erase(const_iterator __it)
1124      {
1125	__glibcxx_check_erase(__it);
1126	return { _M_erase(__it.base()), this };
1127      }
1128
1129      iterator
1130      erase(iterator __it)
1131      {
1132	__glibcxx_check_erase(__it);
1133	return { _M_erase(__it.base()), this };
1134      }
1135
1136      iterator
1137      erase(const_iterator __first, const_iterator __last)
1138      {
1139	__glibcxx_check_erase_range(__first, __last);
1140	for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
1141	  {
1142	    _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
1143				  _M_message(__gnu_debug::__msg_valid_range)
1144				  ._M_iterator(__first, "first")
1145				  ._M_iterator(__last, "last"));
1146	    _M_invalidate(__tmp);
1147	  }
1148	return { _Base::erase(__first.base(), __last.base()), this };
1149      }
1150
1151      _Base&
1152      _M_base() noexcept	{ return *this; }
1153
1154      const _Base&
1155      _M_base() const noexcept	{ return *this; }
1156
1157    private:
1158      void
1159      _M_check_rehashed(size_type __prev_count)
1160      {
1161	if (__prev_count != this->bucket_count())
1162	  this->_M_invalidate_all();
1163      }
1164
1165      void
1166      _M_invalidate(_Base_const_iterator __victim)
1167      {
1168	this->_M_invalidate_if(
1169	  [__victim](_Base_const_iterator __it) { return __it == __victim; });
1170	this->_M_invalidate_local_if(
1171	  [__victim](_Base_const_local_iterator __it)
1172	  { return __it == __victim; });
1173      }
1174
1175      _Base_iterator
1176      _M_erase(_Base_const_iterator __victim)
1177      {
1178	_M_invalidate(__victim);
1179	size_type __bucket_count = this->bucket_count();
1180	_Base_iterator __next = _Base::erase(__victim);
1181	_M_check_rehashed(__bucket_count);
1182	return __next;
1183      }
1184
1185#if __cplusplus > 201402L
1186      node_type
1187      _M_extract(_Base_const_iterator __victim)
1188      {
1189	_M_invalidate(__victim);
1190	return _Base::extract(__victim);
1191      }
1192#endif
1193    };
1194
1195#if __cpp_deduction_guides >= 201606
1196
1197  template<typename _InputIterator,
1198	   typename _Hash =
1199	     hash<typename iterator_traits<_InputIterator>::value_type>,
1200	   typename _Pred =
1201	     equal_to<typename iterator_traits<_InputIterator>::value_type>,
1202	   typename _Allocator =
1203	     allocator<typename iterator_traits<_InputIterator>::value_type>,
1204	   typename = _RequireInputIter<_InputIterator>,
1205	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
1206	   typename = _RequireNotAllocator<_Pred>,
1207	   typename = _RequireAllocator<_Allocator>>
1208    unordered_multiset(_InputIterator, _InputIterator,
1209		       unordered_multiset<int>::size_type = {},
1210		       _Hash = _Hash(), _Pred = _Pred(),
1211		       _Allocator = _Allocator())
1212    -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1213			  _Hash, _Pred, _Allocator>;
1214
1215  template<typename _Tp, typename _Hash = hash<_Tp>,
1216	   typename _Pred = equal_to<_Tp>,
1217	   typename _Allocator = allocator<_Tp>,
1218	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
1219	   typename = _RequireNotAllocator<_Pred>,
1220	   typename = _RequireAllocator<_Allocator>>
1221    unordered_multiset(initializer_list<_Tp>,
1222		       unordered_multiset<int>::size_type = {},
1223		       _Hash = _Hash(), _Pred = _Pred(),
1224		       _Allocator = _Allocator())
1225    -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>;
1226
1227  template<typename _InputIterator, typename _Allocator,
1228	   typename = _RequireInputIter<_InputIterator>,
1229	   typename = _RequireAllocator<_Allocator>>
1230    unordered_multiset(_InputIterator, _InputIterator,
1231		       unordered_multiset<int>::size_type, _Allocator)
1232    -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1233			  hash<typename
1234			       iterator_traits<_InputIterator>::value_type>,
1235			  equal_to<typename
1236				   iterator_traits<_InputIterator>::value_type>,
1237			  _Allocator>;
1238
1239  template<typename _InputIterator, typename _Hash, typename _Allocator,
1240	   typename = _RequireInputIter<_InputIterator>,
1241	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
1242	   typename = _RequireAllocator<_Allocator>>
1243    unordered_multiset(_InputIterator, _InputIterator,
1244		       unordered_multiset<int>::size_type,
1245		       _Hash, _Allocator)
1246    -> unordered_multiset<typename
1247			  iterator_traits<_InputIterator>::value_type,
1248			  _Hash,
1249			  equal_to<
1250			    typename
1251			    iterator_traits<_InputIterator>::value_type>,
1252			  _Allocator>;
1253
1254  template<typename _Tp, typename _Allocator,
1255	   typename = _RequireAllocator<_Allocator>>
1256    unordered_multiset(initializer_list<_Tp>,
1257		       unordered_multiset<int>::size_type, _Allocator)
1258    -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
1259
1260  template<typename _Tp, typename _Hash, typename _Allocator,
1261	   typename = _RequireNotAllocatorOrIntegral<_Hash>,
1262	   typename = _RequireAllocator<_Allocator>>
1263    unordered_multiset(initializer_list<_Tp>,
1264		       unordered_multiset<int>::size_type, _Hash, _Allocator)
1265    -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
1266
1267#endif
1268
1269  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1270    inline void
1271    swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1272	 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1273    noexcept(noexcept(__x.swap(__y)))
1274    { __x.swap(__y); }
1275
1276  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1277    inline bool
1278    operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1279	       const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1280    { return __x._M_base() == __y._M_base(); }
1281
1282#if __cpp_impl_three_way_comparison < 201907L
1283  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1284    inline bool
1285    operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1286	       const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1287    { return !(__x == __y); }
1288#endif
1289
1290} // namespace __debug
1291} // namespace std
1292
1293#endif // C++11
1294
1295#endif
1296