llvm-project

Форк
0
/
__hash_table 
2044 строки · 84.1 Кб
1
// -*- C++ -*-
2
//===----------------------------------------------------------------------===//
3
//
4
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5
// See https://llvm.org/LICENSE.txt for license information.
6
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
//
8
//===----------------------------------------------------------------------===//
9

10
#ifndef _LIBCPP___HASH_TABLE
11
#define _LIBCPP___HASH_TABLE
12

13
#include <__algorithm/max.h>
14
#include <__algorithm/min.h>
15
#include <__assert>
16
#include <__bit/countl.h>
17
#include <__config>
18
#include <__functional/hash.h>
19
#include <__functional/invoke.h>
20
#include <__iterator/iterator_traits.h>
21
#include <__memory/addressof.h>
22
#include <__memory/allocator_traits.h>
23
#include <__memory/compressed_pair.h>
24
#include <__memory/construct_at.h>
25
#include <__memory/pointer_traits.h>
26
#include <__memory/swap_allocator.h>
27
#include <__memory/unique_ptr.h>
28
#include <__type_traits/can_extract_key.h>
29
#include <__type_traits/conditional.h>
30
#include <__type_traits/is_const.h>
31
#include <__type_traits/is_constructible.h>
32
#include <__type_traits/is_nothrow_assignable.h>
33
#include <__type_traits/is_nothrow_constructible.h>
34
#include <__type_traits/is_pointer.h>
35
#include <__type_traits/is_reference.h>
36
#include <__type_traits/is_swappable.h>
37
#include <__type_traits/remove_const.h>
38
#include <__type_traits/remove_cvref.h>
39
#include <__utility/forward.h>
40
#include <__utility/move.h>
41
#include <__utility/pair.h>
42
#include <__utility/swap.h>
43
#include <cmath>
44
#include <cstring>
45
#include <initializer_list>
46
#include <new> // __launder
47

48
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
49
#  pragma GCC system_header
50
#endif
51

52
_LIBCPP_PUSH_MACROS
53
#include <__undef_macros>
54

55
_LIBCPP_BEGIN_NAMESPACE_STD
56

57
template <class _Key, class _Tp>
58
struct __hash_value_type;
59

60
template <class _Tp>
61
struct __is_hash_value_type_imp : false_type {};
62

63
template <class _Key, class _Value>
64
struct __is_hash_value_type_imp<__hash_value_type<_Key, _Value> > : true_type {};
65

66
template <class... _Args>
67
struct __is_hash_value_type : false_type {};
68

69
template <class _One>
70
struct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {};
71

72
_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t __n);
73

74
template <class _NodePtr>
75
struct __hash_node_base {
76
  typedef typename pointer_traits<_NodePtr>::element_type __node_type;
77
  typedef __hash_node_base __first_node;
78
  typedef __rebind_pointer_t<_NodePtr, __first_node> __node_base_pointer;
79
  typedef _NodePtr __node_pointer;
80

81
#if defined(_LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB)
82
  typedef __node_base_pointer __next_pointer;
83
#else
84
  typedef __conditional_t<is_pointer<__node_pointer>::value, __node_base_pointer, __node_pointer> __next_pointer;
85
#endif
86

87
  __next_pointer __next_;
88

89
  _LIBCPP_HIDE_FROM_ABI __next_pointer __ptr() _NOEXCEPT {
90
    return static_cast<__next_pointer>(pointer_traits<__node_base_pointer>::pointer_to(*this));
91
  }
92

93
  _LIBCPP_HIDE_FROM_ABI __node_pointer __upcast() _NOEXCEPT {
94
    return static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(*this));
95
  }
96

97
  _LIBCPP_HIDE_FROM_ABI size_t __hash() const _NOEXCEPT { return static_cast<__node_type const&>(*this).__hash_; }
98

99
  _LIBCPP_HIDE_FROM_ABI __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
100
  _LIBCPP_HIDE_FROM_ABI explicit __hash_node_base(__next_pointer __next) _NOEXCEPT : __next_(__next) {}
101
};
102

103
template <class _Tp, class _VoidPtr>
104
struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > {
105
  typedef _Tp __node_value_type;
106
  using _Base          = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >;
107
  using __next_pointer = typename _Base::__next_pointer;
108

109
  size_t __hash_;
110

111
  // We allow starting the lifetime of nodes without initializing the value held by the node,
112
  // since that is handled by the hash table itself in order to be allocator-aware.
113
#ifndef _LIBCPP_CXX03_LANG
114

115
private:
116
  union {
117
    _Tp __value_;
118
  };
119

120
public:
121
  _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
122
#else
123

124
private:
125
  _ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)];
126

127
public:
128
  _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); }
129
#endif
130

131
  _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash) : _Base(__next), __hash_(__hash) {}
132
  _LIBCPP_HIDE_FROM_ABI ~__hash_node() {}
133
};
134

135
inline _LIBCPP_HIDE_FROM_ABI bool __is_hash_power2(size_t __bc) { return __bc > 2 && !(__bc & (__bc - 1)); }
136

137
inline _LIBCPP_HIDE_FROM_ABI size_t __constrain_hash(size_t __h, size_t __bc) {
138
  return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : (__h < __bc ? __h : __h % __bc);
139
}
140

141
inline _LIBCPP_HIDE_FROM_ABI size_t __next_hash_pow2(size_t __n) {
142
  return __n < 2 ? __n : (size_t(1) << (numeric_limits<size_t>::digits - __libcpp_clz(__n - 1)));
143
}
144

145
template <class _Tp, class _Hash, class _Equal, class _Alloc>
146
class __hash_table;
147

148
template <class _NodePtr>
149
class _LIBCPP_TEMPLATE_VIS __hash_iterator;
150
template <class _ConstNodePtr>
151
class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
152
template <class _NodePtr>
153
class _LIBCPP_TEMPLATE_VIS __hash_local_iterator;
154
template <class _ConstNodePtr>
155
class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
156
template <class _HashIterator>
157
class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
158
template <class _HashIterator>
159
class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
160

161
template <class _Tp>
162
struct __hash_key_value_types {
163
  static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
164
  typedef _Tp key_type;
165
  typedef _Tp __node_value_type;
166
  typedef _Tp __container_value_type;
167
  static const bool __is_map = false;
168

169
  _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; }
170
  _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; }
171
  _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); }
172
  _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); }
173
};
174

175
template <class _Key, class _Tp>
176
struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
177
  typedef _Key key_type;
178
  typedef _Tp mapped_type;
179
  typedef __hash_value_type<_Key, _Tp> __node_value_type;
180
  typedef pair<const _Key, _Tp> __container_value_type;
181
  typedef __container_value_type __map_value_type;
182
  static const bool __is_map = true;
183

184
  _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__container_value_type const& __v) { return __v.first; }
185

186
  template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __node_value_type>::value, int> = 0>
187
  _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
188
    return __t.__get_value();
189
  }
190

191
  template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
192
  _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
193
    return __t;
194
  }
195

196
  _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
197
    return std::addressof(__n.__get_value());
198
  }
199
  _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
200
};
201

202
template <class _Tp, class _AllocPtr, class _KVTypes = __hash_key_value_types<_Tp>, bool = _KVTypes::__is_map>
203
struct __hash_map_pointer_types {};
204

205
template <class _Tp, class _AllocPtr, class _KVTypes>
206
struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
207
  typedef typename _KVTypes::__map_value_type _Mv;
208
  typedef __rebind_pointer_t<_AllocPtr, _Mv> __map_value_type_pointer;
209
  typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer;
210
};
211

212
template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
213
struct __hash_node_types;
214

215
template <class _NodePtr, class _Tp, class _VoidPtr>
216
struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
217
    : public __hash_key_value_types<_Tp>,
218
      __hash_map_pointer_types<_Tp, _VoidPtr>
219

220
{
221
  typedef __hash_key_value_types<_Tp> __base;
222

223
public:
224
  typedef ptrdiff_t difference_type;
225
  typedef size_t size_type;
226

227
  typedef __rebind_pointer_t<_NodePtr, void> __void_pointer;
228

229
  typedef typename pointer_traits<_NodePtr>::element_type __node_type;
230
  typedef _NodePtr __node_pointer;
231

232
  typedef __hash_node_base<__node_pointer> __node_base_type;
233
  typedef __rebind_pointer_t<_NodePtr, __node_base_type> __node_base_pointer;
234

235
  typedef typename __node_base_type::__next_pointer __next_pointer;
236

237
  typedef _Tp __node_value_type;
238
  typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer;
239
  typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer;
240

241
private:
242
  static_assert(!is_const<__node_type>::value, "_NodePtr should never be a pointer to const");
243
  static_assert(is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value,
244
                "_VoidPtr does not point to unqualified void type");
245
  static_assert(is_same<__rebind_pointer_t<_VoidPtr, __node_type>, _NodePtr>::value,
246
                "_VoidPtr does not rebind to _NodePtr.");
247
};
248

249
template <class _HashIterator>
250
struct __hash_node_types_from_iterator;
251
template <class _NodePtr>
252
struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
253
template <class _NodePtr>
254
struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
255
template <class _NodePtr>
256
struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
257
template <class _NodePtr>
258
struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
259

260
template <class _NodeValueTp, class _VoidPtr>
261
struct __make_hash_node_types {
262
  typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp;
263
  typedef __rebind_pointer_t<_VoidPtr, _NodeTp> _NodePtr;
264
  typedef __hash_node_types<_NodePtr> type;
265
};
266

