llvm-project

Форк
0
/
unordered_set 
1811 строк · 83.3 Кб
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_UNORDERED_SET
11
#define _LIBCPP_UNORDERED_SET
12

13
// clang-format off
14

15
/*
16

17
    unordered_set synopsis
18

19
#include <initializer_list>
20

21
namespace std
22
{
23

24
template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
25
          class Alloc = allocator<Value>>
26
class unordered_set
27
{
28
public:
29
    // types
30
    typedef Value                                                      key_type;
31
    typedef key_type                                                   value_type;
32
    typedef Hash                                                       hasher;
33
    typedef Pred                                                       key_equal;
34
    typedef Alloc                                                      allocator_type;
35
    typedef value_type&                                                reference;
36
    typedef const value_type&                                          const_reference;
37
    typedef typename allocator_traits<allocator_type>::pointer         pointer;
38
    typedef typename allocator_traits<allocator_type>::const_pointer   const_pointer;
39
    typedef typename allocator_traits<allocator_type>::size_type       size_type;
40
    typedef typename allocator_traits<allocator_type>::difference_type difference_type;
41

42
    typedef /unspecified/ iterator;
43
    typedef /unspecified/ const_iterator;
44
    typedef /unspecified/ local_iterator;
45
    typedef /unspecified/ const_local_iterator;
46

47
    typedef unspecified node_type unspecified;                            // C++17
48
    typedef INSERT_RETURN_TYPE<iterator, node_type> insert_return_type;   // C++17
49

50
    unordered_set()
51
        noexcept(
52
            is_nothrow_default_constructible<hasher>::value &&
53
            is_nothrow_default_constructible<key_equal>::value &&
54
            is_nothrow_default_constructible<allocator_type>::value);
55
    explicit unordered_set(size_type n, const hasher& hf = hasher(),
56
                           const key_equal& eql = key_equal(),
57
                           const allocator_type& a = allocator_type());
58
    template <class InputIterator>
59
        unordered_set(InputIterator f, InputIterator l,
60
                      size_type n = 0, const hasher& hf = hasher(),
61
                      const key_equal& eql = key_equal(),
62
                      const allocator_type& a = allocator_type());
63
    template<container-compatible-range<value_type> R>
64
      unordered_set(from_range_t, R&& rg, size_type n = see below,
65
        const hasher& hf = hasher(), const key_equal& eql = key_equal(),
66
        const allocator_type& a = allocator_type()); // C++23
67
    explicit unordered_set(const allocator_type&);
68
    unordered_set(const unordered_set&);
69
    unordered_set(const unordered_set&, const Allocator&);
70
    unordered_set(unordered_set&&)
71
        noexcept(
72
            is_nothrow_move_constructible<hasher>::value &&
73
            is_nothrow_move_constructible<key_equal>::value &&
74
            is_nothrow_move_constructible<allocator_type>::value);
75
    unordered_set(unordered_set&&, const Allocator&);
76
    unordered_set(initializer_list<value_type>, size_type n = 0,
77
                  const hasher& hf = hasher(), const key_equal& eql = key_equal(),
78
                  const allocator_type& a = allocator_type());
79
    unordered_set(size_type n, const allocator_type& a); // C++14
80
    unordered_set(size_type n, const hasher& hf, const allocator_type& a); // C++14
81
    template <class InputIterator>
82
      unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a); // C++14
83
    template <class InputIterator>
84
      unordered_set(InputIterator f, InputIterator l, size_type n,
85
                    const hasher& hf,  const allocator_type& a); // C++14
86
    template<container-compatible-range<value_type> R>
87
      unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a)
88
        : unordered_set(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } // C++23
89
    template<container-compatible-range<value_type> R>
90
      unordered_set(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a)
91
        : unordered_set(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { }       // C++23
92
    unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a); // C++14
93
    unordered_set(initializer_list<value_type> il, size_type n,
94
                  const hasher& hf,  const allocator_type& a); // C++14
95
    ~unordered_set();
96
    unordered_set& operator=(const unordered_set&);
97
    unordered_set& operator=(unordered_set&&)
98
        noexcept(
99
            allocator_type::propagate_on_container_move_assignment::value &&
100
            is_nothrow_move_assignable<allocator_type>::value &&
101
            is_nothrow_move_assignable<hasher>::value &&
102
            is_nothrow_move_assignable<key_equal>::value);
103
    unordered_set& operator=(initializer_list<value_type>);
104

105
    allocator_type get_allocator() const noexcept;
106

107
    bool      empty() const noexcept;
108
    size_type size() const noexcept;
109
    size_type max_size() const noexcept;
110

111
    iterator       begin() noexcept;
112
    iterator       end() noexcept;
113
    const_iterator begin()  const noexcept;
114
    const_iterator end()    const noexcept;
115
    const_iterator cbegin() const noexcept;
116
    const_iterator cend()   const noexcept;
117

118
    template <class... Args>
119
        pair<iterator, bool> emplace(Args&&... args);
120
    template <class... Args>
121
        iterator emplace_hint(const_iterator position, Args&&... args);
122
    pair<iterator, bool> insert(const value_type& obj);
123
    pair<iterator, bool> insert(value_type&& obj);
124
    iterator insert(const_iterator hint, const value_type& obj);
125
    iterator insert(const_iterator hint, value_type&& obj);
126
    template <class InputIterator>
127
        void insert(InputIterator first, InputIterator last);
128
    template<container-compatible-range<value_type> R>
129
      void insert_range(R&& rg);                                      // C++23
130
    void insert(initializer_list<value_type>);
131

132
    node_type extract(const_iterator position);                       // C++17
133
    node_type extract(const key_type& x);                             // C++17
134
    insert_return_type insert(node_type&& nh);                        // C++17
135
    iterator           insert(const_iterator hint, node_type&& nh);   // C++17
136

137
    iterator erase(const_iterator position);
138
    iterator erase(iterator position);  // C++14
139
    size_type erase(const key_type& k);
140
    iterator erase(const_iterator first, const_iterator last);
141
    void clear() noexcept;
142

143
    template<class H2, class P2>
144
      void merge(unordered_set<Key, H2, P2, Allocator>& source);         // C++17
145
    template<class H2, class P2>
146
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);        // C++17
147
    template<class H2, class P2>
148
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);    // C++17
149
    template<class H2, class P2>
150
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);   // C++17
151

152
    void swap(unordered_set&)
153
       noexcept(allocator_traits<Allocator>::is_always_equal::value &&
154
                 noexcept(swap(declval<hasher&>(), declval<hasher&>())) &&
155
                 noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); // C++17
156

157
    hasher hash_function() const;
158
    key_equal key_eq() const;
159

160
    iterator       find(const key_type& k);
161
    const_iterator find(const key_type& k) const;
162
    template<typename K>
163
        iterator find(const K& x);              // C++20
164
    template<typename K>
165
        const_iterator find(const K& x) const;  // C++20
166
    size_type count(const key_type& k) const;
167
    template<typename K>
168
        size_type count(const K& k) const; // C++20
169
    bool contains(const key_type& k) const; // C++20
170
    template<typename K>
171
        bool contains(const K& k) const; // C++20
172
    pair<iterator, iterator>             equal_range(const key_type& k);
173
    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
174
    template<typename K>
175
        pair<iterator, iterator>             equal_range(const K& k); // C++20
176
    template<typename K>
177
        pair<const_iterator, const_iterator> equal_range(const K& k) const; // C++20
178

179
    size_type bucket_count() const noexcept;
180
    size_type max_bucket_count() const noexcept;
181

182
    size_type bucket_size(size_type n) const;
183
    size_type bucket(const key_type& k) const;
184

185
    local_iterator       begin(size_type n);
186
    local_iterator       end(size_type n);
187
    const_local_iterator begin(size_type n) const;
188
    const_local_iterator end(size_type n) const;
189
    const_local_iterator cbegin(size_type n) const;
190
    const_local_iterator cend(size_type n) const;
191

192
    float load_factor() const noexcept;
193
    float max_load_factor() const noexcept;
194
    void max_load_factor(float z);
195
    void rehash(size_type n);
196
    void reserve(size_type n);
197
};
198

199
template<class InputIterator,
200
    class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
201
    class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
202
    class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
203
unordered_set(InputIterator, InputIterator, typename see below::size_type = see below,
204
    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
205
  -> unordered_set<typename iterator_traits<InputIterator>::value_type,
206
        Hash, Pred, Allocator>; // C++17
207

208
template<ranges::input_range R,
209
         class Hash = hash<ranges::range_value_t<R>>,
210
         class Pred = equal_to<ranges::range_value_t<R>>,
211
         class Allocator = allocator<ranges::range_value_t<R>>>
212
  unordered_set(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator())
213
    -> unordered_set<ranges::range_value_t<R>, Hash, Pred, Allocator>; // C++23
214

215
template<class T, class Hash = hash<T>,
216
          class Pred = equal_to<T>, class Allocator = allocator<T>>
217
unordered_set(initializer_list<T>, typename see below::size_type = see below,
218
    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
219
  -> unordered_set<T, Hash, Pred, Allocator>; // C++17
220

221
template<class InputIterator,  class Allocator>
222
unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
223
  -> unordered_set<typename iterator_traits<InputIterator>::value_type,
224
        hash<typename iterator_traits<InputIterator>::value_type>,
225
        equal_to<typename iterator_traits<InputIterator>::value_type>,
226
        Allocator>; // C++17
227

228
template<class InputIterator, class Hash, class Allocator>
229
unordered_set(InputIterator, InputIterator, typename see below::size_type,
230
    Hash, Allocator)
231
  -> unordered_set<typename iterator_traits<InputIterator>::value_type, Hash,
232
        equal_to<typename iterator_traits<InputIterator>::value_type>,
233
        Allocator>; // C++17
234

235
template<ranges::input_range R, class Allocator>
236
  unordered_set(from_range_t, R&&, typename see below::size_type, Allocator)
237
    -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
238
                      equal_to<ranges::range_value_t<R>>, Allocator>; // C++23
239

240
template<ranges::input_range R, class Allocator>
241
  unordered_set(from_range_t, R&&, Allocator)
242
    -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
243
                      equal_to<ranges::range_value_t<R>>, Allocator>; // C++23
244

245
template<ranges::input_range R, class Hash, class Allocator>
246
  unordered_set(from_range_t, R&&, typename see below::size_type, Hash, Allocator)
247
    -> unordered_set<ranges::range_value_t<R>, Hash,
248
                      equal_to<ranges::range_value_t<R>>, Allocator>; // C++23
249

250
template<class T, class Allocator>
251
unordered_set(initializer_list<T>, typename see below::size_type, Allocator)
252
  -> unordered_set<T, hash<T>, equal_to<T>, Allocator>; // C++17
253

254
template<class T, class Hash, class Allocator>
255
unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator)
256
  -> unordered_set<T, Hash, equal_to<T>, Allocator>; // C++17
257

258
template <class Value, class Hash, class Pred, class Alloc>
259
    void swap(unordered_set<Value, Hash, Pred, Alloc>& x,
260
              unordered_set<Value, Hash, Pred, Alloc>& y)
261
              noexcept(noexcept(x.swap(y)));
262

263
template <class Value, class Hash, class Pred, class Alloc>
264
    bool
265
    operator==(const unordered_set<Value, Hash, Pred, Alloc>& x,
266
               const unordered_set<Value, Hash, Pred, Alloc>& y);
267

268
template <class Value, class Hash, class Pred, class Alloc>
269
    bool
270
    operator!=(const unordered_set<Value, Hash, Pred, Alloc>& x,
271
               const unordered_set<Value, Hash, Pred, Alloc>& y); // removed in C++20
272

273
template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>,
274
          class Alloc = allocator<Value>>
275
class unordered_multiset
276
{
277
public:
278
    // types
279
    typedef Value                                                      key_type;
280
    typedef key_type                                                   value_type;
281
    typedef Hash                                                       hasher;
282
    typedef Pred                                                       key_equal;
283
    typedef Alloc                                                      allocator_type;
284
    typedef value_type&                                                reference;
285
    typedef const value_type&                                          const_reference;
286
    typedef typename allocator_traits<allocator_type>::pointer         pointer;
287
    typedef typename allocator_traits<allocator_type>::const_pointer   const_pointer;
288
    typedef typename allocator_traits<allocator_type>::size_type       size_type;
289
    typedef typename allocator_traits<allocator_type>::difference_type difference_type;
290

291
    typedef /unspecified/ iterator;
292
    typedef /unspecified/ const_iterator;
293
    typedef /unspecified/ local_iterator;
294
    typedef /unspecified/ const_local_iterator;
295

296
    typedef unspecified node_type unspecified;   // C++17
297

298
    unordered_multiset()
299
        noexcept(
300
            is_nothrow_default_constructible<hasher>::value &&
301
            is_nothrow_default_constructible<key_equal>::value &&
302
            is_nothrow_default_constructible<allocator_type>::value);
303
    explicit unordered_multiset(size_type n, const hasher& hf = hasher(),
304
                           const key_equal& eql = key_equal(),
305
                           const allocator_type& a = allocator_type());
306
    template <class InputIterator>
307
        unordered_multiset(InputIterator f, InputIterator l,
308
                      size_type n = 0, const hasher& hf = hasher(),
309
                      const key_equal& eql = key_equal(),
310
                      const allocator_type& a = allocator_type());
311
    template<container-compatible-range<value_type> R>
312
      unordered_multiset(from_range_t, R&& rg, size_type n = see below,
313
        const hasher& hf = hasher(), const key_equal& eql = key_equal(),
314
        const allocator_type& a = allocator_type()); // C++23
315
    explicit unordered_multiset(const allocator_type&);
316
    unordered_multiset(const unordered_multiset&);
317
    unordered_multiset(const unordered_multiset&, const Allocator&);
318
    unordered_multiset(unordered_multiset&&)
319
        noexcept(
320
            is_nothrow_move_constructible<hasher>::value &&
321
            is_nothrow_move_constructible<key_equal>::value &&
322
            is_nothrow_move_constructible<allocator_type>::value);
323
    unordered_multiset(unordered_multiset&&, const Allocator&);
324
    unordered_multiset(initializer_list<value_type>, size_type n = /see below/,
325
                  const hasher& hf = hasher(), const key_equal& eql = key_equal(),
326
                  const allocator_type& a = allocator_type());
327
    unordered_multiset(size_type n, const allocator_type& a); // C++14
328
    unordered_multiset(size_type n, const hasher& hf, const allocator_type& a); // C++14
329
    template <class InputIterator>
330
      unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a); // C++14
331
    template <class InputIterator>
332
      unordered_multiset(InputIterator f, InputIterator l, size_type n,
333
                         const hasher& hf, const allocator_type& a); // C++14
334
    template<container-compatible-range<value_type> R>
335
      unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a)
336
        : unordered_multiset(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } // C++23
337
    template<container-compatible-range<value_type> R>
338
      unordered_multiset(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a)
339
        : unordered_multiset(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { }       // C++23
340
    unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a); // C++14
341
    unordered_multiset(initializer_list<value_type> il, size_type n,
342
                       const hasher& hf,  const allocator_type& a); // C++14
343
    ~unordered_multiset();
344
    unordered_multiset& operator=(const unordered_multiset&);
345
    unordered_multiset& operator=(unordered_multiset&&)
346
        noexcept(
347
            allocator_type::propagate_on_container_move_assignment::value &&
348
            is_nothrow_move_assignable<allocator_type>::value &&
349
            is_nothrow_move_assignable<hasher>::value &&
350
            is_nothrow_move_assignable<key_equal>::value);
351
    unordered_multiset& operator=(initializer_list<value_type>);
352

353
    allocator_type get_allocator() const noexcept;
354

355
    bool      empty() const noexcept;
356
    size_type size() const noexcept;
357
    size_type max_size() const noexcept;
358

359
    iterator       begin() noexcept;
360
    iterator       end() noexcept;
361
    const_iterator begin()  const noexcept;
362
    const_iterator end()    const noexcept;
363
    const_iterator cbegin() const noexcept;
364
    const_iterator cend()   const noexcept;
365

366
    template <class... Args>
367
        iterator emplace(Args&&... args);
368
    template <class... Args>
369
        iterator emplace_hint(const_iterator position, Args&&... args);
370
    iterator insert(const value_type& obj);
371
    iterator insert(value_type&& obj);
372
    iterator insert(const_iterator hint, const value_type& obj);
373
    iterator insert(const_iterator hint, value_type&& obj);
374
    template <class InputIterator>
375
        void insert(InputIterator first, InputIterator last);
376
    template<container-compatible-range<value_type> R>
377
      void insert_range(R&& rg);                            // C++23
378
    void insert(initializer_list<value_type>);
379

380
    node_type extract(const_iterator position);             // C++17
381
    node_type extract(const key_type& x);                   // C++17
382
    iterator insert(node_type&& nh);                        // C++17
383
    iterator insert(const_iterator hint, node_type&& nh);   // C++17
384

385
    iterator erase(const_iterator position);
386
    iterator erase(iterator position);  // C++14
387
    size_type erase(const key_type& k);
388
    iterator erase(const_iterator first, const_iterator last);
389
    void clear() noexcept;
390

391
    template<class H2, class P2>
392
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);    // C++17
393
    template<class H2, class P2>
394
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);   // C++17
395
    template<class H2, class P2>
396
      void merge(unordered_set<Key, H2, P2, Allocator>& source);         // C++17
397
    template<class H2, class P2>
398
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);        // C++17
399

400
    void swap(unordered_multiset&)
401
       noexcept(allocator_traits<Allocator>::is_always_equal::value &&
402
                 noexcept(swap(declval<hasher&>(), declval<hasher&>())) &&
403
                 noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); // C++17
404

405
    hasher hash_function() const;
406
    key_equal key_eq() const;
407

408
    iterator       find(const key_type& k);
409
    const_iterator find(const key_type& k) const;
410
    template<typename K>
411
        iterator find(const K& x);              // C++20
412
    template<typename K>
413
        const_iterator find(const K& x) const;  // C++20
414
    size_type count(const key_type& k) const;
415
    template<typename K>
416
        size_type count(const K& k) const; // C++20
417
    bool contains(const key_type& k) const; // C++20
418
    template<typename K>
419
        bool contains(const K& k) const; // C++20
420
    pair<iterator, iterator>             equal_range(const key_type& k);
421
    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
422
    template<typename K>
423
        pair<iterator, iterator>             equal_range(const K& k); // C++20
424
    template<typename K>
425
        pair<const_iterator, const_iterator> equal_range(const K& k) const; // C++20
426

427
    size_type bucket_count() const noexcept;
428
    size_type max_bucket_count() const noexcept;
429

430
    size_type bucket_size(size_type n) const;
431
    size_type bucket(const key_type& k) const;
432

433
    local_iterator       begin(size_type n);
434
    local_iterator       end(size_type n);
435
    const_local_iterator begin(size_type n) const;
436
    const_local_iterator end(size_type n) const;
437
    const_local_iterator cbegin(size_type n) const;
438
    const_local_iterator cend(size_type n) const;
439

440
    float load_factor() const noexcept;
441
    float max_load_factor() const noexcept;
442
    void max_load_factor(float z);
443
    void rehash(size_type n);
444
    void reserve(size_type n);
445
};
446

447
template<class InputIterator,
448
    class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
449
    class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
450
    class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
451
unordered_multiset(InputIterator, InputIterator, see below::size_type = see below,
452
    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
453
  -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
454
        Hash, Pred, Allocator>; // C++17
455

456
template<ranges::input_range R,
457
         class Hash = hash<ranges::range_value_t<R>>,
458
         class Pred = equal_to<ranges::range_value_t<R>>,
459
         class Allocator = allocator<ranges::range_value_t<R>>>
460
  unordered_multiset(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator())
461
    -> unordered_multiset<ranges::range_value_t<R>, Hash, Pred, Allocator>; // C++23
462

463
template<class T, class Hash = hash<T>,
464
          class Pred = equal_to<T>, class Allocator = allocator<T>>
465
unordered_multiset(initializer_list<T>, typename see below::size_type = see below,
466
    Hash = Hash(), Pred = Pred(), Allocator = Allocator())
467
  -> unordered_multiset<T, Hash, Pred, Allocator>; // C++17
468

469
template<class InputIterator,  class Allocator>
470
unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator)
471
  -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
472
        hash<typename iterator_traits<InputIterator>::value_type>,
473
        equal_to<typename iterator_traits<InputIterator>::value_type>,
474
        Allocator>; // C++17
475

476
template<class InputIterator,  class Hash, class Allocator>
477
unordered_multiset(InputIterator, InputIterator, typename see below::size_type,
478
    Hash, Allocator)
479
  -> unordered_multiset<typename iterator_traits<InputIterator>::value_type, Hash,
480
        equal_to<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17
481

482
template<ranges::input_range R, class Allocator>
483
  unordered_multiset(from_range_t, R&&, typename see below::size_type, Allocator)
484
    -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
485
                      equal_to<ranges::range_value_t<R>>, Allocator>; // C++23
486

487
template<ranges::input_range R, class Allocator>
488
  unordered_multiset(from_range_t, R&&, Allocator)
489
    -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>,
490
                      equal_to<ranges::range_value_t<R>>, Allocator>; // C++23
491

492
template<ranges::input_range R, class Hash, class Allocator>
493
  unordered_multiset(from_range_t, R&&, typename see below::size_type, Hash, Allocator)
494
    -> unordered_multiset<ranges::range_value_t<R>, Hash,
495
                      equal_to<ranges::range_value_t<R>>, Allocator>; // C++23
496

497
template<class T, class Allocator>
498
unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator)
499
  -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>; // C++17
500

501
template<class T, class Hash, class Allocator>
502
unordered_multiset(initializer_list<T>, typename see below::size_type, Hash, Allocator)
503
  -> unordered_multiset<T, Hash, equal_to<T>, Allocator>; // C++17
504

505
template <class Value, class Hash, class Pred, class Alloc>
506
    void swap(unordered_multiset<Value, Hash, Pred, Alloc>& x,
507
              unordered_multiset<Value, Hash, Pred, Alloc>& y)
508
              noexcept(noexcept(x.swap(y)));
509

510
template <class K, class T, class H, class P, class A, class Predicate>
511
    typename unordered_set<K, T, H, P, A>::size_type
512
    erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred);       // C++20
513

514
template <class K, class T, class H, class P, class A, class Predicate>
515
    typename unordered_multiset<K, T, H, P, A>::size_type
516
    erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred);  // C++20
517

518

519
template <class Value, class Hash, class Pred, class Alloc>
520
    bool
521
    operator==(const unordered_multiset<Value, Hash, Pred, Alloc>& x,
522
               const unordered_multiset<Value, Hash, Pred, Alloc>& y);
523

524
template <class Value, class Hash, class Pred, class Alloc>
525
    bool
526
    operator!=(const unordered_multiset<Value, Hash, Pred, Alloc>& x,
527
               const unordered_multiset<Value, Hash, Pred, Alloc>& y); // removed in C++20
528
}  // std
529

530
*/
531

