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