267
template <class _NodePtr>
268
class _LIBCPP_TEMPLATE_VIS __hash_iterator {
269
  typedef __hash_node_types<_NodePtr> _NodeTypes;
270
  typedef _NodePtr __node_pointer;
271
  typedef typename _NodeTypes::__next_pointer __next_pointer;
272

273
  __next_pointer __node_;
274

275
public:
276
  typedef forward_iterator_tag iterator_category;
277
  typedef typename _NodeTypes::__node_value_type value_type;
278
  typedef typename _NodeTypes::difference_type difference_type;
279
  typedef value_type& reference;
280
  typedef typename _NodeTypes::__node_value_type_pointer pointer;
281

282
  _LIBCPP_HIDE_FROM_ABI __hash_iterator() _NOEXCEPT : __node_(nullptr) {}
283

284
  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
285
    _LIBCPP_ASSERT_NON_NULL(
286
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
287
    return __node_->__upcast()->__get_value();
288
  }
289

290
  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
291
    _LIBCPP_ASSERT_NON_NULL(
292
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
293
    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
294
  }
295

296
  _LIBCPP_HIDE_FROM_ABI __hash_iterator& operator++() {
297
    _LIBCPP_ASSERT_NON_NULL(
298
        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container iterator");
299
    __node_ = __node_->__next_;
300
    return *this;
301
  }
302

303
  _LIBCPP_HIDE_FROM_ABI __hash_iterator operator++(int) {
304
    __hash_iterator __t(*this);
305
    ++(*this);
306
    return __t;
307
  }
308

309
  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_iterator& __x, const __hash_iterator& __y) {
310
    return __x.__node_ == __y.__node_;
311
  }
312
  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y) {
313
    return !(__x == __y);
314
  }
315

316
private:
317
  _LIBCPP_HIDE_FROM_ABI explicit __hash_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) {}
318

319
  template <class, class, class, class>
320
  friend class __hash_table;
321
  template <class>
322
  friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
323
  template <class>
324
  friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
325
  template <class, class, class, class, class>
326
  friend class _LIBCPP_TEMPLATE_VIS unordered_map;
327
  template <class, class, class, class, class>
328
  friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
329
};
330

331
template <class _NodePtr>
332
class _LIBCPP_TEMPLATE_VIS __hash_const_iterator {
333
  static_assert(!is_const<typename pointer_traits<_NodePtr>::element_type>::value, "");
334
  typedef __hash_node_types<_NodePtr> _NodeTypes;
335
  typedef _NodePtr __node_pointer;
336
  typedef typename _NodeTypes::__next_pointer __next_pointer;
337

338
  __next_pointer __node_;
339

340
public:
341
  typedef __hash_iterator<_NodePtr> __non_const_iterator;
342

343
  typedef forward_iterator_tag iterator_category;
344
  typedef typename _NodeTypes::__node_value_type value_type;
345
  typedef typename _NodeTypes::difference_type difference_type;
346
  typedef const value_type& reference;
347
  typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
348

349
  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator() _NOEXCEPT : __node_(nullptr) {}
350

351
  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) {}
352

353
  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
354
    _LIBCPP_ASSERT_NON_NULL(
355
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
356
    return __node_->__upcast()->__get_value();
357
  }
358
  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
359
    _LIBCPP_ASSERT_NON_NULL(
360
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
361
    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
362
  }
363

364
  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator& operator++() {
365
    _LIBCPP_ASSERT_NON_NULL(
366
        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_iterator");
367
    __node_ = __node_->__next_;
368
    return *this;
369
  }
370

371
  _LIBCPP_HIDE_FROM_ABI __hash_const_iterator operator++(int) {
372
    __hash_const_iterator __t(*this);
373
    ++(*this);
374
    return __t;
375
  }
376

377
  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y) {
378
    return __x.__node_ == __y.__node_;
379
  }
380
  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y) {
381
    return !(__x == __y);
382
  }
383

384
private:
385
  _LIBCPP_HIDE_FROM_ABI explicit __hash_const_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) {}
386

387
  template <class, class, class, class>
388
  friend class __hash_table;
389
  template <class>
390
  friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
391
  template <class, class, class, class, class>
392
  friend class _LIBCPP_TEMPLATE_VIS unordered_map;
393
  template <class, class, class, class, class>
394
  friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
395
};
396

397
template <class _NodePtr>
398
class _LIBCPP_TEMPLATE_VIS __hash_local_iterator {
399
  typedef __hash_node_types<_NodePtr> _NodeTypes;
400
  typedef _NodePtr __node_pointer;
401
  typedef typename _NodeTypes::__next_pointer __next_pointer;
402

403
  __next_pointer __node_;
404
  size_t __bucket_;
405
  size_t __bucket_count_;
406

407
public:
408
  typedef forward_iterator_tag iterator_category;
409
  typedef typename _NodeTypes::__node_value_type value_type;
410
  typedef typename _NodeTypes::difference_type difference_type;
411
  typedef value_type& reference;
412
  typedef typename _NodeTypes::__node_value_type_pointer pointer;
413

414
  _LIBCPP_HIDE_FROM_ABI __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {}
415

416
  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
417
    _LIBCPP_ASSERT_NON_NULL(
418
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
419
    return __node_->__upcast()->__get_value();
420
  }
421

422
  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
423
    _LIBCPP_ASSERT_NON_NULL(
424
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
425
    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
426
  }
427

428
  _LIBCPP_HIDE_FROM_ABI __hash_local_iterator& operator++() {
429
    _LIBCPP_ASSERT_NON_NULL(
430
        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container local_iterator");
431
    __node_ = __node_->__next_;
432
    if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
433
      __node_ = nullptr;
434
    return *this;
435
  }
436

437
  _LIBCPP_HIDE_FROM_ABI __hash_local_iterator operator++(int) {
438
    __hash_local_iterator __t(*this);
439
    ++(*this);
440
    return __t;
441
  }
442

443
  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y) {
444
    return __x.__node_ == __y.__node_;
445
  }
446
  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y) {
447
    return !(__x == __y);
448
  }
449

450
private:
451
  _LIBCPP_HIDE_FROM_ABI explicit __hash_local_iterator(
452
      __next_pointer __node, size_t __bucket, size_t __bucket_count) _NOEXCEPT
453
      : __node_(__node),
454
        __bucket_(__bucket),
455
        __bucket_count_(__bucket_count) {
456
    if (__node_ != nullptr)
457
      __node_ = __node_->__next_;
458
  }
459

460
  template <class, class, class, class>
461
  friend class __hash_table;
462
  template <class>
463
  friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
464
  template <class>
465
  friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
466
};
467

468
template <class _ConstNodePtr>
469
class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator {
470
  typedef __hash_node_types<_ConstNodePtr> _NodeTypes;
471
  typedef _ConstNodePtr __node_pointer;
472
  typedef typename _NodeTypes::__next_pointer __next_pointer;
473

474
  __next_pointer __node_;
475
  size_t __bucket_;
476
  size_t __bucket_count_;
477

478
  typedef pointer_traits<__node_pointer> __pointer_traits;
479
  typedef typename __pointer_traits::element_type __node;
480
  typedef __remove_const_t<__node> __non_const_node;
481
  typedef __rebind_pointer_t<__node_pointer, __non_const_node> __non_const_node_pointer;
482

483
public:
484
  typedef __hash_local_iterator<__non_const_node_pointer> __non_const_iterator;
485

486
  typedef forward_iterator_tag iterator_category;
487
  typedef typename _NodeTypes::__node_value_type value_type;
488
  typedef typename _NodeTypes::difference_type difference_type;
489
  typedef const value_type& reference;
490
  typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
491

492
  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) {}
493

494
  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
495
      : __node_(__x.__node_),
496
        __bucket_(__x.__bucket_),
497
        __bucket_count_(__x.__bucket_count_) {}
498

499
  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
500
    _LIBCPP_ASSERT_NON_NULL(
501
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
502
    return __node_->__upcast()->__get_value();
503
  }
504

505
  _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
506
    _LIBCPP_ASSERT_NON_NULL(
507
        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
508
    return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
509
  }
510

511
  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator& operator++() {
512
    _LIBCPP_ASSERT_NON_NULL(
513
        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_local_iterator");
514
    __node_ = __node_->__next_;
515
    if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
516
      __node_ = nullptr;
517
    return *this;
518
  }
519

520
  _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator operator++(int) {
521
    __hash_const_local_iterator __t(*this);
522
    ++(*this);
523
    return __t;
524
  }
525

526
  friend _LIBCPP_HIDE_FROM_ABI bool
527
  operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) {
528
    return __x.__node_ == __y.__node_;
529
  }
530
  friend _LIBCPP_HIDE_FROM_ABI bool
531
  operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) {
532
    return !(__x == __y);
533
  }
534

535
private:
536
  _LIBCPP_HIDE_FROM_ABI explicit __hash_const_local_iterator(
537
      __next_pointer __node_ptr, size_t __bucket, size_t __bucket_count) _NOEXCEPT
538
      : __node_(__node_ptr),
539
        __bucket_(__bucket),
540
        __bucket_count_(__bucket_count) {
541
    if (__node_ != nullptr)
542
      __node_ = __node_->__next_;
543
  }
544

545
  template <class, class, class, class>
546
  friend class __hash_table;
547
  template <class>