532
// clang-format on
533

534
#include <__algorithm/is_permutation.h>
535
#include <__assert>
536
#include <__config>
537
#include <__functional/is_transparent.h>
538
#include <__functional/operations.h>
539
#include <__hash_table>
540
#include <__iterator/distance.h>
541
#include <__iterator/erase_if_container.h>
542
#include <__iterator/iterator_traits.h>
543
#include <__iterator/ranges_iterator_traits.h>
544
#include <__memory/addressof.h>
545
#include <__memory/allocator.h>
546
#include <__memory_resource/polymorphic_allocator.h>
547
#include <__node_handle>
548
#include <__ranges/concepts.h>
549
#include <__ranges/container_compatible_range.h>
550
#include <__ranges/from_range.h>
551
#include <__type_traits/is_allocator.h>
552
#include <__utility/forward.h>
553
#include <version>
554

555
// standard-mandated includes
556

557
// [iterator.range]
558
#include <__iterator/access.h>
559
#include <__iterator/data.h>
560
#include <__iterator/empty.h>
561
#include <__iterator/reverse_access.h>
562
#include <__iterator/size.h>
563

564
// [unord.set.syn]
565
#include <compare>
566
#include <initializer_list>
567

568
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
569
#  pragma GCC system_header
570
#endif
571

