xref: /freebsd/contrib/llvm-project/libcxx/include/ext/hash_set (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_HASH_SET
11#define _LIBCPP_HASH_SET
12
13/*
14
15    hash_set synopsis
16
17namespace __gnu_cxx
18{
19
20template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
21          class Alloc = allocator<Value>>
22class hash_set
23{
24public:
25    // types
26    typedef Value                                                      key_type;
27    typedef key_type                                                   value_type;
28    typedef Hash                                                       hasher;
29    typedef Pred                                                       key_equal;
30    typedef Alloc                                                      allocator_type;
31    typedef value_type&                                                reference;
32    typedef const value_type&                                          const_reference;
33    typedef typename allocator_traits<allocator_type>::pointer         pointer;
34    typedef typename allocator_traits<allocator_type>::const_pointer   const_pointer;
35    typedef typename allocator_traits<allocator_type>::size_type       size_type;
36    typedef typename allocator_traits<allocator_type>::difference_type difference_type;
37
38    typedef /unspecified/ iterator;
39    typedef /unspecified/ const_iterator;
40
41    explicit hash_set(size_type n = 193, const hasher& hf = hasher(),
42                           const key_equal& eql = key_equal(),
43                           const allocator_type& a = allocator_type());
44    template <class InputIterator>
45        hash_set(InputIterator f, InputIterator l,
46                      size_type n = 193, const hasher& hf = hasher(),
47                      const key_equal& eql = key_equal(),
48                      const allocator_type& a = allocator_type());
49    hash_set(const hash_set&);
50    ~hash_set();
51    hash_set& operator=(const hash_set&);
52
53    allocator_type get_allocator() const;
54
55    bool      empty() const;
56    size_type size() const;
57    size_type max_size() const;
58
59    iterator       begin();
60    iterator       end();
61    const_iterator begin()  const;
62    const_iterator end()    const;
63
64    pair<iterator, bool> insert(const value_type& obj);
65    template <class InputIterator>
66        void insert(InputIterator first, InputIterator last);
67
68    void erase(const_iterator position);
69    size_type erase(const key_type& k);
70    void erase(const_iterator first, const_iterator last);
71    void clear();
72
73    void swap(hash_set&);
74
75    hasher hash_funct() const;
76    key_equal key_eq() const;
77
78    iterator       find(const key_type& k);
79    const_iterator find(const key_type& k) const;
80    size_type count(const key_type& k) const;
81    pair<iterator, iterator>             equal_range(const key_type& k);
82    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
83
84    size_type bucket_count() const;
85    size_type max_bucket_count() const;
86
87    size_type elems_in_bucket(size_type n) const;
88
89    void resize(size_type n);
90};
91
92template <class Value, class Hash, class Pred, class Alloc>
93    void swap(hash_set<Value, Hash, Pred, Alloc>& x,
94              hash_set<Value, Hash, Pred, Alloc>& y);
95
96template <class Value, class Hash, class Pred, class Alloc>
97    bool
98    operator==(const hash_set<Value, Hash, Pred, Alloc>& x,
99               const hash_set<Value, Hash, Pred, Alloc>& y);
100
101template <class Value, class Hash, class Pred, class Alloc>
102    bool
103    operator!=(const hash_set<Value, Hash, Pred, Alloc>& x,
104               const hash_set<Value, Hash, Pred, Alloc>& y);
105
106template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
107          class Alloc = allocator<Value>>
108class hash_multiset
109{
110public:
111    // types
112    typedef Value                                                      key_type;
113    typedef key_type                                                   value_type;
114    typedef Hash                                                       hasher;
115    typedef Pred                                                       key_equal;
116    typedef Alloc                                                      allocator_type;
117    typedef value_type&                                                reference;
118    typedef const value_type&                                          const_reference;
119    typedef typename allocator_traits<allocator_type>::pointer         pointer;
120    typedef typename allocator_traits<allocator_type>::const_pointer   const_pointer;
121    typedef typename allocator_traits<allocator_type>::size_type       size_type;
122    typedef typename allocator_traits<allocator_type>::difference_type difference_type;
123
124    typedef /unspecified/ iterator;
125    typedef /unspecified/ const_iterator;
126
127    explicit hash_multiset(size_type n = 193, const hasher& hf = hasher(),
128                           const key_equal& eql = key_equal(),
129                           const allocator_type& a = allocator_type());
130    template <class InputIterator>
131        hash_multiset(InputIterator f, InputIterator l,
132                      size_type n = 193, const hasher& hf = hasher(),
133                      const key_equal& eql = key_equal(),
134                      const allocator_type& a = allocator_type());
135    hash_multiset(const hash_multiset&);
136    ~hash_multiset();
137    hash_multiset& operator=(const hash_multiset&);
138
139    allocator_type get_allocator() const;
140
141    bool      empty() const;
142    size_type size() const;
143    size_type max_size() const;
144
145    iterator       begin();
146    iterator       end();
147    const_iterator begin()  const;
148    const_iterator end()    const;
149
150    iterator insert(const value_type& obj);
151    template <class InputIterator>
152        void insert(InputIterator first, InputIterator last);
153
154    void erase(const_iterator position);
155    size_type erase(const key_type& k);
156    void erase(const_iterator first, const_iterator last);
157    void clear();
158
159    void swap(hash_multiset&);
160
161    hasher hash_funct() const;
162    key_equal key_eq() const;
163
164    iterator       find(const key_type& k);
165    const_iterator find(const key_type& k) const;
166    size_type count(const key_type& k) const;
167    pair<iterator, iterator>             equal_range(const key_type& k);
168    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
169
170    size_type bucket_count() const;
171    size_type max_bucket_count() const;
172
173    size_type elems_in_bucket(size_type n) const;
174
175    void resize(size_type n);
176};
177
178template <class Value, class Hash, class Pred, class Alloc>
179    void swap(hash_multiset<Value, Hash, Pred, Alloc>& x,
180              hash_multiset<Value, Hash, Pred, Alloc>& y);
181
182template <class Value, class Hash, class Pred, class Alloc>
183    bool
184    operator==(const hash_multiset<Value, Hash, Pred, Alloc>& x,
185               const hash_multiset<Value, Hash, Pred, Alloc>& y);
186
187template <class Value, class Hash, class Pred, class Alloc>
188    bool
189    operator!=(const hash_multiset<Value, Hash, Pred, Alloc>& x,
190               const hash_multiset<Value, Hash, Pred, Alloc>& y);
191}  // __gnu_cxx
192
193*/
194
195#include <__assert> // all public C++ headers provide the assertion handler
196#include <__config>
197#include <__hash_table>
198#include <algorithm>
199#include <ext/__hash>
200#include <functional>
201
202#if defined(__DEPRECATED) && __DEPRECATED
203#  if defined(_LIBCPP_WARNING)
204_LIBCPP_WARNING("Use of the header <ext/hash_set> is deprecated.  Migrate to <unordered_set>")
205#  else
206#    warning Use of the header <ext/hash_set> is deprecated.  Migrate to <unordered_set>
207#  endif
208#endif
209
210#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
211#  pragma GCC system_header
212#endif
213
214namespace __gnu_cxx {
215
216template <class _Value,
217          class _Hash  = hash<_Value>,
218          class _Pred  = std::equal_to<_Value>,
219          class _Alloc = std::allocator<_Value> >
220class _LIBCPP_TEMPLATE_VIS hash_set {
221public:
222  // types
223  typedef _Value key_type;
224  typedef key_type value_type;
225  typedef _Hash hasher;
226  typedef _Pred key_equal;
227  typedef _Alloc allocator_type;
228  typedef value_type& reference;
229  typedef const value_type& const_reference;
230
231private:
232  typedef std::__hash_table<value_type, hasher, key_equal, allocator_type> __table;
233
234  __table __table_;
235
236public:
237  typedef typename __table::pointer pointer;
238  typedef typename __table::const_pointer const_pointer;
239  typedef typename __table::size_type size_type;
240  typedef typename __table::difference_type difference_type;
241
242  typedef typename __table::const_iterator iterator;
243  typedef typename __table::const_iterator const_iterator;
244
245  _LIBCPP_HIDE_FROM_ABI hash_set() {}
246  _LIBCPP_HIDE_FROM_ABI explicit hash_set(
247      size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal());
248  _LIBCPP_HIDE_FROM_ABI hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
249  template <class _InputIterator>
250  _LIBCPP_HIDE_FROM_ABI hash_set(_InputIterator __first, _InputIterator __last);
251  template <class _InputIterator>
252  _LIBCPP_HIDE_FROM_ABI
253  hash_set(_InputIterator __first,
254           _InputIterator __last,
255           size_type __n,
256           const hasher& __hf     = hasher(),
257           const key_equal& __eql = key_equal());
258  template <class _InputIterator>
259  _LIBCPP_HIDE_FROM_ABI
260  hash_set(_InputIterator __first,
261           _InputIterator __last,
262           size_type __n,
263           const hasher& __hf,
264           const key_equal& __eql,
265           const allocator_type& __a);
266  _LIBCPP_HIDE_FROM_ABI hash_set(const hash_set& __u);
267
268  _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return allocator_type(__table_.__node_alloc()); }
269
270  _LIBCPP_HIDE_FROM_ABI bool empty() const { return __table_.size() == 0; }
271  _LIBCPP_HIDE_FROM_ABI size_type size() const { return __table_.size(); }
272  _LIBCPP_HIDE_FROM_ABI size_type max_size() const { return __table_.max_size(); }
273
274  _LIBCPP_HIDE_FROM_ABI iterator begin() { return __table_.begin(); }
275  _LIBCPP_HIDE_FROM_ABI iterator end() { return __table_.end(); }
276  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return __table_.begin(); }
277  _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __table_.end(); }
278
279  _LIBCPP_HIDE_FROM_ABI std::pair<iterator, bool> insert(const value_type& __x) {
280    return __table_.__insert_unique(__x);
281  }
282  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x).first; }
283  template <class _InputIterator>
284  _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last);
285
286  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __p) { __table_.erase(__p); }
287  _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_unique(__k); }
288  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __first, const_iterator __last) { __table_.erase(__first, __last); }
289  _LIBCPP_HIDE_FROM_ABI void clear() { __table_.clear(); }
290
291  _LIBCPP_HIDE_FROM_ABI void swap(hash_set& __u) { __table_.swap(__u.__table_); }
292
293  _LIBCPP_HIDE_FROM_ABI hasher hash_funct() const { return __table_.hash_function(); }
294  _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq(); }
295
296  _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
297  _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
298  _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_unique(__k); }
299  _LIBCPP_HIDE_FROM_ABI std::pair<iterator, iterator> equal_range(const key_type& __k) {
300    return __table_.__equal_range_unique(__k);
301  }
302  _LIBCPP_HIDE_FROM_ABI std::pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
303    return __table_.__equal_range_unique(__k);
304  }
305
306  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const { return __table_.bucket_count(); }
307  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const { return __table_.max_bucket_count(); }
308
309  _LIBCPP_HIDE_FROM_ABI size_type elems_in_bucket(size_type __n) const { return __table_.bucket_size(__n); }
310
311  _LIBCPP_HIDE_FROM_ABI void resize(size_type __n) { __table_.__rehash_unique(__n); }
312};
313
314template <class _Value, class _Hash, class _Pred, class _Alloc>
315hash_set<_Value, _Hash, _Pred, _Alloc>::hash_set(size_type __n, const hasher& __hf, const key_equal& __eql)
316    : __table_(__hf, __eql) {
317  __table_.__rehash_unique(__n);
318}
319
320template <class _Value, class _Hash, class _Pred, class _Alloc>
321hash_set<_Value, _Hash, _Pred, _Alloc>::hash_set(
322    size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
323    : __table_(__hf, __eql, __a) {
324  __table_.__rehash_unique(__n);
325}
326
327template <class _Value, class _Hash, class _Pred, class _Alloc>
328template <class _InputIterator>
329hash_set<_Value, _Hash, _Pred, _Alloc>::hash_set(_InputIterator __first, _InputIterator __last) {
330  insert(__first, __last);
331}
332
333template <class _Value, class _Hash, class _Pred, class _Alloc>
334template <class _InputIterator>
335hash_set<_Value, _Hash, _Pred, _Alloc>::hash_set(
336    _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql)
337    : __table_(__hf, __eql) {
338  __table_.__rehash_unique(__n);
339  insert(__first, __last);
340}
341
342template <class _Value, class _Hash, class _Pred, class _Alloc>
343template <class _InputIterator>
344hash_set<_Value, _Hash, _Pred, _Alloc>::hash_set(
345    _InputIterator __first,
346    _InputIterator __last,
347    size_type __n,
348    const hasher& __hf,
349    const key_equal& __eql,
350    const allocator_type& __a)
351    : __table_(__hf, __eql, __a) {
352  __table_.__rehash_unique(__n);
353  insert(__first, __last);
354}
355
356template <class _Value, class _Hash, class _Pred, class _Alloc>
357hash_set<_Value, _Hash, _Pred, _Alloc>::hash_set(const hash_set& __u) : __table_(__u.__table_) {
358  __table_.__rehash_unique(__u.bucket_count());
359  insert(__u.begin(), __u.end());
360}
361
362template <class _Value, class _Hash, class _Pred, class _Alloc>
363template <class _InputIterator>
364inline void hash_set<_Value, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) {
365  for (; __first != __last; ++__first)
366    __table_.__insert_unique(*__first);
367}
368
369template <class _Value, class _Hash, class _Pred, class _Alloc>
370inline _LIBCPP_HIDE_FROM_ABI void
371swap(hash_set<_Value, _Hash, _Pred, _Alloc>& __x, hash_set<_Value, _Hash, _Pred, _Alloc>& __y) {
372  __x.swap(__y);
373}
374
375template <class _Value, class _Hash, class _Pred, class _Alloc>
376_LIBCPP_HIDE_FROM_ABI bool
377operator==(const hash_set<_Value, _Hash, _Pred, _Alloc>& __x, const hash_set<_Value, _Hash, _Pred, _Alloc>& __y) {
378  if (__x.size() != __y.size())
379    return false;
380  typedef typename hash_set<_Value, _Hash, _Pred, _Alloc>::const_iterator const_iterator;
381  for (const_iterator __i = __x.begin(), __ex = __x.end(), __ey = __y.end(); __i != __ex; ++__i) {
382    const_iterator __j = __y.find(*__i);
383    if (__j == __ey || !(*__i == *__j))
384      return false;
385  }
386  return true;
387}
388
389template <class _Value, class _Hash, class _Pred, class _Alloc>
390inline _LIBCPP_HIDE_FROM_ABI bool
391operator!=(const hash_set<_Value, _Hash, _Pred, _Alloc>& __x, const hash_set<_Value, _Hash, _Pred, _Alloc>& __y) {
392  return !(__x == __y);
393}
394
395template <class _Value,
396          class _Hash  = hash<_Value>,
397          class _Pred  = std::equal_to<_Value>,
398          class _Alloc = std::allocator<_Value> >
399class _LIBCPP_TEMPLATE_VIS hash_multiset {
400public:
401  // types
402  typedef _Value key_type;
403  typedef key_type value_type;
404  typedef _Hash hasher;
405  typedef _Pred key_equal;
406  typedef _Alloc allocator_type;
407  typedef value_type& reference;
408  typedef const value_type& const_reference;
409
410private:
411  typedef std::__hash_table<value_type, hasher, key_equal, allocator_type> __table;
412
413  __table __table_;
414
415public:
416  typedef typename __table::pointer pointer;
417  typedef typename __table::const_pointer const_pointer;
418  typedef typename __table::size_type size_type;
419  typedef typename __table::difference_type difference_type;
420
421  typedef typename __table::const_iterator iterator;
422  typedef typename __table::const_iterator const_iterator;
423
424  _LIBCPP_HIDE_FROM_ABI hash_multiset() {}
425  explicit _LIBCPP_HIDE_FROM_ABI
426  hash_multiset(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal());
427  _LIBCPP_HIDE_FROM_ABI
428  hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
429  template <class _InputIterator>
430  _LIBCPP_HIDE_FROM_ABI hash_multiset(_InputIterator __first, _InputIterator __last);
431  template <class _InputIterator>
432  _LIBCPP_HIDE_FROM_ABI
433  hash_multiset(_InputIterator __first,
434                _InputIterator __last,
435                size_type __n,
436                const hasher& __hf     = hasher(),
437                const key_equal& __eql = key_equal());
438  template <class _InputIterator>
439  _LIBCPP_HIDE_FROM_ABI hash_multiset(
440      _InputIterator __first,
441      _InputIterator __last,
442      size_type __n,
443      const hasher& __hf,
444      const key_equal& __eql,
445      const allocator_type& __a);
446  _LIBCPP_HIDE_FROM_ABI hash_multiset(const hash_multiset& __u);
447
448  _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return allocator_type(__table_.__node_alloc()); }
449
450  _LIBCPP_HIDE_FROM_ABI bool empty() const { return __table_.size() == 0; }
451  _LIBCPP_HIDE_FROM_ABI size_type size() const { return __table_.size(); }
452  _LIBCPP_HIDE_FROM_ABI size_type max_size() const { return __table_.max_size(); }
453
454  _LIBCPP_HIDE_FROM_ABI iterator begin() { return __table_.begin(); }
455  _LIBCPP_HIDE_FROM_ABI iterator end() { return __table_.end(); }
456  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return __table_.begin(); }
457  _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __table_.end(); }
458
459  _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__insert_multi(__x); }
460  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x); }
461  template <class _InputIterator>
462  _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last);
463
464  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __p) { __table_.erase(__p); }
465  _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_multi(__k); }
466  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __first, const_iterator __last) { __table_.erase(__first, __last); }
467  _LIBCPP_HIDE_FROM_ABI void clear() { __table_.clear(); }
468
469  _LIBCPP_HIDE_FROM_ABI void swap(hash_multiset& __u) { __table_.swap(__u.__table_); }
470
471  _LIBCPP_HIDE_FROM_ABI hasher hash_funct() const { return __table_.hash_function(); }
472  _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq(); }
473
474  _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
475  _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
476  _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_multi(__k); }
477  _LIBCPP_HIDE_FROM_ABI std::pair<iterator, iterator> equal_range(const key_type& __k) {
478    return __table_.__equal_range_multi(__k);
479  }
480  _LIBCPP_HIDE_FROM_ABI std::pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
481    return __table_.__equal_range_multi(__k);
482  }
483
484  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const { return __table_.bucket_count(); }
485  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const { return __table_.max_bucket_count(); }
486
487  _LIBCPP_HIDE_FROM_ABI size_type elems_in_bucket(size_type __n) const { return __table_.bucket_size(__n); }
488
489  _LIBCPP_HIDE_FROM_ABI void resize(size_type __n) { __table_.__rehash_multi(__n); }
490};
491
492template <class _Value, class _Hash, class _Pred, class _Alloc>
493hash_multiset<_Value, _Hash, _Pred, _Alloc>::hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql)
494    : __table_(__hf, __eql) {
495  __table_.__rehash_multi(__n);
496}
497
498template <class _Value, class _Hash, class _Pred, class _Alloc>
499hash_multiset<_Value, _Hash, _Pred, _Alloc>::hash_multiset(
500    size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
501    : __table_(__hf, __eql, __a) {
502  __table_.__rehash_multi(__n);
503}
504
505template <class _Value, class _Hash, class _Pred, class _Alloc>
506template <class _InputIterator>
507hash_multiset<_Value, _Hash, _Pred, _Alloc>::hash_multiset(_InputIterator __first, _InputIterator __last) {
508  insert(__first, __last);
509}
510
511template <class _Value, class _Hash, class _Pred, class _Alloc>
512template <class _InputIterator>
513hash_multiset<_Value, _Hash, _Pred, _Alloc>::hash_multiset(
514    _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql)
515    : __table_(__hf, __eql) {
516  __table_.__rehash_multi(__n);
517  insert(__first, __last);
518}
519
520template <class _Value, class _Hash, class _Pred, class _Alloc>
521template <class _InputIterator>
522hash_multiset<_Value, _Hash, _Pred, _Alloc>::hash_multiset(
523    _InputIterator __first,
524    _InputIterator __last,
525    size_type __n,
526    const hasher& __hf,
527    const key_equal& __eql,
528    const allocator_type& __a)
529    : __table_(__hf, __eql, __a) {
530  __table_.__rehash_multi(__n);
531  insert(__first, __last);
532}
533
534template <class _Value, class _Hash, class _Pred, class _Alloc>
535hash_multiset<_Value, _Hash, _Pred, _Alloc>::hash_multiset(const hash_multiset& __u) : __table_(__u.__table_) {
536  __table_.__rehash_multi(__u.bucket_count());
537  insert(__u.begin(), __u.end());
538}
539
540template <class _Value, class _Hash, class _Pred, class _Alloc>
541template <class _InputIterator>
542inline void hash_multiset<_Value, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) {
543  for (; __first != __last; ++__first)
544    __table_.__insert_multi(*__first);
545}
546
547template <class _Value, class _Hash, class _Pred, class _Alloc>
548inline _LIBCPP_HIDE_FROM_ABI void
549swap(hash_multiset<_Value, _Hash, _Pred, _Alloc>& __x, hash_multiset<_Value, _Hash, _Pred, _Alloc>& __y) {
550  __x.swap(__y);
551}
552
553template <class _Value, class _Hash, class _Pred, class _Alloc>
554_LIBCPP_HIDE_FROM_ABI bool operator==(const hash_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
555                                      const hash_multiset<_Value, _Hash, _Pred, _Alloc>& __y) {
556  if (__x.size() != __y.size())
557    return false;
558  typedef typename hash_multiset<_Value, _Hash, _Pred, _Alloc>::const_iterator const_iterator;
559  typedef std::pair<const_iterator, const_iterator> _EqRng;
560  for (const_iterator __i = __x.begin(), __ex = __x.end(); __i != __ex;) {
561    _EqRng __xeq = __x.equal_range(*__i);
562    _EqRng __yeq = __y.equal_range(*__i);
563    if (std::distance(__xeq.first, __xeq.second) != std::distance(__yeq.first, __yeq.second) ||
564        !std::is_permutation(__xeq.first, __xeq.second, __yeq.first))
565      return false;
566    __i = __xeq.second;
567  }
568  return true;
569}
570
571template <class _Value, class _Hash, class _Pred, class _Alloc>
572inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const hash_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
573                                             const hash_multiset<_Value, _Hash, _Pred, _Alloc>& __y) {
574  return !(__x == __y);
575}
576
577} // namespace __gnu_cxx
578
579#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
580#  include <concepts>
581#  include <iterator>
582#  include <type_traits>
583#endif
584
585#endif // _LIBCPP_HASH_SET
586