548
  friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
549
};
550

551
template <class _Alloc>
552
class __bucket_list_deallocator {
553
  typedef _Alloc allocator_type;
554
  typedef allocator_traits<allocator_type> __alloc_traits;
555
  typedef typename __alloc_traits::size_type size_type;
556

557
  __compressed_pair<size_type, allocator_type> __data_;
558

559
public:
560
  typedef typename __alloc_traits::pointer pointer;
561

562
  _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
563
      : __data_(0, __default_init_tag()) {}
564

565
  _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(const allocator_type& __a, size_type __size)
566
      _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
567
      : __data_(__size, __a) {}
568

569
  _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(__bucket_list_deallocator&& __x)
570
      _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
571
      : __data_(std::move(__x.__data_)) {
572
    __x.size() = 0;
573
  }
574

575
  _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __data_.first(); }
576
  _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __data_.first(); }
577

578
  _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __data_.second(); }
579
  _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __data_.second(); }
580

581
  _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { __alloc_traits::deallocate(__alloc(), __p, size()); }
582
};
583

584
template <class _Alloc>
585
class __hash_map_node_destructor;
586

587
template <class _Alloc>
588
class __hash_node_destructor {
589
  typedef _Alloc allocator_type;
590
  typedef allocator_traits<allocator_type> __alloc_traits;
591

592
public:
593
  typedef typename __alloc_traits::pointer pointer;
594

595
private:
596
  typedef __hash_node_types<pointer> _NodeTypes;
597

598
  allocator_type& __na_;
599

600
public:
601
  bool __value_constructed;
602

603
  _LIBCPP_HIDE_FROM_ABI __hash_node_destructor(__hash_node_destructor const&)            = default;
604
  _LIBCPP_HIDE_FROM_ABI __hash_node_destructor& operator=(const __hash_node_destructor&) = delete;
605

606
  _LIBCPP_HIDE_FROM_ABI explicit __hash_node_destructor(allocator_type& __na, bool __constructed = false) _NOEXCEPT
607
      : __na_(__na),
608
        __value_constructed(__constructed) {}
609

610
  _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
611
    if (__value_constructed) {
612
      __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__get_value()));
613
      std::__destroy_at(std::addressof(*__p));
614
    }
615
    if (__p)
616
      __alloc_traits::deallocate(__na_, __p, 1);
617
  }
618

619
  template <class>
620
  friend class __hash_map_node_destructor;
621
};
622

623
#if _LIBCPP_STD_VER >= 17
624
template <class _NodeType, class _Alloc>
625
struct __generic_container_node_destructor;
626

627
template <class _Tp, class _VoidPtr, class _Alloc>
628
struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc> : __hash_node_destructor<_Alloc> {
629
  using __hash_node_destructor<_Alloc>::__hash_node_destructor;
630
};
631
#endif
632

633
template <class _Key, class _Hash, class _Equal>
634
struct __enforce_unordered_container_requirements {
635
#ifndef _LIBCPP_CXX03_LANG
636
  static_assert(__check_hash_requirements<_Key, _Hash>::value,
637
                "the specified hash does not meet the Hash requirements");
638
  static_assert(is_copy_constructible<_Equal>::value, "the specified comparator is required to be copy constructible");
639
#endif
640
  typedef int type;
641
};
642

643
template <class _Key, class _Hash, class _Equal>
644
#ifndef _LIBCPP_CXX03_LANG
645
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
646
                         "the specified comparator type does not provide a viable const call operator")
647
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
648
                         "the specified hash functor does not provide a viable const call operator")
649
#endif
650
    typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
651
    __diagnose_unordered_container_requirements(int);
652

653
// This dummy overload is used so that the compiler won't emit a spurious
654
// "no matching function for call to __diagnose_unordered_xxx" diagnostic
655
// when the overload above causes a hard error.
656
template <class _Key, class _Hash, class _Equal>
657
int __diagnose_unordered_container_requirements(void*);
658

659
template <class _Tp, class _Hash, class _Equal, class _Alloc>
660
class __hash_table {
661
public:
662
  typedef _Tp value_type;
663
  typedef _Hash hasher;
664
  typedef _Equal key_equal;
665
  typedef _Alloc allocator_type;
666

667
private:
668
  typedef allocator_traits<allocator_type> __alloc_traits;
669
  typedef typename __make_hash_node_types<value_type, typename __alloc_traits::void_pointer>::type _NodeTypes;
670

671
public:
672
  typedef typename _NodeTypes::__node_value_type __node_value_type;
673
  typedef typename _NodeTypes::__container_value_type __container_value_type;
674
  typedef typename _NodeTypes::key_type key_type;
675
  typedef value_type& reference;
676
  typedef const value_type& const_reference;
677
  typedef typename __alloc_traits::pointer pointer;
678
  typedef typename __alloc_traits::const_pointer const_pointer;
679
#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
680
  typedef typename __alloc_traits::size_type size_type;
681
#else
682
  typedef typename _NodeTypes::size_type size_type;
683
#endif
684
  typedef typename _NodeTypes::difference_type difference_type;
685

686
public:
687
  // Create __node
688

689
  typedef typename _NodeTypes::__node_type __node;
690
  typedef __rebind_alloc<__alloc_traits, __node> __node_allocator;
691
  typedef allocator_traits<__node_allocator> __node_traits;
692
  typedef typename _NodeTypes::__void_pointer __void_pointer;
693
  typedef typename _NodeTypes::__node_pointer __node_pointer;
694
  typedef typename _NodeTypes::__node_pointer __node_const_pointer;
695
  typedef typename _NodeTypes::__node_base_type __first_node;
696
  typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
697
  typedef typename _NodeTypes::__next_pointer __next_pointer;
698

699
private:
700
  // check for sane allocator pointer rebinding semantics. Rebinding the
701
  // allocator for a new pointer type should be exactly the same as rebinding
702
  // the pointer using 'pointer_traits'.
703
  static_assert(is_same<__node_pointer, typename __node_traits::pointer>::value,
704
                "Allocator does not rebind pointers in a sane manner.");
705
  typedef __rebind_alloc<__node_traits, __first_node> __node_base_allocator;
706
  typedef allocator_traits<__node_base_allocator> __node_base_traits;
707
  static_assert(is_same<__node_base_pointer, typename __node_base_traits::pointer>::value,
708
                "Allocator does not rebind pointers in a sane manner.");
709

710
private:
711
  typedef __rebind_alloc<__node_traits, __next_pointer> __pointer_allocator;
712
  typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
713
  typedef unique_ptr<__next_pointer[], __bucket_list_deleter> __bucket_list;
714
  typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
715
  typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
716

717
  // --- Member data begin ---
718
  __bucket_list __bucket_list_;
719
  __compressed_pair<__first_node, __node_allocator> __p1_;
720
  __compressed_pair<size_type, hasher> __p2_;
721
  __compressed_pair<float, key_equal> __p3_;
722
  // --- Member data end ---
723

724
  _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __p2_.first(); }
725

726
public:
727
  _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __p2_.first(); }
728

729
  _LIBCPP_HIDE_FROM_ABI hasher& hash_function() _NOEXCEPT { return __p2_.second(); }
730
  _LIBCPP_HIDE_FROM_ABI const hasher& hash_function() const _NOEXCEPT { return __p2_.second(); }
731

732
  _LIBCPP_HIDE_FROM_ABI float& max_load_factor() _NOEXCEPT { return __p3_.first(); }
733
  _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __p3_.first(); }
734

735
  _LIBCPP_HIDE_FROM_ABI key_equal& key_eq() _NOEXCEPT { return __p3_.second(); }
736
  _LIBCPP_HIDE_FROM_ABI const key_equal& key_eq() const _NOEXCEPT { return __p3_.second(); }
737

738
  _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __p1_.second(); }
739
  _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __p1_.second(); }
740

741
public:
742
  typedef __hash_iterator<__node_pointer> iterator;
743
  typedef __hash_const_iterator<__node_pointer> const_iterator;
744
  typedef __hash_local_iterator<__node_pointer> local_iterator;
745
  typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
746

747
  _LIBCPP_HIDE_FROM_ABI __hash_table() _NOEXCEPT_(
748
      is_nothrow_default_constructible<__bucket_list>::value&& is_nothrow_default_constructible<__first_node>::value&&
749
          is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_default_constructible<hasher>::value&&
750
              is_nothrow_default_constructible<key_equal>::value);
751
  _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql);
752
  _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
753
  _LIBCPP_HIDE_FROM_ABI explicit __hash_table(const allocator_type& __a);
754
  _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u);
755
  _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u, const allocator_type& __a);
756
  _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u) _NOEXCEPT_(
757
      is_nothrow_move_constructible<__bucket_list>::value&& is_nothrow_move_constructible<__first_node>::value&&
758
          is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<hasher>::value&&
759
              is_nothrow_move_constructible<key_equal>::value);
760
  _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u, const allocator_type& __a);
761
  _LIBCPP_HIDE_FROM_ABI ~__hash_table();
762

763
  _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(const __hash_table& __u);
764
  _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(__hash_table&& __u)
765
      _NOEXCEPT_(__node_traits::propagate_on_container_move_assignment::value&&
766
                     is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
767
                         is_nothrow_move_assignable<key_equal>::value);
768
  template <class _InputIterator>
769
  _LIBCPP_HIDE_FROM_ABI void __assign_unique(_InputIterator __first, _InputIterator __last);