572
_LIBCPP_PUSH_MACROS
573
#include <__undef_macros>
574

575
_LIBCPP_BEGIN_NAMESPACE_STD
576

577
template <class _Value, class _Hash, class _Pred, class _Alloc>
578
class unordered_multiset;
579

580
template <class _Value, class _Hash = hash<_Value>, class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> >
581
class _LIBCPP_TEMPLATE_VIS unordered_set {
582
public:
583
  // types
584
  typedef _Value key_type;
585
  typedef key_type value_type;
586
  typedef __type_identity_t<_Hash> hasher;
587
  typedef __type_identity_t<_Pred> key_equal;
588
  typedef __type_identity_t<_Alloc> allocator_type;
589
  typedef value_type& reference;
590
  typedef const value_type& const_reference;
591
  static_assert(__check_valid_allocator<allocator_type>::value, "");
592
  static_assert(is_same<value_type, typename allocator_type::value_type>::value,
593
                "Allocator::value_type must be same type as value_type");
594

595
private:
596
  typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table;
597

598
  __table __table_;
599

600
public:
601
  typedef typename __table::pointer pointer;
602
  typedef typename __table::const_pointer const_pointer;
603
  typedef typename __table::size_type size_type;
604
  typedef typename __table::difference_type difference_type;
605

606
  typedef typename __table::const_iterator iterator;
607
  typedef typename __table::const_iterator const_iterator;
608
  typedef typename __table::const_local_iterator local_iterator;
609
  typedef typename __table::const_local_iterator const_local_iterator;
610

611
#if _LIBCPP_STD_VER >= 17
612
  typedef __set_node_handle<typename __table::__node, allocator_type> node_type;
613
  typedef __insert_return_type<iterator, node_type> insert_return_type;
614
#endif
615

616
  template <class _Value2, class _Hash2, class _Pred2, class _Alloc2>
617
  friend class _LIBCPP_TEMPLATE_VIS unordered_set;
618
  template <class _Value2, class _Hash2, class _Pred2, class _Alloc2>
619
  friend class _LIBCPP_TEMPLATE_VIS unordered_multiset;
620

621
  _LIBCPP_HIDE_FROM_ABI unordered_set() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) {}
622
  explicit _LIBCPP_HIDE_FROM_ABI
623
  unordered_set(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal());
624
#if _LIBCPP_STD_VER >= 14
625
  inline _LIBCPP_HIDE_FROM_ABI unordered_set(size_type __n, const allocator_type& __a)
626
      : unordered_set(__n, hasher(), key_equal(), __a) {}
627
  inline _LIBCPP_HIDE_FROM_ABI unordered_set(size_type __n, const hasher& __hf, const allocator_type& __a)
628
      : unordered_set(__n, __hf, key_equal(), __a) {}
629
#endif
630
  _LIBCPP_HIDE_FROM_ABI
631
  unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
632
  template <class _InputIterator>
633
  _LIBCPP_HIDE_FROM_ABI unordered_set(_InputIterator __first, _InputIterator __last);
634
  template <class _InputIterator>
635
  _LIBCPP_HIDE_FROM_ABI
636
  unordered_set(_InputIterator __first,
637
                _InputIterator __last,
638
                size_type __n,
639
                const hasher& __hf     = hasher(),
640
                const key_equal& __eql = key_equal());
641
  template <class _InputIterator>
642
  _LIBCPP_HIDE_FROM_ABI unordered_set(
643
      _InputIterator __first,
644
      _InputIterator __last,
645
      size_type __n,
646
      const hasher& __hf,
647
      const key_equal& __eql,
648
      const allocator_type& __a);
649

650
#if _LIBCPP_STD_VER >= 23
651
  template <_ContainerCompatibleRange<value_type> _Range>
652
  _LIBCPP_HIDE_FROM_ABI unordered_set(
653
      from_range_t,
654
      _Range&& __range,
655
      size_type __n             = /*implementation-defined*/ 0,
656
      const hasher& __hf        = hasher(),
657
      const key_equal& __eql    = key_equal(),
658
      const allocator_type& __a = allocator_type())
659
      : __table_(__hf, __eql, __a) {
660
    if (__n > 0) {
661
      __table_.__rehash_unique(__n);
662
    }
663
    insert_range(std::forward<_Range>(__range));
664
  }
665
#endif
666

667
#if _LIBCPP_STD_VER >= 14
668
  template <class _InputIterator>
669
  inline _LIBCPP_HIDE_FROM_ABI
670
  unordered_set(_InputIterator __first, _InputIterator __last, size_type __n, const allocator_type& __a)
671
      : unordered_set(__first, __last, __n, hasher(), key_equal(), __a) {}
672
  template <class _InputIterator>
673
  _LIBCPP_HIDE_FROM_ABI unordered_set(
674
      _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a)
675
      : unordered_set(__first, __last, __n, __hf, key_equal(), __a) {}
676
#endif
677

678
#if _LIBCPP_STD_VER >= 23
679
  template <_ContainerCompatibleRange<value_type> _Range>
680
  _LIBCPP_HIDE_FROM_ABI unordered_set(from_range_t, _Range&& __range, size_type __n, const allocator_type& __a)
681
      : unordered_set(from_range, std::forward<_Range>(__range), __n, hasher(), key_equal(), __a) {}
682

683
  template <_ContainerCompatibleRange<value_type> _Range>
684
  _LIBCPP_HIDE_FROM_ABI
685
  unordered_set(from_range_t, _Range&& __range, size_type __n, const hasher& __hf, const allocator_type& __a)
686
      : unordered_set(from_range, std::forward<_Range>(__range), __n, __hf, key_equal(), __a) {}
687
#endif
688

689
  _LIBCPP_HIDE_FROM_ABI explicit unordered_set(const allocator_type& __a);
690
  _LIBCPP_HIDE_FROM_ABI unordered_set(const unordered_set& __u);
691
  _LIBCPP_HIDE_FROM_ABI unordered_set(const unordered_set& __u, const allocator_type& __a);
692
#ifndef _LIBCPP_CXX03_LANG
693
  _LIBCPP_HIDE_FROM_ABI unordered_set(unordered_set&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value);
694
  _LIBCPP_HIDE_FROM_ABI unordered_set(unordered_set&& __u, const allocator_type& __a);
695
  _LIBCPP_HIDE_FROM_ABI unordered_set(initializer_list<value_type> __il);
696
  _LIBCPP_HIDE_FROM_ABI
697
  unordered_set(initializer_list<value_type> __il,
698
                size_type __n,
699
                const hasher& __hf     = hasher(),
700
                const key_equal& __eql = key_equal());
701
  _LIBCPP_HIDE_FROM_ABI unordered_set(
702
      initializer_list<value_type> __il,
703
      size_type __n,
704
      const hasher& __hf,
705
      const key_equal& __eql,
706
      const allocator_type& __a);
707
#  if _LIBCPP_STD_VER >= 14
708
  inline _LIBCPP_HIDE_FROM_ABI
709
  unordered_set(initializer_list<value_type> __il, size_type __n, const allocator_type& __a)
710
      : unordered_set(__il, __n, hasher(), key_equal(), __a) {}
711
  inline _LIBCPP_HIDE_FROM_ABI
712
  unordered_set(initializer_list<value_type> __il, size_type __n, const hasher& __hf, const allocator_type& __a)
713
      : unordered_set(__il, __n, __hf, key_equal(), __a) {}
714
#  endif
715
#endif // _LIBCPP_CXX03_LANG
716
  _LIBCPP_HIDE_FROM_ABI ~unordered_set() {
717
    static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), "");
718
  }
719

720
  _LIBCPP_HIDE_FROM_ABI unordered_set& operator=(const unordered_set& __u) {
721
    __table_ = __u.__table_;
722
    return *this;
723
  }
724
#ifndef _LIBCPP_CXX03_LANG
725
  _LIBCPP_HIDE_FROM_ABI unordered_set& operator=(unordered_set&& __u)
726
      _NOEXCEPT_(is_nothrow_move_assignable<__table>::value);
727
  _LIBCPP_HIDE_FROM_ABI unordered_set& operator=(initializer_list<value_type> __il);
728
#endif // _LIBCPP_CXX03_LANG
729

730
  _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
731
    return allocator_type(__table_.__node_alloc());
732
  }
733

734
  _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __table_.size() == 0; }
735
  _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __table_.size(); }
736
  _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __table_.max_size(); }
737

738
  _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __table_.begin(); }
739
  _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __table_.end(); }
740
  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __table_.begin(); }
741
  _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __table_.end(); }
742
  _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return __table_.begin(); }
743
  _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return __table_.end(); }
744

745
#ifndef _LIBCPP_CXX03_LANG
746
  template <class... _Args>
747
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> emplace(_Args&&... __args) {
748
    return __table_.__emplace_unique(std::forward<_Args>(__args)...);
749
  }
750
  template <class... _Args>
751
  _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator, _Args&&... __args) {
752
    return __table_.__emplace_unique(std::forward<_Args>(__args)...).first;
753
  }
754

755
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(value_type&& __x) {
756
    return __table_.__insert_unique(std::move(__x));
757
  }
758
  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, value_type&& __x) { return insert(std::move(__x)).first; }
759

760
  _LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }
761
#endif // _LIBCPP_CXX03_LANG
762
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(const value_type& __x) { return __table_.__insert_unique(__x); }
763

764
  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x).first; }
765
  template <class _InputIterator>
766
  _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last);
767

768
#if _LIBCPP_STD_VER >= 23
769
  template <_ContainerCompatibleRange<value_type> _Range>
770
  _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
771
    for (auto&& __element : __range) {
772
      __table_.__insert_unique(std::forward<decltype(__element)>(__element));
773
    }
774
  }
775
#endif
776

777
  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __table_.erase(__p); }
778
  _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_unique(__k); }
779
  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
780
    return __table_.erase(__first, __last);
781
  }
782
  _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __table_.clear(); }
783

784
#if _LIBCPP_STD_VER >= 17
785
  _LIBCPP_HIDE_FROM_ABI insert_return_type insert(node_type&& __nh) {
786
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(),
787
                                        "node_type with incompatible allocator passed to unordered_set::insert()");
788
    return __table_.template __node_handle_insert_unique< node_type, insert_return_type>(std::move(__nh));
789
  }
790
  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __h, node_type&& __nh) {
791
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(),
792
                                        "node_type with incompatible allocator passed to unordered_set::insert()");
793
    return __table_.template __node_handle_insert_unique<node_type>(__h, std::move(__nh));
794
  }
795
  _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
796
    return __table_.template __node_handle_extract<node_type>(__key);
797
  }
798
  _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __it) {
799
    return __table_.template __node_handle_extract<node_type>(__it);
800
  }
801

802
  template <class _H2, class _P2>
803
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_set<key_type, _H2, _P2, allocator_type>& __source) {
804
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
805
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
806
    __table_.__node_handle_merge_unique(__source.__table_);
807
  }
808
  template <class _H2, class _P2>
809
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_set<key_type, _H2, _P2, allocator_type>&& __source) {
810
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
811
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
812
    __table_.__node_handle_merge_unique(__source.__table_);
813
  }
814
  template <class _H2, class _P2>
815
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>& __source) {
816
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
817
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
818
    __table_.__node_handle_merge_unique(__source.__table_);
819
  }
820
  template <class _H2, class _P2>
821
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>&& __source) {
822
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
823
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
824
    __table_.__node_handle_merge_unique(__source.__table_);
825
  }
826
#endif
827

828
  _LIBCPP_HIDE_FROM_ABI void swap(unordered_set& __u) _NOEXCEPT_(__is_nothrow_swappable_v<__table>) {
829
    __table_.swap(__u.__table_);
830
  }
831

832
  _LIBCPP_HIDE_FROM_ABI hasher hash_function() const { return __table_.hash_function(); }
833
  _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq(); }
834

835
  _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
836
  _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
837
#if _LIBCPP_STD_VER >= 20
838
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
839
  _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
840
    return __table_.find(__k);
841
  }
842
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
843
  _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
844
    return __table_.find(__k);
845
  }
846
#endif // _LIBCPP_STD_VER >= 20
847

848
  _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_unique(__k); }
849
#if _LIBCPP_STD_VER >= 20
850
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
851
  _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
852
    return __table_.__count_unique(__k);
853
  }
854
#endif // _LIBCPP_STD_VER >= 20
855

856
#if _LIBCPP_STD_VER >= 20
857
  _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
858

859
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
860
  _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
861
    return find(__k) != end();
862
  }
863
#endif // _LIBCPP_STD_VER >= 20
864

865
  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
866
    return __table_.__equal_range_unique(__k);
867
  }
868
  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
869
    return __table_.__equal_range_unique(__k);
870
  }
871
#if _LIBCPP_STD_VER >= 20
872
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
873
  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
874
    return __table_.__equal_range_unique(__k);
875
  }
876
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
877
  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
878
    return __table_.__equal_range_unique(__k);
879
  }
880
#endif // _LIBCPP_STD_VER >= 20
881

882
  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __table_.bucket_count(); }
883
  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return __table_.max_bucket_count(); }
884

885
  _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const { return __table_.bucket_size(__n); }
886
  _LIBCPP_HIDE_FROM_ABI size_type bucket(const key_type& __k) const { return __table_.bucket(__k); }
887

888
  _LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) { return __table_.begin(__n); }
889
  _LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) { return __table_.end(__n); }
890
  _LIBCPP_HIDE_FROM_ABI const_local_iterator begin(size_type __n) const { return __table_.cbegin(__n); }
891
  _LIBCPP_HIDE_FROM_ABI const_local_iterator end(size_type __n) const { return __table_.cend(__n); }
892
  _LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const { return __table_.cbegin(__n); }
893
  _LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const { return __table_.cend(__n); }
894

895
  _LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT { return __table_.load_factor(); }
896
  _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __table_.max_load_factor(); }
897
  _LIBCPP_HIDE_FROM_ABI void max_load_factor(float __mlf) { __table_.max_load_factor(__mlf); }
898
  _LIBCPP_HIDE_FROM_ABI void rehash(size_type __n) { __table_.__rehash_unique(__n); }
899
  _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n) { __table_.__reserve_unique(__n); }
900
};
901

902
#if _LIBCPP_STD_VER >= 17
903
template <class _InputIterator,
904
          class _Hash      = hash<__iter_value_type<_InputIterator>>,
905
          class _Pred      = equal_to<__iter_value_type<_InputIterator>>,
906
          class _Allocator = allocator<__iter_value_type<_InputIterator>>,
907
          class            = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
908
          class            = enable_if_t<!__is_allocator<_Hash>::value>,
909
          class            = enable_if_t<!is_integral<_Hash>::value>,
910
          class            = enable_if_t<!__is_allocator<_Pred>::value>,
911
          class            = enable_if_t<__is_allocator<_Allocator>::value>>
912
unordered_set(_InputIterator,
913
              _InputIterator,
914
              typename allocator_traits<_Allocator>::size_type = 0,
915
              _Hash                                            = _Hash(),
916
              _Pred                                            = _Pred(),
917
              _Allocator = _Allocator()) -> unordered_set<__iter_value_type<_InputIterator>, _Hash, _Pred, _Allocator>;