770
  template <class _InputIterator>
771
  _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last);
772

773
  _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
774
    return std::min<size_type>(__node_traits::max_size(__node_alloc()), numeric_limits<difference_type >::max());
775
  }
776

777
private:
778
  _LIBCPP_HIDE_FROM_ABI __next_pointer __node_insert_multi_prepare(size_t __cp_hash, value_type& __cp_val);
779
  _LIBCPP_HIDE_FROM_ABI void __node_insert_multi_perform(__node_pointer __cp, __next_pointer __pn) _NOEXCEPT;
780

781
  _LIBCPP_HIDE_FROM_ABI __next_pointer __node_insert_unique_prepare(size_t __nd_hash, value_type& __nd_val);
782
  _LIBCPP_HIDE_FROM_ABI void __node_insert_unique_perform(__node_pointer __ptr) _NOEXCEPT;
783

784
public:
785
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
786
  _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);
787
  _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
788

789
  template <class _Key, class... _Args>
790
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
791

792
  template <class... _Args>
793
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
794

795
  template <class _Pp>
796
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Pp&& __x) {
797
    return __emplace_unique_extract_key(std::forward<_Pp>(__x), __can_extract_key<_Pp, key_type>());
798
  }
799

800
  template <class _First,
801
            class _Second,
802
            __enable_if_t<__can_extract_map_key<_First, key_type, __container_value_type>::value, int> = 0>
803
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_First&& __f, _Second&& __s) {
804
    return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s));
805
  }
806

807
  template <class... _Args>
808
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Args&&... __args) {
809
    return __emplace_unique_impl(std::forward<_Args>(__args)...);
810
  }
811

812
  template <class _Pp>
813
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) {
814
    return __emplace_unique_impl(std::forward<_Pp>(__x));
815
  }
816
  template <class _Pp>
817
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) {
818
    return __emplace_unique_key_args(__x, std::forward<_Pp>(__x));
819
  }
820
  template <class _Pp>
821
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) {
822
    return __emplace_unique_key_args(__x.first, std::forward<_Pp>(__x));
823
  }
824

825
  template <class... _Args>
826
  _LIBCPP_HIDE_FROM_ABI iterator __emplace_multi(_Args&&... __args);
827
  template <class... _Args>
828
  _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
829

830
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(__container_value_type&& __x) {
831
    return __emplace_unique_key_args(_NodeTypes::__get_key(__x), std::move(__x));
832
  }
833

834
  template <class _Pp, __enable_if_t<!__is_same_uncvref<_Pp, __container_value_type>::value, int> = 0>
835
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(_Pp&& __x) {
836
    return __emplace_unique(std::forward<_Pp>(__x));
837
  }
838

839
  template <class _Pp>
840
  _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(_Pp&& __x) {
841
    return __emplace_multi(std::forward<_Pp>(__x));
842
  }
843

844
  template <class _Pp>
845
  _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(const_iterator __p, _Pp&& __x) {
846
    return __emplace_hint_multi(__p, std::forward<_Pp>(__x));
847
  }
848

849
  _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(const __container_value_type& __x) {
850
    return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
851
  }
852

853
#if _LIBCPP_STD_VER >= 17
854
  template <class _NodeHandle, class _InsertReturnType>
855
  _LIBCPP_HIDE_FROM_ABI _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
856
  template <class _NodeHandle>
857
  _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_unique(const_iterator __hint, _NodeHandle&& __nh);
858
  template <class _Table>
859
  _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_unique(_Table& __source);
860

861
  template <class _NodeHandle>
862
  _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(_NodeHandle&& __nh);
863
  template <class _NodeHandle>
864
  _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
865
  template <class _Table>
866
  _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(_Table& __source);
867

868
  template <class _NodeHandle>
869
  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const& __key);
870
  template <class _NodeHandle>
871
  _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator __it);
872
#endif
873

874
  _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
875
  _LIBCPP_HIDE_FROM_ABI void __rehash_unique(size_type __n) { __rehash<true>(__n); }
876
  _LIBCPP_HIDE_FROM_ABI void __rehash_multi(size_type __n) { __rehash<false>(__n); }
877
  _LIBCPP_HIDE_FROM_ABI void __reserve_unique(size_type __n) {
878
    __rehash_unique(static_cast<size_type>(std::ceil(__n / max_load_factor())));
879
  }
880
  _LIBCPP_HIDE_FROM_ABI void __reserve_multi(size_type __n) {
881
    __rehash_multi(static_cast<size_type>(std::ceil(__n / max_load_factor())));
882
  }
883

884
  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __bucket_list_.get_deleter().size(); }
885

886
  _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT;
887
  _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT;
888
  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT;
889
  _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT;
890

891
  template <class _Key>
892
  _LIBCPP_HIDE_FROM_ABI size_type bucket(const _Key& __k) const {
893
    _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
894
        bucket_count() > 0, "unordered container::bucket(key) called when bucket_count() == 0");
895
    return std::__constrain_hash(hash_function()(__k), bucket_count());
896
  }
897

898
  template <class _Key>
899
  _LIBCPP_HIDE_FROM_ABI iterator find(const _Key& __x);
900
  template <class _Key>
901
  _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __x) const;
902

903
  typedef __hash_node_destructor<__node_allocator> _Dp;
904
  typedef unique_ptr<__node, _Dp> __node_holder;
905

906
  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p);
907
  _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last);
908
  template <class _Key>
909
  _LIBCPP_HIDE_FROM_ABI size_type __erase_unique(const _Key& __k);
910
  template <class _Key>
911
  _LIBCPP_HIDE_FROM_ABI size_type __erase_multi(const _Key& __k);
912
  _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT;
913

914
  template <class _Key>
915
  _LIBCPP_HIDE_FROM_ABI size_type __count_unique(const _Key& __k) const;
916
  template <class _Key>
917
  _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const;
918

919
  template <class _Key>
920
  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_unique(const _Key& __k);
921
  template <class _Key>
922
  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_unique(const _Key& __k) const;
923

924
  template <class _Key>
925
  _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_multi(const _Key& __k);
926
  template <class _Key>
927
  _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_multi(const _Key& __k) const;
928

929
  _LIBCPP_HIDE_FROM_ABI void swap(__hash_table& __u)
930
#if _LIBCPP_STD_VER <= 11
931
      _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
932
                 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
933
                  __is_nothrow_swappable_v<__pointer_allocator>) &&
934
                 (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>));
935
#else
936
      _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>);
937
#endif
938

939
  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return max_size(); }
940
  _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const;
941
  _LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT {
942
    size_type __bc = bucket_count();
943
    return __bc != 0 ? (float)size() / __bc : 0.f;
944
  }
945
  _LIBCPP_HIDE_FROM_ABI void max_load_factor(float __mlf) _NOEXCEPT {
946
    // While passing a non-positive load factor is undefined behavior, in practice the result will be benign (the
947
    // call will be equivalent to `max_load_factor(load_factor())`, which is also the case for passing a valid value
948
    // less than the current `load_factor`).
949
    _LIBCPP_ASSERT_PEDANTIC(__mlf > 0, "unordered container::max_load_factor(lf) called with lf <= 0");
950
    max_load_factor() = std::max(__mlf, load_factor());
951
  }
952

953
  _LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) {
954
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
955
        __n < bucket_count(), "unordered container::begin(n) called with n >= bucket_count()");
956
    return local_iterator(__bucket_list_[__n], __n, bucket_count());
957
  }
958

959
  _LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) {
960
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
961
        __n < bucket_count(), "unordered container::end(n) called with n >= bucket_count()");
962
    return local_iterator(nullptr, __n, bucket_count());
963
  }
964

965
  _LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const {
966
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
967
        __n < bucket_count(), "unordered container::cbegin(n) called with n >= bucket_count()");
968
    return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
969
  }
970

971
  _LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const {
972
    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
973
        __n < bucket_count(), "unordered container::cend(n) called with n >= bucket_count()");
974
    return const_local_iterator(nullptr, __n, bucket_count());
975
  }
976

977
private:
978
  template <bool _UniqueKeys>
979
  _LIBCPP_HIDE_FROM_ABI void __rehash(size_type __n);
980
  template <bool _UniqueKeys>
981
  _LIBCPP_HIDE_FROM_ABI void __do_rehash(size_type __n);
982

983
  template <class... _Args>
984
  _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args);
985

986
  template <class _First, class... _Rest>
987
  _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest);
988

989
  _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u) {
990
    __copy_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
991
  }
992
  _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u, true_type);
993
  _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table&, false_type) {}
994

995
  _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, false_type);
996
  _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, true_type)
997
      _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
998
                     is_nothrow_move_assignable<key_equal>::value);
999
  _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table& __u) _NOEXCEPT_(
1000
      !__node_traits::propagate_on_container_move_assignment::value ||
1001
      (is_nothrow_move_assignable<__pointer_allocator>::value && is_nothrow_move_assignable<__node_allocator>::value)) {
1002
    __move_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());
1003
  }
1004
  _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table& __u, true_type) _NOEXCEPT_(
1005
      is_nothrow_move_assignable<__pointer_allocator>::value&& is_nothrow_move_assignable<__node_allocator>::value) {
1006
    __bucket_list_.get_deleter().__alloc() = std::move(__u.__bucket_list_.get_deleter().__alloc());
1007
    __node_alloc()                         = std::move(__u.__node_alloc());
1008
  }
1009
  _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
1010