918

919
#  if _LIBCPP_STD_VER >= 23
920
template <ranges::input_range _Range,
921
          class _Hash      = hash<ranges::range_value_t<_Range>>,
922
          class _Pred      = equal_to<ranges::range_value_t<_Range>>,
923
          class _Allocator = allocator<ranges::range_value_t<_Range>>,
924
          class            = enable_if_t<!__is_allocator<_Hash>::value>,
925
          class            = enable_if_t<!is_integral<_Hash>::value>,
926
          class            = enable_if_t<!__is_allocator<_Pred>::value>,
927
          class            = enable_if_t<__is_allocator<_Allocator>::value>>
928
unordered_set(
929
    from_range_t,
930
    _Range&&,
931
    typename allocator_traits<_Allocator>::size_type = 0,
932
    _Hash                                            = _Hash(),
933
    _Pred                                            = _Pred(),
934
    _Allocator = _Allocator()) -> unordered_set<ranges::range_value_t<_Range>, _Hash, _Pred, _Allocator>; // C++23
935
#  endif
936

937
template <class _Tp,
938
          class _Hash      = hash<_Tp>,
939
          class _Pred      = equal_to<_Tp>,
940
          class _Allocator = allocator<_Tp>,
941
          class            = enable_if_t<!__is_allocator<_Hash>::value>,
942
          class            = enable_if_t<!is_integral<_Hash>::value>,
943
          class            = enable_if_t<!__is_allocator<_Pred>::value>,
944
          class            = enable_if_t<__is_allocator<_Allocator>::value>>
945
unordered_set(initializer_list<_Tp>,
946
              typename allocator_traits<_Allocator>::size_type = 0,
947
              _Hash                                            = _Hash(),
948
              _Pred                                            = _Pred(),
949
              _Allocator = _Allocator()) -> unordered_set<_Tp, _Hash, _Pred, _Allocator>;
950

951
template <class _InputIterator,
952
          class _Allocator,
953
          class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
954
          class = enable_if_t<__is_allocator<_Allocator>::value>>
955
unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator)
956
    -> unordered_set<__iter_value_type<_InputIterator>,
957
                     hash<__iter_value_type<_InputIterator>>,
958
                     equal_to<__iter_value_type<_InputIterator>>,
959
                     _Allocator>;
960

961
template <class _InputIterator,
962
          class _Hash,
963
          class _Allocator,
964
          class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
965
          class = enable_if_t<!__is_allocator<_Hash>::value>,
966
          class = enable_if_t<!is_integral<_Hash>::value>,
967
          class = enable_if_t<__is_allocator<_Allocator>::value>>
968
unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator)
969
    -> unordered_set<__iter_value_type<_InputIterator>, _Hash, equal_to<__iter_value_type<_InputIterator>>, _Allocator>;
970

971
#  if _LIBCPP_STD_VER >= 23
972

973
template <ranges::input_range _Range, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>>
974
unordered_set(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Allocator)
975
    -> unordered_set<ranges::range_value_t<_Range>,
976
                     hash<ranges::range_value_t<_Range>>,
977
                     equal_to<ranges::range_value_t<_Range>>,
978
                     _Allocator>;
979

980
template <ranges::input_range _Range, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>>
981
unordered_set(from_range_t, _Range&&, _Allocator)
982
    -> unordered_set<ranges::range_value_t<_Range>,
983
                     hash<ranges::range_value_t<_Range>>,
984
                     equal_to<ranges::range_value_t<_Range>>,
985
                     _Allocator>;
986

987
template <ranges::input_range _Range,
988
          class _Hash,
989
          class _Allocator,
990
          class = enable_if_t<!__is_allocator<_Hash>::value>,
991
          class = enable_if_t<!is_integral<_Hash>::value>,
992
          class = enable_if_t<__is_allocator<_Allocator>::value>>
993
unordered_set(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator)
994
    -> unordered_set<ranges::range_value_t<_Range>, _Hash, equal_to<ranges::range_value_t<_Range>>, _Allocator>;
995

996
#  endif
997

998
template <class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>>
999
unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator)
1000
    -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
1001

1002
template <class _Tp,
1003
          class _Hash,
1004
          class _Allocator,
1005
          class = enable_if_t<!__is_allocator<_Hash>::value>,
1006
          class = enable_if_t<!is_integral<_Hash>::value>,
1007
          class = enable_if_t<__is_allocator<_Allocator>::value>>
1008
unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator)
1009
    -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
1010
#endif
1011

1012
template <class _Value, class _Hash, class _Pred, class _Alloc>
1013
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql)
1014
    : __table_(__hf, __eql) {
1015
  __table_.__rehash_unique(__n);
1016
}
1017

1018
template <class _Value, class _Hash, class _Pred, class _Alloc>
1019
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(
1020
    size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
1021
    : __table_(__hf, __eql, __a) {
1022
  __table_.__rehash_unique(__n);
1023
}
1024

1025
template <class _Value, class _Hash, class _Pred, class _Alloc>
1026
template <class _InputIterator>
1027
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(_InputIterator __first, _InputIterator __last) {
1028
  insert(__first, __last);
1029
}
1030

1031
template <class _Value, class _Hash, class _Pred, class _Alloc>
1032
template <class _InputIterator>
1033
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(
1034
    _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql)
1035
    : __table_(__hf, __eql) {
1036
  __table_.__rehash_unique(__n);
1037
  insert(__first, __last);
1038
}
1039

1040
template <class _Value, class _Hash, class _Pred, class _Alloc>
1041
template <class _InputIterator>
1042
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(
1043
    _InputIterator __first,
1044
    _InputIterator __last,
1045
    size_type __n,
1046
    const hasher& __hf,
1047
    const key_equal& __eql,
1048
    const allocator_type& __a)
1049
    : __table_(__hf, __eql, __a) {
1050
  __table_.__rehash_unique(__n);
1051
  insert(__first, __last);
1052
}
1053

1054
template <class _Value, class _Hash, class _Pred, class _Alloc>
1055
inline unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(const allocator_type& __a) : __table_(__a) {}
1056

1057
template <class _Value, class _Hash, class _Pred, class _Alloc>
1058
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(const unordered_set& __u) : __table_(__u.__table_) {
1059
  __table_.__rehash_unique(__u.bucket_count());
1060
  insert(__u.begin(), __u.end());
1061
}
1062

1063
template <class _Value, class _Hash, class _Pred, class _Alloc>
1064
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(const unordered_set& __u, const allocator_type& __a)
1065
    : __table_(__u.__table_, __a) {
1066
  __table_.__rehash_unique(__u.bucket_count());
1067
  insert(__u.begin(), __u.end());
1068
}
1069

1070
#ifndef _LIBCPP_CXX03_LANG
1071

1072
template <class _Value, class _Hash, class _Pred, class _Alloc>
1073
inline unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(unordered_set&& __u)
1074
    _NOEXCEPT_(is_nothrow_move_constructible<__table>::value)
1075
    : __table_(std::move(__u.__table_)) {}
1076

1077
template <class _Value, class _Hash, class _Pred, class _Alloc>
1078
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(unordered_set&& __u, const allocator_type& __a)
1079
    : __table_(std::move(__u.__table_), __a) {
1080
  if (__a != __u.get_allocator()) {
1081
    iterator __i = __u.begin();
1082
    while (__u.size() != 0)
1083
      __table_.__insert_unique(std::move(__u.__table_.remove(__i++)->__get_value()));
1084
  }
1085
}
1086

1087
template <class _Value, class _Hash, class _Pred, class _Alloc>
1088
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(initializer_list<value_type> __il) {
1089
  insert(__il.begin(), __il.end());
1090
}
1091

1092
template <class _Value, class _Hash, class _Pred, class _Alloc>
1093
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(
1094
    initializer_list<value_type> __il, size_type __n, const hasher& __hf, const key_equal& __eql)
1095
    : __table_(__hf, __eql) {
1096
  __table_.__rehash_unique(__n);
1097
  insert(__il.begin(), __il.end());
1098
}
1099

1100
template <class _Value, class _Hash, class _Pred, class _Alloc>
1101
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(
1102
    initializer_list<value_type> __il,
1103
    size_type __n,
1104
    const hasher& __hf,
1105
    const key_equal& __eql,
1106
    const allocator_type& __a)
1107
    : __table_(__hf, __eql, __a) {
1108
  __table_.__rehash_unique(__n);
1109
  insert(__il.begin(), __il.end());
1110
}
1111

1112
template <class _Value, class _Hash, class _Pred, class _Alloc>
1113
inline unordered_set<_Value, _Hash, _Pred, _Alloc>&
1114
unordered_set<_Value, _Hash, _Pred, _Alloc>::operator=(unordered_set&& __u)
1115
    _NOEXCEPT_(is_nothrow_move_assignable<__table>::value) {
1116
  __table_ = std::move(__u.__table_);
1117
  return *this;
1118
}
1119

1120
template <class _Value, class _Hash, class _Pred, class _Alloc>
1121
inline unordered_set<_Value, _Hash, _Pred, _Alloc>&
1122
unordered_set<_Value, _Hash, _Pred, _Alloc>::operator=(initializer_list<value_type> __il) {
1123
  __table_.__assign_unique(__il.begin(), __il.end());
1124
  return *this;
1125
}
1126

1127
#endif // _LIBCPP_CXX03_LANG
1128

1129
template <class _Value, class _Hash, class _Pred, class _Alloc>
1130
template <class _InputIterator>
1131
inline void unordered_set<_Value, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) {
1132
  for (; __first != __last; ++__first)
1133
    __table_.__insert_unique(*__first);
1134
}
1135

1136
template <class _Value, class _Hash, class _Pred, class _Alloc>
1137
inline _LIBCPP_HIDE_FROM_ABI void
1138
swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
1139
    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
1140
  __x.swap(__y);
1141
}
1142

1143
#if _LIBCPP_STD_VER >= 20
1144
template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate>
1145
inline _LIBCPP_HIDE_FROM_ABI typename unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type
1146
erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) {
1147
  return std::__libcpp_erase_if_container(__c, __pred);
1148
}
1149
#endif
1150

1151
template <class _Value, class _Hash, class _Pred, class _Alloc>
1152
_LIBCPP_HIDE_FROM_ABI bool operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
1153
                                      const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) {
1154
  if (__x.size() != __y.size())
1155
    return false;
1156
  typedef typename unordered_set<_Value, _Hash, _Pred, _Alloc>::const_iterator const_iterator;
1157
  for (const_iterator __i = __x.begin(), __ex = __x.end(), __ey = __y.end(); __i != __ex; ++__i) {
1158
    const_iterator __j = __y.find(*__i);
1159
    if (__j == __ey || !(*__i == *__j))
1160
      return false;
1161
  }
1162
  return true;
1163
}
1164

1165
#if _LIBCPP_STD_VER <= 17
1166

1167
template <class _Value, class _Hash, class _Pred, class _Alloc>
1168
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
1169
                                             const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) {
1170
  return !(__x == __y);
1171
}
1172

1173
#endif
1174

1175
template <class _Value, class _Hash = hash<_Value>, class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> >
1176
class _LIBCPP_TEMPLATE_VIS unordered_multiset {
1177
public:
1178
  // types
1179
  typedef _Value key_type;
1180
  typedef key_type value_type;
1181
  typedef __type_identity_t<_Hash> hasher;
1182
  typedef __type_identity_t<_Pred> key_equal;
1183
  typedef __type_identity_t<_Alloc> allocator_type;
1184
  typedef value_type& reference;
1185
  typedef const value_type& const_reference;
1186
  static_assert(is_same<value_type, typename allocator_type::value_type>::value,
1187
                "Allocator::value_type must be same type as value_type");
1188

1189
private:
1190
  typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table;
1191

1192
  __table __table_;
1193

1194
public:
1195
  typedef typename __table::pointer pointer;
1196
  typedef typename __table::const_pointer const_pointer;
1197
  typedef typename __table::size_type size_type;
1198
  typedef typename __table::difference_type difference_type;
1199

1200
  typedef typename __table::const_iterator iterator;
1201
  typedef typename __table::const_iterator const_iterator;
1202
  typedef typename __table::const_local_iterator local_iterator;
1203
  typedef typename __table::const_local_iterator const_local_iterator;
1204

1205
#if _LIBCPP_STD_VER >= 17
1206
  typedef __set_node_handle<typename __table::__node, allocator_type> node_type;
1207
#endif
1208

1209
  template <class _Value2, class _Hash2, class _Pred2, class _Alloc2>
1210
  friend class _LIBCPP_TEMPLATE_VIS unordered_set;
1211
  template <class _Value2, class _Hash2, class _Pred2, class _Alloc2>
1212
  friend class _LIBCPP_TEMPLATE_VIS unordered_multiset;
1213

1214
  _LIBCPP_HIDE_FROM_ABI unordered_multiset() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) {}
1215
  explicit _LIBCPP_HIDE_FROM_ABI
1216
  unordered_multiset(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal());
1217
  _LIBCPP_HIDE_FROM_ABI
1218
  unordered_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
1219
#if _LIBCPP_STD_VER >= 14
1220
  inline _LIBCPP_HIDE_FROM_ABI unordered_multiset(size_type __n, const allocator_type& __a)
1221
      : unordered_multiset(__n, hasher(), key_equal(), __a) {}
1222
  inline _LIBCPP_HIDE_FROM_ABI unordered_multiset(size_type __n, const hasher& __hf, const allocator_type& __a)
1223
      : unordered_multiset(__n, __hf, key_equal(), __a) {}
1224
#endif
1225
  template <class _InputIterator>
1226
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(_InputIterator __first, _InputIterator __last);
1227
  template <class _InputIterator>
1228
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(
1229
      _InputIterator __first,
1230
      _InputIterator __last,
1231
      size_type __n,
1232
      const hasher& __hf     = hasher(),
1233
      const key_equal& __eql = key_equal());
1234
  template <class _InputIterator>
1235
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(
1236
      _InputIterator __first,
1237
      _InputIterator __last,
1238
      size_type __n,
1239
      const hasher& __hf,
1240
      const key_equal& __eql,
1241
      const allocator_type& __a);
1242

1243
#if _LIBCPP_STD_VER >= 23
1244
  template <_ContainerCompatibleRange<value_type> _Range>
1245
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(
1246
      from_range_t,
1247
      _Range&& __range,
1248
      size_type __n             = /*implementation-defined*/ 0,
1249
      const hasher& __hf        = hasher(),
1250
      const key_equal& __eql    = key_equal(),
1251
      const allocator_type& __a = allocator_type())
1252
      : __table_(__hf, __eql, __a) {
1253
    if (__n > 0) {
1254
      __table_.__rehash_multi(__n);
1255
    }
1256
    insert_range(std::forward<_Range>(__range));
1257
  }
1258
#endif
1259

1260
#if _LIBCPP_STD_VER >= 14
1261
  template <class _InputIterator>
1262
  inline _LIBCPP_HIDE_FROM_ABI
1263
  unordered_multiset(_InputIterator __first, _InputIterator __last, size_type __n, const allocator_type& __a)
1264
      : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a) {}
1265
  template <class _InputIterator>
1266
  inline _LIBCPP_HIDE_FROM_ABI unordered_multiset(
1267
      _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a)
1268
      : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a) {}
1269
#endif
1270

1271
#if _LIBCPP_STD_VER >= 23
1272
  template <_ContainerCompatibleRange<value_type> _Range>
1273
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(from_range_t, _Range&& __range, size_type __n, const allocator_type& __a)
1274
      : unordered_multiset(from_range, std::forward<_Range>(__range), __n, hasher(), key_equal(), __a) {}
1275

1276
  template <_ContainerCompatibleRange<value_type> _Range>
1277
  _LIBCPP_HIDE_FROM_ABI
1278
  unordered_multiset(from_range_t, _Range&& __range, size_type __n, const hasher& __hf, const allocator_type& __a)
1279
      : unordered_multiset(from_range, std::forward<_Range>(__range), __n, __hf, key_equal(), __a) {}
1280
#endif
1281

1282
  _LIBCPP_HIDE_FROM_ABI explicit unordered_multiset(const allocator_type& __a);
1283
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(const unordered_multiset& __u);
1284
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(const unordered_multiset& __u, const allocator_type& __a);
1285
#ifndef _LIBCPP_CXX03_LANG
1286
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(unordered_multiset&& __u)
1287
      _NOEXCEPT_(is_nothrow_move_constructible<__table>::value);
1288
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(unordered_multiset&& __u, const allocator_type& __a);
1289
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(initializer_list<value_type> __il);
1290
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(
1291
      initializer_list<value_type> __il,
1292
      size_type __n,
1293
      const hasher& __hf     = hasher(),
1294
      const key_equal& __eql = key_equal());
1295
  _LIBCPP_HIDE_FROM_ABI unordered_multiset(
1296
      initializer_list<value_type> __il,
1297
      size_type __n,
1298
      const hasher& __hf,
1299
      const key_equal& __eql,
1300
      const allocator_type& __a);
1301
#  if _LIBCPP_STD_VER >= 14
1302
  inline _LIBCPP_HIDE_FROM_ABI
1303
  unordered_multiset(initializer_list<value_type> __il, size_type __n, const allocator_type& __a)
1304
      : unordered_multiset(__il, __n, hasher(), key_equal(), __a) {}
1305
  inline _LIBCPP_HIDE_FROM_ABI
1306
  unordered_multiset(initializer_list<value_type> __il, size_type __n, const hasher& __hf, const allocator_type& __a)
1307
      : unordered_multiset(__il, __n, __hf, key_equal(), __a) {}
1308
#  endif
1309
#endif // _LIBCPP_CXX03_LANG
1310
  _LIBCPP_HIDE_FROM_ABI ~unordered_multiset() {
1311
    static_assert(sizeof(std::__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), "");
1312
  }
1313

1314
  _LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(const unordered_multiset& __u) {
1315
    __table_ = __u.__table_;
1316
    return *this;
1317
  }
1318
#ifndef _LIBCPP_CXX03_LANG
1319
  _LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(unordered_multiset&& __u)
1320
      _NOEXCEPT_(is_nothrow_move_assignable<__table>::value);
1321
  _LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(initializer_list<value_type> __il);
1322
#endif // _LIBCPP_CXX03_LANG
1323

1324
  _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
1325
    return allocator_type(__table_.__node_alloc());
1326
  }
1327

1328
  _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __table_.size() == 0; }
1329
  _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __table_.size(); }
1330
  _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { return __table_.max_size(); }
1331

1332
  _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __table_.begin(); }
1333
  _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __table_.end(); }
1334
  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __table_.begin(); }
1335
  _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __table_.end(); }
1336
  _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT { return __table_.begin(); }
1337
  _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT { return __table_.end(); }
1338

1339
#ifndef _LIBCPP_CXX03_LANG
1340
  template <class... _Args>
1341
  _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) {
1342
    return __table_.__emplace_multi(std::forward<_Args>(__args)...);
1343
  }
1344
  template <class... _Args>
1345
  _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __p, _Args&&... __args) {
1346
    return __table_.__emplace_hint_multi(__p, std::forward<_Args>(__args)...);
1347
  }
1348

1349
  _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return __table_.__insert_multi(std::move(__x)); }
1350
  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, value_type&& __x) {
1351
    return __table_.__insert_multi(__p, std::move(__x));
1352
  }
1353
  _LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }
1354
#endif // _LIBCPP_CXX03_LANG
1355

1356
  _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__insert_multi(__x); }
1357