1011
  _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT;
1012
  _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT;
1013

1014
  template <class, class, class, class, class>
1015
  friend class _LIBCPP_TEMPLATE_VIS unordered_map;
1016
  template <class, class, class, class, class>
1017
  friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
1018
};
1019

1020
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1021
inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() _NOEXCEPT_(
1022
    is_nothrow_default_constructible<__bucket_list>::value&& is_nothrow_default_constructible<__first_node>::value&&
1023
        is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_default_constructible<hasher>::value&&
1024
            is_nothrow_default_constructible<key_equal>::value)
1025
    : __p2_(0, __default_init_tag()), __p3_(1.0f, __default_init_tag()) {}
1026

1027
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1028
inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, const key_equal& __eql)
1029
    : __bucket_list_(nullptr, __bucket_list_deleter()), __p1_(), __p2_(0, __hf), __p3_(1.0f, __eql) {}
1030

1031
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1032
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(
1033
    const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
1034
    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1035
      __p1_(__default_init_tag(), __node_allocator(__a)),
1036
      __p2_(0, __hf),
1037
      __p3_(1.0f, __eql) {}
1038

1039
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1040
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
1041
    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1042
      __p1_(__default_init_tag(), __node_allocator(__a)),
1043
      __p2_(0, __default_init_tag()),
1044
      __p3_(1.0f, __default_init_tag()) {}
1045

1046
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1047
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
1048
    : __bucket_list_(nullptr,
1049
                     __bucket_list_deleter(allocator_traits<__pointer_allocator>::select_on_container_copy_construction(
1050
                                               __u.__bucket_list_.get_deleter().__alloc()),
1051
                                           0)),
1052
      __p1_(__default_init_tag(),
1053
            allocator_traits<__node_allocator>::select_on_container_copy_construction(__u.__node_alloc())),
1054
      __p2_(0, __u.hash_function()),
1055
      __p3_(__u.__p3_) {}
1056

1057
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1058
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, const allocator_type& __a)
1059
    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1060
      __p1_(__default_init_tag(), __node_allocator(__a)),
1061
      __p2_(0, __u.hash_function()),
1062
      __p3_(__u.__p3_) {}
1063

1064
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1065
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) _NOEXCEPT_(
1066
    is_nothrow_move_constructible<__bucket_list>::value&& is_nothrow_move_constructible<__first_node>::value&&
1067
        is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<hasher>::value&&
1068
            is_nothrow_move_constructible<key_equal>::value)
1069
    : __bucket_list_(std::move(__u.__bucket_list_)),
1070
      __p1_(std::move(__u.__p1_)),
1071
      __p2_(std::move(__u.__p2_)),
1072
      __p3_(std::move(__u.__p3_)) {
1073
  if (size() > 0) {
1074
    __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
1075
    __u.__p1_.first().__next_                                                              = nullptr;
1076
    __u.size()                                                                             = 0;
1077
  }
1078
}
1079

1080
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1081
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, const allocator_type& __a)
1082
    : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1083
      __p1_(__default_init_tag(), __node_allocator(__a)),
1084
      __p2_(0, std::move(__u.hash_function())),
1085
      __p3_(std::move(__u.__p3_)) {
1086
  if (__a == allocator_type(__u.__node_alloc())) {
1087
    __bucket_list_.reset(__u.__bucket_list_.release());
1088
    __bucket_list_.get_deleter().size()     = __u.__bucket_list_.get_deleter().size();
1089
    __u.__bucket_list_.get_deleter().size() = 0;
1090
    if (__u.size() > 0) {
1091
      __p1_.first().__next_     = __u.__p1_.first().__next_;
1092
      __u.__p1_.first().__next_ = nullptr;
1093
      __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
1094
      size()                                                                                 = __u.size();
1095
      __u.size()                                                                             = 0;
1096
    }
1097
  }
1098
}
1099

1100
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1101
__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() {
1102
#if defined(_LIBCPP_CXX03_LANG)
1103
  static_assert(is_copy_constructible<key_equal>::value, "Predicate must be copy-constructible.");
1104
  static_assert(is_copy_constructible<hasher>::value, "Hasher must be copy-constructible.");
1105
#endif
1106

1107
  __deallocate_node(__p1_.first().__next_);
1108
}
1109

1110
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1111
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(const __hash_table& __u, true_type) {
1112
  if (__node_alloc() != __u.__node_alloc()) {
1113
    clear();
1114
    __bucket_list_.reset();
1115
    __bucket_list_.get_deleter().size() = 0;
1116
  }
1117
  __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
1118
  __node_alloc()                         = __u.__node_alloc();
1119
}
1120

1121
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1122
__hash_table<_Tp, _Hash, _Equal, _Alloc>& __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) {
1123
  if (this != std::addressof(__u)) {
1124
    __copy_assign_alloc(__u);
1125
    hash_function()   = __u.hash_function();
1126
    key_eq()          = __u.key_eq();
1127
    max_load_factor() = __u.max_load_factor();
1128
    __assign_multi(__u.begin(), __u.end());
1129
  }
1130
  return *this;
1131
}
1132

1133
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1134
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) _NOEXCEPT {
1135
  __node_allocator& __na = __node_alloc();
1136
  while (__np != nullptr) {
1137
    __next_pointer __next    = __np->__next_;
1138
    __node_pointer __real_np = __np->__upcast();
1139
    __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__get_value()));
1140
    std::__destroy_at(std::addressof(*__real_np));
1141
    __node_traits::deallocate(__na, __real_np, 1);
1142
    __np = __next;
1143
  }
1144
}
1145

1146
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1147
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1148
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT {
1149
  size_type __bc = bucket_count();
1150
  for (size_type __i = 0; __i < __bc; ++__i)
1151
    __bucket_list_[__i] = nullptr;
1152
  size()                 = 0;
1153
  __next_pointer __cache = __p1_.first().__next_;
1154
  __p1_.first().__next_  = nullptr;
1155
  return __cache;
1156
}
1157

1158
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1159
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, true_type)
1160
    _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
1161
                   is_nothrow_move_assignable<key_equal>::value) {
1162
  clear();
1163
  __bucket_list_.reset(__u.__bucket_list_.release());
1164
  __bucket_list_.get_deleter().size()     = __u.__bucket_list_.get_deleter().size();
1165
  __u.__bucket_list_.get_deleter().size() = 0;
1166
  __move_assign_alloc(__u);
1167
  size()                = __u.size();
1168
  hash_function()       = std::move(__u.hash_function());
1169
  max_load_factor()     = __u.max_load_factor();
1170
  key_eq()              = std::move(__u.key_eq());
1171
  __p1_.first().__next_ = __u.__p1_.first().__next_;
1172
  if (size() > 0) {
1173
    __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
1174
    __u.__p1_.first().__next_                                                              = nullptr;
1175
    __u.size()                                                                             = 0;
1176
  }
1177
}
1178

1179
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1180
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, false_type) {
1181
  if (__node_alloc() == __u.__node_alloc())
1182
    __move_assign(__u, true_type());
1183
  else {
1184
    hash_function()   = std::move(__u.hash_function());
1185
    key_eq()          = std::move(__u.key_eq());
1186
    max_load_factor() = __u.max_load_factor();
1187
    if (bucket_count() != 0) {
1188
      __next_pointer __cache = __detach();
1189
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1190
      try {
1191
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1192
        const_iterator __i = __u.begin();
1193
        while (__cache != nullptr && __u.size() != 0) {
1194
          __cache->__upcast()->__get_value() = std::move(__u.remove(__i++)->__get_value());
1195
          __next_pointer __next              = __cache->__next_;
1196
          __node_insert_multi(__cache->__upcast());
1197
          __cache = __next;
1198
        }
1199
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1200
      } catch (...) {
1201
        __deallocate_node(__cache);
1202
        throw;
1203
      }
1204
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1205
      __deallocate_node(__cache);
1206
    }
1207
    const_iterator __i = __u.begin();
1208
    while (__u.size() != 0) {
1209
      __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__get_value()));
1210
      __node_insert_multi(__h.get());
1211
      __h.release();
1212
    }
1213
  }
1214
}
1215

1216
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1217
inline __hash_table<_Tp, _Hash, _Equal, _Alloc>&
1218
__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) _NOEXCEPT_(
1219
    __node_traits::propagate_on_container_move_assignment::value&& is_nothrow_move_assignable<__node_allocator>::value&&
1220
        is_nothrow_move_assignable<hasher>::value&& is_nothrow_move_assignable<key_equal>::value) {
1221
  __move_assign(__u, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());
1222
  return *this;
1223
}
1224

1225
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1226
template <class _InputIterator>
1227
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) {
1228
  typedef iterator_traits<_InputIterator> _ITraits;
1229
  typedef typename _ITraits::value_type _ItValueType;
1230
  static_assert(is_same<_ItValueType, __container_value_type>::value,
1231
                "__assign_unique may only be called with the containers value type");
1232

1233
  if (bucket_count() != 0) {
1234
    __next_pointer __cache = __detach();
1235
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1236
    try {
1237
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1238
      for (; __cache != nullptr && __first != __last; ++__first) {
1239
        __cache->__upcast()->__get_value() = *__first;
1240
        __next_pointer __next              = __cache->__next_;
1241
        __node_insert_unique(__cache->__upcast());
1242
        __cache = __next;
1243
      }
1244
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1245
    } catch (...) {
1246
      __deallocate_node(__cache);
1247
      throw;
1248
    }
1249
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1250
    __deallocate_node(__cache);
1251
  }
1252
  for (; __first != __last; ++__first)
1253
    __insert_unique(*__first);
1254
}
1255

1256
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1257
template <class _InputIterator>
1258
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, _InputIterator __last) {
1259
  typedef iterator_traits<_InputIterator> _ITraits;
1260
  typedef typename _ITraits::value_type _ItValueType;
1261
  static_assert(
1262
      (is_same<_ItValueType, __container_value_type>::value || is_same<_ItValueType, __node_value_type>::value),
1263
      "__assign_multi may only be called with the containers value type"
1264
      " or the nodes value type");
1265
  if (bucket_count() != 0) {
1266
    __next_pointer __cache = __detach();
1267
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1268
    try {
1269
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1270
      for (; __cache != nullptr && __first != __last; ++__first) {
1271
        __cache->__upcast()->__get_value() = *__first;
1272
        __next_pointer __next              = __cache->__next_;
1273
        __node_insert_multi(__cache->__upcast());
1274
        __cache = __next;
1275
      }
1276
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1277
    } catch (...) {
1278
      __deallocate_node(__cache);
1279
      throw;
1280
    }
1281
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
1282
    __deallocate_node(__cache);
1283
  }
1284
  for (; __first != __last; ++__first)
1285
    __insert_multi(_NodeTypes::__get_value(*__first));
1286
}
1287

1288
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1289
inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1290
__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT {
1291
  return iterator(__p1_.first().__next_);
1292
}
1293

1294
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1295
inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1296
__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT {
1297
  return iterator(nullptr);
1298
}
1299

1300
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1301
inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1302
__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT {
1303
  return const_iterator(__p1_.first().__next_);
1304
}
1305

1306
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1307
inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1308
__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT {
1309
  return const_iterator(nullptr);
1310
}
1311

1312
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1313
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT {
1314
  if (size() > 0) {
1315
    __deallocate_node(__p1_.first().__next_);
1316
    __p1_.first().__next_ = nullptr;
1317
    size_type __bc        = bucket_count();
1318
    for (size_type __i = 0; __i < __bc; ++__i)
1319
      __bucket_list_[__i] = nullptr;
1320
    size() = 0;
1321
  }
1322
}
1323

1324
// Prepare the container for an insertion of the value __value with the hash
1325
// __hash. This does a lookup into the container to see if __value is already
1326
// present, and performs a rehash if necessary. Returns a pointer to the
1327
// existing element if it exists, otherwise nullptr.
1328
//
1329
// Note that this function does forward exceptions if key_eq() throws, and never
1330
// mutates __value or actually inserts into the map.
1331
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1332
_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1333
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare(size_t __hash, value_type& __value) {
1334
  size_type __bc = bucket_count();
1335

1336
  if (__bc != 0) {
1337
    size_t __chash         = std::__constrain_hash(__hash, __bc);
1338
    __next_pointer __ndptr = __bucket_list_[__chash];
1339
    if (__ndptr != nullptr) {
1340
      for (__ndptr = __ndptr->__next_;
1341
           __ndptr != nullptr &&
1342
           (__ndptr->__hash() == __hash || std::__constrain_hash(__ndptr->__hash(), __bc) == __chash);
1343
           __ndptr = __ndptr->__next_) {
1344
        if ((__ndptr->__hash() == __hash) && key_eq()(__ndptr->__upcast()->__get_value(), __value))
1345
          return __ndptr;
1346
      }
1347
    }
1348
  }
1349
  if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1350
    __rehash_unique(std::max<size_type>(
1351
        2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1352
  }
1353
  return nullptr;
1354
}
1355

1356
// Insert the node __nd into the container by pushing it into the right bucket,
1357
// and updating size(). Assumes that __nd->__hash is up-to-date, and that
1358
// rehashing has already occurred and that no element with the same key exists
1359
// in the map.
1360
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1361
_LIBCPP_HIDE_FROM_ABI void
1362
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform(__node_pointer __nd) _NOEXCEPT {
1363
  size_type __bc = bucket_count();
1364
  size_t __chash = std::__constrain_hash(__nd->__hash(), __bc);
1365
  // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1366
  __next_pointer __pn = __bucket_list_[__chash];
1367
  if (__pn == nullptr) {
1368
    __pn          = __p1_.first().__ptr();
1369
    __nd->__next_ = __pn->__next_;
1370
    __pn->__next_ = __nd->__ptr();
1371
    // fix up __bucket_list_
1372
    __bucket_list_[__chash] = __pn;
1373
    if (__nd->__next_ != nullptr)
1374
      __bucket_list_[std::__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr();
1375
  } else {
1376
    __nd->__next_ = __pn->__next_;
1377
    __pn->__next_ = __nd->__ptr();
1378
  }
1379
  ++size();
1380
}
1381

1382
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1383
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1384
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd) {
1385
  __nd->__hash_                  = hash_function()(__nd->__get_value());
1386
  __next_pointer __existing_node = __node_insert_unique_prepare(__nd->__hash(), __nd->__get_value());
1387

1388
  // Insert the node, unless it already exists in the container.
1389
  bool __inserted = false;
1390
  if (__existing_node == nullptr) {
1391
    __node_insert_unique_perform(__nd);
1392
    __existing_node = __nd->__ptr();
1393
    __inserted      = true;
1394
  }
1395
  return pair<iterator, bool>(iterator(__existing_node), __inserted);
1396
}
1397

1398
// Prepare the container for an insertion of the value __cp_val with the hash
1399
// __cp_hash. This does a lookup into the container to see if __cp_value is
1400
// already present, and performs a rehash if necessary. Returns a pointer to the
1401
// last occurrence of __cp_val in the map.
1402
//
1403
// Note that this function does forward exceptions if key_eq() throws, and never
1404
// mutates __value or actually inserts into the map.
1405
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1406
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1407
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare(size_t __cp_hash, value_type& __cp_val) {
1408
  size_type __bc = bucket_count();
1409
  if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1410
    __rehash_multi(std::max<size_type>(
1411
        2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1412
    __bc = bucket_count();
1413
  }
1414
  size_t __chash      = std::__constrain_hash(__cp_hash, __bc);
1415
  __next_pointer __pn = __bucket_list_[__chash];
1416
  if (__pn != nullptr) {
1417
    for (bool __found = false;
1418
         __pn->__next_ != nullptr && std::__constrain_hash(__pn->__next_->__hash(), __bc) == __chash;
1419
         __pn = __pn->__next_) {
1420
      //      __found    key_eq()     action
1421
      //      false       false       loop
1422
      //      true        true        loop
1423
      //      false       true        set __found to true
1424
      //      true        false       break
1425
      if (__found !=
1426
          (__pn->__next_->__hash() == __cp_hash && key_eq()(__pn->__next_->__upcast()->__get_value(), __cp_val))) {
1427
        if (!__found)
1428
          __found = true;
1429
        else
1430
          break;
1431
      }
1432
    }
1433
  }
1434
  return __pn;
1435
}
1436

1437
// Insert the node __cp into the container after __pn (which is the last node in
1438
// the bucket that compares equal to __cp). Rehashing, and checking for
1439
// uniqueness has already been performed (in __node_insert_multi_prepare), so
1440
// all we need to do is update the bucket and size(). Assumes that __cp->__hash
1441
// is up-to-date.
1442
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1443
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform(
1444
    __node_pointer __cp, __next_pointer __pn) _NOEXCEPT {
1445
  size_type __bc = bucket_count();
1446
  size_t __chash = std::__constrain_hash(__cp->__hash_, __bc);
1447
  if (__pn == nullptr) {
1448
    __pn          = __p1_.first().__ptr();
1449
    __cp->__next_ = __pn->__next_;
1450
    __pn->__next_ = __cp->__ptr();
1451
    // fix up __bucket_list_
1452
    __bucket_list_[__chash] = __pn;
1453
    if (__cp->__next_ != nullptr)
1454
      __bucket_list_[std::__constrain_hash(__cp->__next_->__hash(), __bc)] = __cp->__ptr();
1455
  } else {
1456
    __cp->__next_ = __pn->__next_;
1457
    __pn->__next_ = __cp->__ptr();
1458
    if (__cp->__next_ != nullptr) {
1459
      size_t __nhash = std::__constrain_hash(__cp->__next_->__hash(), __bc);
1460
      if (__nhash != __chash)
1461
        __bucket_list_[__nhash] = __cp->__ptr();
1462
    }
1463
  }
1464
  ++size();
1465
}
1466

1467
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1468
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1469
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) {
1470
  __cp->__hash_       = hash_function()(__cp->__get_value());
1471
  __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__get_value());
1472
  __node_insert_multi_perform(__cp, __pn);
1473

1474
  return iterator(__cp->__ptr());
1475
}
1476