1358
  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, const value_type& __x) {
1359
    return __table_.__insert_multi(__p, __x);
1360
  }
1361

1362
  template <class _InputIterator>
1363
  _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last);
1364

1365
#if _LIBCPP_STD_VER >= 23
1366
  template <_ContainerCompatibleRange<value_type> _Range>
1367
  _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
1368
    for (auto&& __element : __range) {
1369
      __table_.__insert_multi(std::forward<decltype(__element)>(__element));
1370
    }
1371
  }
1372
#endif
1373

1374
#if _LIBCPP_STD_VER >= 17
1375
  _LIBCPP_HIDE_FROM_ABI iterator insert(node_type&& __nh) {
1376
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(),
1377
                                        "node_type with incompatible allocator passed to unordered_multiset::insert()");
1378
    return __table_.template __node_handle_insert_multi<node_type>(std::move(__nh));
1379
  }
1380
  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, node_type&& __nh) {
1381
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(),
1382
                                        "node_type with incompatible allocator passed to unordered_multiset::insert()");
1383
    return __table_.template __node_handle_insert_multi<node_type>(__hint, std::move(__nh));
1384
  }
1385
  _LIBCPP_HIDE_FROM_ABI node_type extract(const_iterator __position) {
1386
    return __table_.template __node_handle_extract<node_type>(__position);
1387
  }
1388
  _LIBCPP_HIDE_FROM_ABI node_type extract(key_type const& __key) {
1389
    return __table_.template __node_handle_extract<node_type>(__key);
1390
  }
1391

1392
  template <class _H2, class _P2>
1393
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>& __source) {
1394
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
1395
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
1396
    return __table_.__node_handle_merge_multi(__source.__table_);
1397
  }
1398
  template <class _H2, class _P2>
1399
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>&& __source) {
1400
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
1401
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
1402
    return __table_.__node_handle_merge_multi(__source.__table_);
1403
  }
1404
  template <class _H2, class _P2>
1405
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_set<key_type, _H2, _P2, allocator_type>& __source) {
1406
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
1407
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
1408
    return __table_.__node_handle_merge_multi(__source.__table_);
1409
  }
1410
  template <class _H2, class _P2>
1411
  _LIBCPP_HIDE_FROM_ABI void merge(unordered_set<key_type, _H2, _P2, allocator_type>&& __source) {
1412
    _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
1413
        __source.get_allocator() == get_allocator(), "merging container with incompatible allocator");
1414
    return __table_.__node_handle_merge_multi(__source.__table_);
1415
  }
1416
#endif
1417

1418
  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p) { return __table_.erase(__p); }
1419
  _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_multi(__k); }
1420
  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
1421
    return __table_.erase(__first, __last);
1422
  }
1423
  _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __table_.clear(); }
1424

1425
  _LIBCPP_HIDE_FROM_ABI void swap(unordered_multiset& __u) _NOEXCEPT_(__is_nothrow_swappable_v<__table>) {
1426
    __table_.swap(__u.__table_);
1427
  }
1428

1429
  _LIBCPP_HIDE_FROM_ABI hasher hash_function() const { return __table_.hash_function(); }
1430
  _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq(); }
1431

1432
  _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
1433
  _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
1434
#if _LIBCPP_STD_VER >= 20
1435
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1436
  _LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) {
1437
    return __table_.find(__k);
1438
  }
1439
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1440
  _LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const {
1441
    return __table_.find(__k);
1442
  }
1443
#endif // _LIBCPP_STD_VER >= 20
1444

1445
  _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_multi(__k); }
1446
#if _LIBCPP_STD_VER >= 20
1447
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1448
  _LIBCPP_HIDE_FROM_ABI size_type count(const _K2& __k) const {
1449
    return __table_.__count_multi(__k);
1450
  }
1451
#endif // _LIBCPP_STD_VER >= 20
1452

1453
#if _LIBCPP_STD_VER >= 20
1454
  _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); }
1455

1456
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1457
  _LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const {
1458
    return find(__k) != end();
1459
  }
1460
#endif // _LIBCPP_STD_VER >= 20
1461

1462
  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __k) {
1463
    return __table_.__equal_range_multi(__k);
1464
  }
1465
  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
1466
    return __table_.__equal_range_multi(__k);
1467
  }
1468
#if _LIBCPP_STD_VER >= 20
1469
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1470
  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _K2& __k) {
1471
    return __table_.__equal_range_multi(__k);
1472
  }
1473
  template <class _K2, enable_if_t<__is_transparent_v<hasher, _K2> && __is_transparent_v<key_equal, _K2>>* = nullptr>
1474
  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {
1475
    return __table_.__equal_range_multi(__k);
1476
  }
1477
#endif // _LIBCPP_STD_VER >= 20
1478

1479
  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __table_.bucket_count(); }
1480
  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return __table_.max_bucket_count(); }
1481

1482
  _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const { return __table_.bucket_size(__n); }
1483
  _LIBCPP_HIDE_FROM_ABI size_type bucket(const key_type& __k) const { return __table_.bucket(__k); }
1484

1485
  _LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) { return __table_.begin(__n); }
1486
  _LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) { return __table_.end(__n); }
1487
  _LIBCPP_HIDE_FROM_ABI const_local_iterator begin(size_type __n) const { return __table_.cbegin(__n); }
1488
  _LIBCPP_HIDE_FROM_ABI const_local_iterator end(size_type __n) const { return __table_.cend(__n); }
1489
  _LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const { return __table_.cbegin(__n); }
1490
  _LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const { return __table_.cend(__n); }
1491

1492
  _LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT { return __table_.load_factor(); }
1493
  _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __table_.max_load_factor(); }
1494
  _LIBCPP_HIDE_FROM_ABI void max_load_factor(float __mlf) { __table_.max_load_factor(__mlf); }
1495
  _LIBCPP_HIDE_FROM_ABI void rehash(size_type __n) { __table_.__rehash_multi(__n); }
1496
  _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n) { __table_.__reserve_multi(__n); }
1497
};
1498

1499
#if _LIBCPP_STD_VER >= 17
1500
template <class _InputIterator,
1501
          class _Hash      = hash<__iter_value_type<_InputIterator>>,
1502
          class _Pred      = equal_to<__iter_value_type<_InputIterator>>,
1503
          class _Allocator = allocator<__iter_value_type<_InputIterator>>,
1504
          class            = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
1505
          class            = enable_if_t<!__is_allocator<_Hash>::value>,
1506
          class            = enable_if_t<!is_integral<_Hash>::value>,
1507
          class            = enable_if_t<!__is_allocator<_Pred>::value>,
1508
          class            = enable_if_t<__is_allocator<_Allocator>::value>>
1509
unordered_multiset(
1510
    _InputIterator,
1511
    _InputIterator,
1512
    typename allocator_traits<_Allocator>::size_type = 0,
1513
    _Hash                                            = _Hash(),
1514
    _Pred                                            = _Pred(),
1515
    _Allocator = _Allocator()) -> unordered_multiset<__iter_value_type<_InputIterator>, _Hash, _Pred, _Allocator>;
1516

1517
#  if _LIBCPP_STD_VER >= 23
1518
template <ranges::input_range _Range,
1519
          class _Hash      = hash<ranges::range_value_t<_Range>>,
1520
          class _Pred      = equal_to<ranges::range_value_t<_Range>>,
1521
          class _Allocator = allocator<ranges::range_value_t<_Range>>,
1522
          class            = enable_if_t<!__is_allocator<_Hash>::value>,
1523
          class            = enable_if_t<!is_integral<_Hash>::value>,
1524
          class            = enable_if_t<!__is_allocator<_Pred>::value>,
1525
          class            = enable_if_t<__is_allocator<_Allocator>::value>>
1526
unordered_multiset(
1527
    from_range_t,
1528
    _Range&&,
1529
    typename allocator_traits<_Allocator>::size_type = 0,
1530
    _Hash                                            = _Hash(),
1531
    _Pred                                            = _Pred(),
1532
    _Allocator = _Allocator()) -> unordered_multiset<ranges::range_value_t<_Range>, _Hash, _Pred, _Allocator>; // C++23
1533
#  endif
1534

1535
template <class _Tp,
1536
          class _Hash      = hash<_Tp>,
1537
          class _Pred      = equal_to<_Tp>,
1538
          class _Allocator = allocator<_Tp>,
1539
          class            = enable_if_t<!__is_allocator<_Hash>::value>,
1540
          class            = enable_if_t<!is_integral<_Hash>::value>,
1541
          class            = enable_if_t<!__is_allocator<_Pred>::value>,
1542
          class            = enable_if_t<__is_allocator<_Allocator>::value>>
1543
unordered_multiset(initializer_list<_Tp>,
1544
                   typename allocator_traits<_Allocator>::size_type = 0,
1545
                   _Hash                                            = _Hash(),
1546
                   _Pred                                            = _Pred(),
1547
                   _Allocator = _Allocator()) -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>;
1548

1549
template <class _InputIterator,
1550
          class _Allocator,
1551
          class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
1552
          class = enable_if_t<__is_allocator<_Allocator>::value>>
1553
unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator)
1554
    -> unordered_multiset<__iter_value_type<_InputIterator>,
1555
                          hash<__iter_value_type<_InputIterator>>,
1556
                          equal_to<__iter_value_type<_InputIterator>>,
1557
                          _Allocator>;
1558

1559
template <class _InputIterator,
1560
          class _Hash,
1561
          class _Allocator,
1562
          class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>,
1563
          class = enable_if_t<!__is_allocator<_Hash>::value>,
1564
          class = enable_if_t<!is_integral<_Hash>::value>,
1565
          class = enable_if_t<__is_allocator<_Allocator>::value>>
1566
unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator)
1567
    -> unordered_multiset<__iter_value_type<_InputIterator>,
1568
                          _Hash,
1569
                          equal_to<__iter_value_type<_InputIterator>>,
1570
                          _Allocator>;
1571

1572
#  if _LIBCPP_STD_VER >= 23
1573