1477
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1478
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1479
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(const_iterator __p, __node_pointer __cp) {
1480
  if (__p != end() && key_eq()(*__p, __cp->__get_value())) {
1481
    __next_pointer __np = __p.__node_;
1482
    __cp->__hash_       = __np->__hash();
1483
    size_type __bc      = bucket_count();
1484
    if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1485
      __rehash_multi(std::max<size_type>(
1486
          2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1487
      __bc = bucket_count();
1488
    }
1489
    size_t __chash      = std::__constrain_hash(__cp->__hash_, __bc);
1490
    __next_pointer __pp = __bucket_list_[__chash];
1491
    while (__pp->__next_ != __np)
1492
      __pp = __pp->__next_;
1493
    __cp->__next_ = __np;
1494
    __pp->__next_ = static_cast<__next_pointer>(__cp);
1495
    ++size();
1496
    return iterator(static_cast<__next_pointer>(__cp));
1497
  }
1498
  return __node_insert_multi(__cp);
1499
}
1500

1501
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1502
template <class _Key, class... _Args>
1503
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1504
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) {
1505
  size_t __hash   = hash_function()(__k);
1506
  size_type __bc  = bucket_count();
1507
  bool __inserted = false;
1508
  __next_pointer __nd;
1509
  size_t __chash;
1510
  if (__bc != 0) {
1511
    __chash = std::__constrain_hash(__hash, __bc);
1512
    __nd    = __bucket_list_[__chash];
1513
    if (__nd != nullptr) {
1514
      for (__nd = __nd->__next_;
1515
           __nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1516
           __nd = __nd->__next_) {
1517
        if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
1518
          goto __done;
1519
      }
1520
    }
1521
  }
1522
  {
1523
    __node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args)...);
1524
    if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1525
      __rehash_unique(std::max<size_type>(
1526
          2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1527
      __bc    = bucket_count();
1528
      __chash = std::__constrain_hash(__hash, __bc);
1529
    }
1530
    // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1531
    __next_pointer __pn = __bucket_list_[__chash];
1532
    if (__pn == nullptr) {
1533
      __pn          = __p1_.first().__ptr();
1534
      __h->__next_  = __pn->__next_;
1535
      __pn->__next_ = __h.get()->__ptr();
1536
      // fix up __bucket_list_
1537
      __bucket_list_[__chash] = __pn;
1538
      if (__h->__next_ != nullptr)
1539
        __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr();
1540
    } else {
1541
      __h->__next_  = __pn->__next_;
1542
      __pn->__next_ = static_cast<__next_pointer>(__h.get());
1543
    }
1544
    __nd = static_cast<__next_pointer>(__h.release());
1545
    // increment size
1546
    ++size();
1547
    __inserted = true;
1548
  }
1549
__done:
1550
  return pair<iterator, bool>(iterator(__nd), __inserted);
1551
}
1552

1553
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1554
template <class... _Args>
1555
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1556
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) {
1557
  __node_holder __h        = __construct_node(std::forward<_Args>(__args)...);
1558
  pair<iterator, bool> __r = __node_insert_unique(__h.get());
1559
  if (__r.second)
1560
    __h.release();
1561
  return __r;
1562
}
1563

1564
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1565
template <class... _Args>
1566
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1567
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args) {
1568
  __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1569
  iterator __r      = __node_insert_multi(__h.get());
1570
  __h.release();
1571
  return __r;
1572
}
1573

1574
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1575
template <class... _Args>
1576
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1577
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) {
1578
  __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1579
  iterator __r      = __node_insert_multi(__p, __h.get());
1580
  __h.release();
1581
  return __r;
1582
}
1583

1584
#if _LIBCPP_STD_VER >= 17
1585
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1586
template <class _NodeHandle, class _InsertReturnType>
1587
_LIBCPP_HIDE_FROM_ABI _InsertReturnType
1588
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(_NodeHandle&& __nh) {
1589
  if (__nh.empty())
1590
    return _InsertReturnType{end(), false, _NodeHandle()};
1591
  pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
1592
  if (__result.second)
1593
    __nh.__release_ptr();
1594
  return _InsertReturnType{__result.first, __result.second, std::move(__nh)};
1595
}
1596

1597
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1598
template <class _NodeHandle>
1599
_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1600
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(const_iterator, _NodeHandle&& __nh) {
1601
  if (__nh.empty())
1602
    return end();
1603
  pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
1604
  if (__result.second)
1605
    __nh.__release_ptr();
1606
  return __result.first;
1607
}
1608

1609
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1610
template <class _NodeHandle>
1611
_LIBCPP_HIDE_FROM_ABI _NodeHandle
1612
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(key_type const& __key) {
1613
  iterator __i = find(__key);
1614
  if (__i == end())
1615
    return _NodeHandle();
1616
  return __node_handle_extract<_NodeHandle>(__i);
1617
}
1618

1619
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1620
template <class _NodeHandle>
1621
_LIBCPP_HIDE_FROM_ABI _NodeHandle __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(const_iterator __p) {
1622
  allocator_type __alloc(__node_alloc());
1623
  return _NodeHandle(remove(__p).release(), __alloc);
1624
}
1625

1626
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1627
template <class _Table>
1628
_LIBCPP_HIDE_FROM_ABI void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique(_Table& __source) {
1629
  static_assert(is_same<__node, typename _Table::__node>::value, "");
1630

1631
  for (typename _Table::iterator __it = __source.begin(); __it != __source.end();) {
1632
    __node_pointer __src_ptr       = __it.__node_->__upcast();
1633
    size_t __hash                  = hash_function()(__src_ptr->__get_value());
1634
    __next_pointer __existing_node = __node_insert_unique_prepare(__hash, __src_ptr->__get_value());
1635
    auto __prev_iter               = __it++;
1636
    if (__existing_node == nullptr) {
1637
      (void)__source.remove(__prev_iter).release();
1638
      __src_ptr->__hash_ = __hash;
1639
      __node_insert_unique_perform(__src_ptr);
1640
    }
1641
  }
1642
}
1643

1644
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1645
template <class _NodeHandle>
1646
_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1647
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(_NodeHandle&& __nh) {
1648
  if (__nh.empty())
1649
    return end();
1650
  iterator __result = __node_insert_multi(__nh.__ptr_);
1651
  __nh.__release_ptr();
1652
  return __result;
1653
}
1654

1655
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1656
template <class _NodeHandle>
1657
_LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1658
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh) {
1659
  if (__nh.empty())
1660
    return end();
1661
  iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
1662
  __nh.__release_ptr();
1663
  return __result;
1664
}
1665

1666
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1667
template <class _Table>
1668
_LIBCPP_HIDE_FROM_ABI void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi(_Table& __source) {
1669
  static_assert(is_same<typename _Table::__node, __node>::value, "");
1670

1671
  for (typename _Table::iterator __it = __source.begin(); __it != __source.end();) {
1672
    __node_pointer __src_ptr = __it.__node_->__upcast();
1673
    size_t __src_hash        = hash_function()(__src_ptr->__get_value());
1674
    __next_pointer __pn      = __node_insert_multi_prepare(__src_hash, __src_ptr->__get_value());
1675
    (void)__source.remove(__it++).release();
1676
    __src_ptr->__hash_ = __src_hash;
1677
    __node_insert_multi_perform(__src_ptr, __pn);
1678
  }
1679
}
1680
#endif // _LIBCPP_STD_VER >= 17
1681

1682
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1683
template <bool _UniqueKeys>
1684
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK {
1685
  if (__n == 1)
1686
    __n = 2;
1687
  else if (__n & (__n - 1))
1688
    __n = std::__next_prime(__n);
1689
  size_type __bc = bucket_count();
1690
  if (__n > __bc)
1691
    __do_rehash<_UniqueKeys>(__n);
1692
  else if (__n < __bc) {
1693
    __n = std::max<size_type>(
1694
        __n,
1695
        std::__is_hash_power2(__bc) ? std::__next_hash_pow2(size_t(std::ceil(float(size()) / max_load_factor())))
1696
                                    : std::__next_prime(size_t(std::ceil(float(size()) / max_load_factor()))));
1697
    if (__n < __bc)
1698
      __do_rehash<_UniqueKeys>(__n);
1699
  }
1700
}
1701

1702
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1703
template <bool _UniqueKeys>
1704
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) {
1705
  __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1706
  __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1707
  __bucket_list_.get_deleter().size() = __nbc;
1708
  if (__nbc > 0) {
1709
    for (size_type __i = 0; __i < __nbc; ++__i)
1710
      __bucket_list_[__i] = nullptr;
1711
    __next_pointer __pp = __p1_.first().__ptr();
1712
    __next_pointer __cp = __pp->__next_;
1713
    if (__cp != nullptr) {
1714
      size_type __chash       = std::__constrain_hash(__cp->__hash(), __nbc);
1715
      __bucket_list_[__chash] = __pp;
1716
      size_type __phash       = __chash;
1717
      for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) {
1718
        __chash = std::__constrain_hash(__cp->__hash(), __nbc);
1719
        if (__chash == __phash)
1720
          __pp = __cp;
1721
        else {
1722
          if (__bucket_list_[__chash] == nullptr) {
1723
            __bucket_list_[__chash] = __pp;
1724
            __pp                    = __cp;
1725
            __phash                 = __chash;
1726
          } else {
1727
            __next_pointer __np = __cp;
1728
            if _LIBCPP_CONSTEXPR_SINCE_CXX17 (!_UniqueKeys) {
1729
              for (; __np->__next_ != nullptr &&
1730
                     key_eq()(__cp->__upcast()->__get_value(), __np->__next_->__upcast()->__get_value());
1731
                   __np = __np->__next_)
1732
                ;
1733
            }
1734
            __pp->__next_                    = __np->__next_;
1735
            __np->__next_                    = __bucket_list_[__chash]->__next_;
1736
            __bucket_list_[__chash]->__next_ = __cp;
1737
          }
1738
        }
1739
      }
1740
    }
1741
  }
1742
}
1743