1574
template <ranges::input_range _Range, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>>
1575
unordered_multiset(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Allocator)
1576
    -> unordered_multiset<ranges::range_value_t<_Range>,
1577
                          hash<ranges::range_value_t<_Range>>,
1578
                          equal_to<ranges::range_value_t<_Range>>,
1579
                          _Allocator>;
1580

1581
template <ranges::input_range _Range, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>>
1582
unordered_multiset(from_range_t, _Range&&, _Allocator)
1583
    -> unordered_multiset<ranges::range_value_t<_Range>,
1584
                          hash<ranges::range_value_t<_Range>>,
1585
                          equal_to<ranges::range_value_t<_Range>>,
1586
                          _Allocator>;
1587

1588
template <ranges::input_range _Range,
1589
          class _Hash,
1590
          class _Allocator,
1591
          class = enable_if_t<!__is_allocator<_Hash>::value>,
1592
          class = enable_if_t<!is_integral<_Hash>::value>,
1593
          class = enable_if_t<__is_allocator<_Allocator>::value>>
1594
unordered_multiset(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator)
1595
    -> unordered_multiset<ranges::range_value_t<_Range>, _Hash, equal_to<ranges::range_value_t<_Range>>, _Allocator>;
1596

1597
#  endif
1598

1599
template <class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>>
1600
unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator)
1601
    -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
1602

1603
template <class _Tp,
1604
          class _Hash,
1605
          class _Allocator,
1606
          class = enable_if_t<!__is_allocator<_Hash>::value>,
1607
          class = enable_if_t<!is_integral<_Hash>::value>,
1608
          class = enable_if_t<__is_allocator<_Allocator>::value>>
1609
unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator)
1610
    -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
1611
#endif
1612

1613
template <class _Value, class _Hash, class _Pred, class _Alloc>
1614
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1615
    size_type __n, const hasher& __hf, const key_equal& __eql)
1616
    : __table_(__hf, __eql) {
1617
  __table_.__rehash_multi(__n);
1618
}
1619

1620
template <class _Value, class _Hash, class _Pred, class _Alloc>
1621
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1622
    size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
1623
    : __table_(__hf, __eql, __a) {
1624
  __table_.__rehash_multi(__n);
1625
}
1626

1627
template <class _Value, class _Hash, class _Pred, class _Alloc>
1628
template <class _InputIterator>
1629
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(_InputIterator __first, _InputIterator __last) {
1630
  insert(__first, __last);
1631
}
1632

1633
template <class _Value, class _Hash, class _Pred, class _Alloc>
1634
template <class _InputIterator>
1635
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1636
    _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql)
1637
    : __table_(__hf, __eql) {
1638
  __table_.__rehash_multi(__n);
1639
  insert(__first, __last);
1640
}
1641

1642
template <class _Value, class _Hash, class _Pred, class _Alloc>
1643
template <class _InputIterator>
1644
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1645
    _InputIterator __first,
1646
    _InputIterator __last,
1647
    size_type __n,
1648
    const hasher& __hf,
1649
    const key_equal& __eql,
1650
    const allocator_type& __a)
1651
    : __table_(__hf, __eql, __a) {
1652
  __table_.__rehash_multi(__n);
1653
  insert(__first, __last);
1654
}
1655

1656
template <class _Value, class _Hash, class _Pred, class _Alloc>
1657
inline unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(const allocator_type& __a)
1658
    : __table_(__a) {}
1659

1660
template <class _Value, class _Hash, class _Pred, class _Alloc>
1661
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(const unordered_multiset& __u)
1662
    : __table_(__u.__table_) {
1663
  __table_.__rehash_multi(__u.bucket_count());
1664
  insert(__u.begin(), __u.end());
1665
}
1666

1667
template <class _Value, class _Hash, class _Pred, class _Alloc>
1668
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1669
    const unordered_multiset& __u, const allocator_type& __a)
1670
    : __table_(__u.__table_, __a) {
1671
  __table_.__rehash_multi(__u.bucket_count());
1672
  insert(__u.begin(), __u.end());
1673
}
1674

1675
#ifndef _LIBCPP_CXX03_LANG
1676

1677
template <class _Value, class _Hash, class _Pred, class _Alloc>
1678
inline unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(unordered_multiset&& __u)
1679
    _NOEXCEPT_(is_nothrow_move_constructible<__table>::value)
1680
    : __table_(std::move(__u.__table_)) {}
1681

1682
template <class _Value, class _Hash, class _Pred, class _Alloc>
1683
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1684
    unordered_multiset&& __u, const allocator_type& __a)
1685
    : __table_(std::move(__u.__table_), __a) {
1686
  if (__a != __u.get_allocator()) {
1687
    iterator __i = __u.begin();
1688
    while (__u.size() != 0)
1689
      __table_.__insert_multi(std::move(__u.__table_.remove(__i++)->__get_value()));
1690
  }
1691
}
1692

1693
template <class _Value, class _Hash, class _Pred, class _Alloc>
1694
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(initializer_list<value_type> __il) {
1695
  insert(__il.begin(), __il.end());
1696
}
1697

1698
template <class _Value, class _Hash, class _Pred, class _Alloc>
1699
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1700
    initializer_list<value_type> __il, size_type __n, const hasher& __hf, const key_equal& __eql)
1701
    : __table_(__hf, __eql) {
1702
  __table_.__rehash_multi(__n);
1703
  insert(__il.begin(), __il.end());
1704
}
1705

1706
template <class _Value, class _Hash, class _Pred, class _Alloc>
1707
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
1708
    initializer_list<value_type> __il,
1709
    size_type __n,
1710
    const hasher& __hf,
1711
    const key_equal& __eql,
1712
    const allocator_type& __a)
1713
    : __table_(__hf, __eql, __a) {
1714
  __table_.__rehash_multi(__n);
1715
  insert(__il.begin(), __il.end());
1716
}
1717

1718
template <class _Value, class _Hash, class _Pred, class _Alloc>
1719
inline unordered_multiset<_Value, _Hash, _Pred, _Alloc>&
1720
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::operator=(unordered_multiset&& __u)
1721
    _NOEXCEPT_(is_nothrow_move_assignable<__table>::value) {
1722
  __table_ = std::move(__u.__table_);
1723
  return *this;
1724
}
1725

1726
template <class _Value, class _Hash, class _Pred, class _Alloc>
1727
inline unordered_multiset<_Value, _Hash, _Pred, _Alloc>&
1728
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::operator=(initializer_list<value_type> __il) {
1729
  __table_.__assign_multi(__il.begin(), __il.end());
1730
  return *this;
1731
}
1732

1733
#endif // _LIBCPP_CXX03_LANG
1734

1735
template <class _Value, class _Hash, class _Pred, class _Alloc>
1736
template <class _InputIterator>
1737
inline void unordered_multiset<_Value, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) {
1738
  for (; __first != __last; ++__first)
1739
    __table_.__insert_multi(*__first);
1740
}
1741

1742
template <class _Value, class _Hash, class _Pred, class _Alloc>
1743
inline _LIBCPP_HIDE_FROM_ABI void
1744
swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1745
    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
1746
  __x.swap(__y);
1747
}
1748

1749
#if _LIBCPP_STD_VER >= 20
1750
template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate>
1751
inline _LIBCPP_HIDE_FROM_ABI typename unordered_multiset<_Value, _Hash, _Pred, _Alloc>::size_type
1752
erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred) {
1753
  return std::__libcpp_erase_if_container(__c, __pred);
1754
}
1755
#endif
1756

1757
template <class _Value, class _Hash, class _Pred, class _Alloc>
1758
_LIBCPP_HIDE_FROM_ABI bool operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1759
                                      const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) {
1760
  if (__x.size() != __y.size())
1761
    return false;
1762
  typedef typename unordered_multiset<_Value, _Hash, _Pred, _Alloc>::const_iterator const_iterator;
1763
  typedef pair<const_iterator, const_iterator> _EqRng;
1764
  for (const_iterator __i = __x.begin(), __ex = __x.end(); __i != __ex;) {
1765
    _EqRng __xeq = __x.equal_range(*__i);
1766
    _EqRng __yeq = __y.equal_range(*__i);
1767
    if (std::distance(__xeq.first, __xeq.second) != std::distance(__yeq.first, __yeq.second) ||
1768
        !std::is_permutation(__xeq.first, __xeq.second, __yeq.first))
1769
      return false;
1770
    __i = __xeq.second;
1771
  }
1772
  return true;
1773
}
1774

1775
#if _LIBCPP_STD_VER <= 17
1776

1777
template <class _Value, class _Hash, class _Pred, class _Alloc>
1778
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1779
                                             const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) {
1780
  return !(__x == __y);
1781
}
1782

1783
#endif
1784

1785
_LIBCPP_END_NAMESPACE_STD
1786

1787
#if _LIBCPP_STD_VER >= 17
1788
_LIBCPP_BEGIN_NAMESPACE_STD
1789
namespace pmr {
1790
template <class _KeyT, class _HashT = std::hash<_KeyT>, class _PredT = std::equal_to<_KeyT>>
1791
using unordered_set _LIBCPP_AVAILABILITY_PMR = std::unordered_set<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>;
1792

1793
template <class _KeyT, class _HashT = std::hash<_KeyT>, class _PredT = std::equal_to<_KeyT>>
1794
using unordered_multiset _LIBCPP_AVAILABILITY_PMR =
1795
    std::unordered_multiset<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>;
1796
} // namespace pmr
1797
_LIBCPP_END_NAMESPACE_STD
1798
#endif
1799

1800
_LIBCPP_POP_MACROS
1801

1802
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
1803
#  include <concepts>
1804
#  include <cstdlib>
1805
#  include <functional>
1806
#  include <iterator>
1807
#  include <stdexcept>
1808
#  include <type_traits>
1809
#endif
1810

1811
#endif // _LIBCPP_UNORDERED_SET
1812

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.