1744
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1745
template <class _Key>
1746
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1747
__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) {
1748
  size_t __hash  = hash_function()(__k);
1749
  size_type __bc = bucket_count();
1750
  if (__bc != 0) {
1751
    size_t __chash      = std::__constrain_hash(__hash, __bc);
1752
    __next_pointer __nd = __bucket_list_[__chash];
1753
    if (__nd != nullptr) {
1754
      for (__nd = __nd->__next_;
1755
           __nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1756
           __nd = __nd->__next_) {
1757
        if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
1758
          return iterator(__nd);
1759
      }
1760
    }
1761
  }
1762
  return end();
1763
}
1764

1765
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1766
template <class _Key>
1767
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1768
__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const {
1769
  size_t __hash  = hash_function()(__k);
1770
  size_type __bc = bucket_count();
1771
  if (__bc != 0) {
1772
    size_t __chash      = std::__constrain_hash(__hash, __bc);
1773
    __next_pointer __nd = __bucket_list_[__chash];
1774
    if (__nd != nullptr) {
1775
      for (__nd = __nd->__next_;
1776
           __nd != nullptr && (__hash == __nd->__hash() || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1777
           __nd = __nd->__next_) {
1778
        if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
1779
          return const_iterator(__nd);
1780
      }
1781
    }
1782
  }
1783
  return end();
1784
}
1785

1786
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1787
template <class... _Args>
1788
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1789
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) {
1790
  static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type");
1791
  __node_allocator& __na = __node_alloc();
1792
  __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
1793

1794
  // Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value
1795
  // held inside the node, since we need to use the allocator's construct() method for that.
1796
  //
1797
  // We don't use the allocator's construct() method to construct the node itself since the
1798
  // Cpp17FooInsertable named requirements don't require the allocator's construct() method
1799
  // to work on anything other than the value_type.
1800
  std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0);
1801

1802
  // Now construct the value_type using the allocator's construct() method.
1803
  __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_Args>(__args)...);
1804
  __h.get_deleter().__value_constructed = true;
1805

1806
  __h->__hash_ = hash_function()(__h->__get_value());
1807
  return __h;
1808
}
1809

1810
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1811
template <class _First, class... _Rest>
1812
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1813
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest) {
1814
  static_assert(!__is_hash_value_type<_First, _Rest...>::value, "Construct cannot be called with a hash value type");
1815
  __node_allocator& __na = __node_alloc();
1816
  __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
1817
  std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash);
1818
  __node_traits::construct(
1819
      __na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...);
1820
  __h.get_deleter().__value_constructed = true;
1821
  return __h;
1822
}
1823

1824
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1825
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1826
__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) {
1827
  __next_pointer __np = __p.__node_;
1828
  _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
1829
      __p != end(), "unordered container::erase(iterator) called with a non-dereferenceable iterator");
1830
  iterator __r(__np);
1831
  ++__r;
1832
  remove(__p);
1833
  return __r;
1834
}
1835

1836
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1837
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1838
__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) {
1839
  for (const_iterator __p = __first; __first != __last; __p = __first) {
1840
    ++__first;
1841
    erase(__p);
1842
  }
1843
  __next_pointer __np = __last.__node_;
1844
  return iterator(__np);
1845
}
1846

1847
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1848
template <class _Key>
1849
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1850
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k) {
1851
  iterator __i = find(__k);
1852
  if (__i == end())
1853
    return 0;
1854
  erase(__i);
1855
  return 1;
1856
}
1857

1858
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1859
template <class _Key>
1860
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1861
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k) {
1862
  size_type __r = 0;
1863
  iterator __i  = find(__k);
1864
  if (__i != end()) {
1865
    iterator __e = end();
1866
    do {
1867
      erase(__i++);
1868
      ++__r;
1869
    } while (__i != __e && key_eq()(*__i, __k));
1870
  }
1871
  return __r;
1872
}
1873

1874
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1875
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1876
__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT {
1877
  // current node
1878
  __next_pointer __cn = __p.__node_;
1879
  size_type __bc      = bucket_count();
1880
  size_t __chash      = std::__constrain_hash(__cn->__hash(), __bc);
1881
  // find previous node
1882
  __next_pointer __pn = __bucket_list_[__chash];
1883
  for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1884
    ;
1885
  // Fix up __bucket_list_
1886
  // if __pn is not in same bucket (before begin is not in same bucket) &&
1887
  //    if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
1888
  if (__pn == __p1_.first().__ptr() || std::__constrain_hash(__pn->__hash(), __bc) != __chash) {
1889
    if (__cn->__next_ == nullptr || std::__constrain_hash(__cn->__next_->__hash(), __bc) != __chash)
1890
      __bucket_list_[__chash] = nullptr;
1891
  }
1892
  // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1893
  if (__cn->__next_ != nullptr) {
1894
    size_t __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc);
1895
    if (__nhash != __chash)
1896
      __bucket_list_[__nhash] = __pn;
1897
  }
1898
  // remove __cn
1899
  __pn->__next_ = __cn->__next_;
1900
  __cn->__next_ = nullptr;
1901
  --size();
1902
  return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true));
1903
}
1904

1905
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1906
template <class _Key>
1907
inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1908
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const {
1909
  return static_cast<size_type>(find(__k) != end());
1910
}
1911

1912
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1913
template <class _Key>
1914
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1915
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const {
1916
  size_type __r      = 0;
1917
  const_iterator __i = find(__k);
1918
  if (__i != end()) {
1919
    const_iterator __e = end();
1920
    do {
1921
      ++__i;
1922
      ++__r;
1923
    } while (__i != __e && key_eq()(*__i, __k));
1924
  }
1925
  return __r;
1926
}
1927

1928
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1929
template <class _Key>
1930
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1931
     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1932
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(const _Key& __k) {
1933
  iterator __i = find(__k);
1934
  iterator __j = __i;
1935
  if (__i != end())
1936
    ++__j;
1937
  return pair<iterator, iterator>(__i, __j);
1938
}
1939

1940
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1941
template <class _Key>
1942
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1943
     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1944
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(const _Key& __k) const {
1945
  const_iterator __i = find(__k);
1946
  const_iterator __j = __i;
1947
  if (__i != end())
1948
    ++__j;
1949
  return pair<const_iterator, const_iterator>(__i, __j);
1950
}
1951

1952
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1953
template <class _Key>
1954
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1955
     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1956
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) {
1957
  iterator __i = find(__k);
1958
  iterator __j = __i;
1959
  if (__i != end()) {
1960
    iterator __e = end();
1961
    do {
1962
      ++__j;
1963
    } while (__j != __e && key_eq()(*__j, __k));
1964
  }
1965
  return pair<iterator, iterator>(__i, __j);
1966
}
1967

1968
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1969
template <class _Key>
1970
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1971
     typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1972
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) const {
1973
  const_iterator __i = find(__k);
1974
  const_iterator __j = __i;
1975
  if (__i != end()) {
1976
    const_iterator __e = end();
1977
    do {
1978
      ++__j;
1979
    } while (__j != __e && key_eq()(*__j, __k));
1980
  }
1981
  return pair<const_iterator, const_iterator>(__i, __j);
1982
}
1983

1984
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1985
void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
1986
#if _LIBCPP_STD_VER <= 11
1987
    _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
1988
               (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1989
                __is_nothrow_swappable_v<__pointer_allocator>) &&
1990
               (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>))
1991
#else
1992
    _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>)
1993
#endif
1994
{
1995
  _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
1996
      __node_traits::propagate_on_container_swap::value || this->__node_alloc() == __u.__node_alloc(),
1997
      "unordered container::swap: Either propagate_on_container_swap "
1998
      "must be true or the allocators must compare equal");
1999
  {
2000
    __node_pointer_pointer __npp = __bucket_list_.release();
2001
    __bucket_list_.reset(__u.__bucket_list_.release());
2002
    __u.__bucket_list_.reset(__npp);
2003
  }
2004
  std::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
2005
  std::__swap_allocator(__bucket_list_.get_deleter().__alloc(), __u.__bucket_list_.get_deleter().__alloc());
2006
  std::__swap_allocator(__node_alloc(), __u.__node_alloc());
2007
  std::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
2008
  __p2_.swap(__u.__p2_);
2009
  __p3_.swap(__u.__p3_);
2010
  if (size() > 0)
2011
    __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
2012
  if (__u.size() > 0)
2013
    __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] =
2014
        __u.__p1_.first().__ptr();
2015
}
2016

2017
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2018
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2019
__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const {
2020
  _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
2021
      __n < bucket_count(), "unordered container::bucket_size(n) called with n >= bucket_count()");
2022
  __next_pointer __np = __bucket_list_[__n];
2023
  size_type __bc      = bucket_count();
2024
  size_type __r       = 0;
2025
  if (__np != nullptr) {
2026
    for (__np = __np->__next_; __np != nullptr && std::__constrain_hash(__np->__hash(), __bc) == __n;
2027
         __np = __np->__next_, (void)++__r)
2028
      ;
2029
  }
2030
  return __r;
2031
}
2032

2033
template <class _Tp, class _Hash, class _Equal, class _Alloc>
2034
inline _LIBCPP_HIDE_FROM_ABI void
2035
swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2036
    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
2037
  __x.swap(__y);
2038
}
2039

2040
_LIBCPP_END_NAMESPACE_STD
2041

2042
_LIBCPP_POP_MACROS
2043

2044
#endif // _LIBCPP___HASH_TABLE
2045

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

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

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

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