xref: /freebsd/contrib/llvm-project/libcxx/include/ext/hash_map (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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_MAP
11#define _LIBCPP_HASH_MAP
12
13/*
14
15    hash_map synopsis
16
17namespace __gnu_cxx
18{
19
20template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
21          class Alloc = allocator<pair<const Key, T>>>
22class hash_map
23{
24public:
25    // types
26    typedef Key                                                        key_type;
27    typedef T                                                          mapped_type;
28    typedef Hash                                                       hasher;
29    typedef Pred                                                       key_equal;
30    typedef Alloc                                                      allocator_type;
31    typedef pair<const key_type, mapped_type>                          value_type;
32    typedef value_type&                                                reference;
33    typedef const value_type&                                          const_reference;
34    typedef typename allocator_traits<allocator_type>::pointer         pointer;
35    typedef typename allocator_traits<allocator_type>::const_pointer   const_pointer;
36    typedef typename allocator_traits<allocator_type>::size_type       size_type;
37    typedef typename allocator_traits<allocator_type>::difference_type difference_type;
38
39    typedef /unspecified/ iterator;
40    typedef /unspecified/ const_iterator;
41
42    hash_map();
43    explicit hash_map(size_type n, const hasher& hf = hasher(),
44                           const key_equal& eql = key_equal(),
45                           const allocator_type& a = allocator_type());
46    template <class InputIterator>
47    hash_map(InputIterator f, InputIterator l);
48    template <class InputIterator>
49    hash_map(InputIterator f, InputIterator l,
50                size_type n, const hasher& hf = hasher(),
51                const key_equal& eql = key_equal(),
52                const allocator_type& a = allocator_type());
53    hash_map(const hash_map&);
54    ~hash_map();
55    hash_map& operator=(const hash_map&);
56
57    allocator_type get_allocator() const;
58
59    bool      empty() const;
60    size_type size() const;
61    size_type max_size() const;
62
63    iterator       begin();
64    iterator       end();
65    const_iterator begin()  const;
66    const_iterator end()    const;
67
68    pair<iterator, bool> insert(const value_type& obj);
69    template <class InputIterator>
70        void insert(InputIterator first, InputIterator last);
71
72    void erase(const_iterator position);
73    size_type erase(const key_type& k);
74    void erase(const_iterator first, const_iterator last);
75    void clear();
76
77    void swap(hash_map&);
78
79    hasher hash_funct() const;
80    key_equal key_eq() const;
81
82    iterator       find(const key_type& k);
83    const_iterator find(const key_type& k) const;
84    size_type count(const key_type& k) const;
85    pair<iterator, iterator>             equal_range(const key_type& k);
86    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
87
88    mapped_type& operator[](const key_type& k);
89
90    size_type bucket_count() const;
91    size_type max_bucket_count() const;
92
93    size_type elems_in_bucket(size_type n) const;
94
95    void resize(size_type n);
96};
97
98template <class Key, class T, class Hash, class Pred, class Alloc>
99    void swap(hash_map<Key, T, Hash, Pred, Alloc>& x,
100              hash_map<Key, T, Hash, Pred, Alloc>& y);
101
102template <class Key, class T, class Hash, class Pred, class Alloc>
103    bool
104    operator==(const hash_map<Key, T, Hash, Pred, Alloc>& x,
105               const hash_map<Key, T, Hash, Pred, Alloc>& y);
106
107template <class Key, class T, class Hash, class Pred, class Alloc>
108    bool
109    operator!=(const hash_map<Key, T, Hash, Pred, Alloc>& x,
110               const hash_map<Key, T, Hash, Pred, Alloc>& y);
111
112template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>,
113          class Alloc = allocator<pair<const Key, T>>>
114class hash_multimap
115{
116public:
117    // types
118    typedef Key                                                        key_type;
119    typedef T                                                          mapped_type;
120    typedef Hash                                                       hasher;
121    typedef Pred                                                       key_equal;
122    typedef Alloc                                                      allocator_type;
123    typedef pair<const key_type, mapped_type>                          value_type;
124    typedef value_type&                                                reference;
125    typedef const value_type&                                          const_reference;
126    typedef typename allocator_traits<allocator_type>::pointer         pointer;
127    typedef typename allocator_traits<allocator_type>::const_pointer   const_pointer;
128    typedef typename allocator_traits<allocator_type>::size_type       size_type;
129    typedef typename allocator_traits<allocator_type>::difference_type difference_type;
130
131    typedef /unspecified/ iterator;
132    typedef /unspecified/ const_iterator;
133
134    explicit hash_multimap(size_type n = 193, const hasher& hf = hasher(),
135                           const key_equal& eql = key_equal(),
136                           const allocator_type& a = allocator_type());
137    template <class InputIterator>
138        hash_multimap(InputIterator f, InputIterator l,
139                      size_type n = 193, const hasher& hf = hasher(),
140                      const key_equal& eql = key_equal(),
141                      const allocator_type& a = allocator_type());
142    explicit hash_multimap(const allocator_type&);
143    hash_multimap(const hash_multimap&);
144    ~hash_multimap();
145    hash_multimap& operator=(const hash_multimap&);
146
147    allocator_type get_allocator() const;
148
149    bool      empty() const;
150    size_type size() const;
151    size_type max_size() const;
152
153    iterator       begin();
154    iterator       end();
155    const_iterator begin()  const;
156    const_iterator end()    const;
157
158    iterator insert(const value_type& obj);
159    template <class InputIterator>
160        void insert(InputIterator first, InputIterator last);
161
162    void erase(const_iterator position);
163    size_type erase(const key_type& k);
164    void erase(const_iterator first, const_iterator last);
165    void clear();
166
167    void swap(hash_multimap&);
168
169    hasher hash_funct() const;
170    key_equal key_eq() const;
171
172    iterator       find(const key_type& k);
173    const_iterator find(const key_type& k) const;
174    size_type count(const key_type& k) const;
175    pair<iterator, iterator>             equal_range(const key_type& k);
176    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
177
178    size_type bucket_count() const;
179    size_type max_bucket_count() const;
180
181    size_type elems_in_bucket(size_type n) const;
182
183    void resize(size_type n);
184};
185
186template <class Key, class T, class Hash, class Pred, class Alloc>
187    void swap(hash_multimap<Key, T, Hash, Pred, Alloc>& x,
188              hash_multimap<Key, T, Hash, Pred, Alloc>& y);
189
190template <class Key, class T, class Hash, class Pred, class Alloc>
191    bool
192    operator==(const hash_multimap<Key, T, Hash, Pred, Alloc>& x,
193               const hash_multimap<Key, T, Hash, Pred, Alloc>& y);
194
195template <class Key, class T, class Hash, class Pred, class Alloc>
196    bool
197    operator!=(const hash_multimap<Key, T, Hash, Pred, Alloc>& x,
198               const hash_multimap<Key, T, Hash, Pred, Alloc>& y);
199
200}  // __gnu_cxx
201
202*/
203
204#include <__config>
205#include <__hash_table>
206#include <algorithm>
207#include <ext/__hash>
208#include <functional>
209
210#if defined(__DEPRECATED) && __DEPRECATED
211#  if defined(_LIBCPP_WARNING)
212_LIBCPP_WARNING("Use of the header <ext/hash_map> is deprecated.  Migrate to <unordered_map>")
213#  else
214#    warning Use of the header <ext/hash_map> is deprecated.  Migrate to <unordered_map>
215#  endif
216#endif
217
218#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
219#  pragma GCC system_header
220#endif
221
222namespace __gnu_cxx {
223
224template <class _Tp, class _Hash, bool = std::is_empty<_Hash>::value && !std::__libcpp_is_final<_Hash>::value >
225class __hash_map_hasher : private _Hash {
226public:
227  _LIBCPP_HIDE_FROM_ABI __hash_map_hasher() : _Hash() {}
228  _LIBCPP_HIDE_FROM_ABI __hash_map_hasher(const _Hash& __h) : _Hash(__h) {}
229  _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const { return *this; }
230  _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Tp& __x) const { return static_cast<const _Hash&>(*this)(__x.first); }
231  _LIBCPP_HIDE_FROM_ABI size_t operator()(const typename _Tp::first_type& __x) const {
232    return static_cast<const _Hash&>(*this)(__x);
233  }
234};
235
236template <class _Tp, class _Hash>
237class __hash_map_hasher<_Tp, _Hash, false> {
238  _Hash __hash_;
239
240public:
241  _LIBCPP_HIDE_FROM_ABI __hash_map_hasher() : __hash_() {}
242  _LIBCPP_HIDE_FROM_ABI __hash_map_hasher(const _Hash& __h) : __hash_(__h) {}
243  _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const { return __hash_; }
244  _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Tp& __x) const { return __hash_(__x.first); }
245  _LIBCPP_HIDE_FROM_ABI size_t operator()(const typename _Tp::first_type& __x) const { return __hash_(__x); }
246};
247
248template <class _Tp, class _Pred, bool = std::is_empty<_Pred>::value && !std::__libcpp_is_final<_Pred>::value >
249class __hash_map_equal : private _Pred {
250public:
251  _LIBCPP_HIDE_FROM_ABI __hash_map_equal() : _Pred() {}
252  _LIBCPP_HIDE_FROM_ABI __hash_map_equal(const _Pred& __p) : _Pred(__p) {}
253  _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const { return *this; }
254  _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const {
255    return static_cast<const _Pred&>(*this)(__x.first, __y.first);
256  }
257  _LIBCPP_HIDE_FROM_ABI bool operator()(const typename _Tp::first_type& __x, const _Tp& __y) const {
258    return static_cast<const _Pred&>(*this)(__x, __y.first);
259  }
260  _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const typename _Tp::first_type& __y) const {
261    return static_cast<const _Pred&>(*this)(__x.first, __y);
262  }
263  _LIBCPP_HIDE_FROM_ABI bool
264  operator()(const typename _Tp::first_type& __x, const typename _Tp::first_type& __y) const {
265    return static_cast<const _Pred&>(*this)(__x, __y);
266  }
267};
268
269template <class _Tp, class _Pred>
270class __hash_map_equal<_Tp, _Pred, false> {
271  _Pred __pred_;
272
273public:
274  _LIBCPP_HIDE_FROM_ABI __hash_map_equal() : __pred_() {}
275  _LIBCPP_HIDE_FROM_ABI __hash_map_equal(const _Pred& __p) : __pred_(__p) {}
276  _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const { return __pred_; }
277  _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const { return __pred_(__x.first, __y.first); }
278  _LIBCPP_HIDE_FROM_ABI bool operator()(const typename _Tp::first_type& __x, const _Tp& __y) const {
279    return __pred_(__x, __y.first);
280  }
281  _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const typename _Tp::first_type& __y) const {
282    return __pred_(__x.first, __y);
283  }
284  _LIBCPP_HIDE_FROM_ABI bool
285  operator()(const typename _Tp::first_type& __x, const typename _Tp::first_type& __y) const {
286    return __pred_(__x, __y);
287  }
288};
289
290template <class _Alloc>
291class __hash_map_node_destructor {
292  typedef _Alloc allocator_type;
293  typedef std::allocator_traits<allocator_type> __alloc_traits;
294  typedef typename __alloc_traits::value_type::__node_value_type value_type;
295
296public:
297  typedef typename __alloc_traits::pointer pointer;
298
299private:
300  typedef typename value_type::first_type first_type;
301  typedef typename value_type::second_type second_type;
302
303  allocator_type& __na_;
304
305public:
306  bool __first_constructed;
307  bool __second_constructed;
308
309  _LIBCPP_HIDE_FROM_ABI __hash_map_node_destructor(__hash_map_node_destructor const&) = default;
310  __hash_map_node_destructor& operator=(const __hash_map_node_destructor&)            = delete;
311
312  _LIBCPP_HIDE_FROM_ABI explicit __hash_map_node_destructor(allocator_type& __na)
313      : __na_(__na), __first_constructed(false), __second_constructed(false) {}
314
315#ifndef _LIBCPP_CXX03_LANG
316  _LIBCPP_HIDE_FROM_ABI __hash_map_node_destructor(std::__hash_node_destructor<allocator_type>&& __x)
317      : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) {
318    __x.__value_constructed = false;
319  }
320#else  // _LIBCPP_CXX03_LANG
321  _LIBCPP_HIDE_FROM_ABI __hash_map_node_destructor(const std::__hash_node_destructor<allocator_type>& __x)
322      : __na_(__x.__na_), __first_constructed(__x.__value_constructed), __second_constructed(__x.__value_constructed) {
323    const_cast<bool&>(__x.__value_constructed) = false;
324  }
325#endif // _LIBCPP_CXX03_LANG
326
327  _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) {
328    if (__second_constructed)
329      __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().second));
330    if (__first_constructed)
331      __alloc_traits::destroy(__na_, std::addressof(__p->__get_value().first));
332    if (__p)
333      __alloc_traits::deallocate(__na_, __p, 1);
334  }
335};
336
337template <class _HashIterator>
338class _LIBCPP_TEMPLATE_VIS __hash_map_iterator {
339  _HashIterator __i_;
340
341  typedef const typename _HashIterator::value_type::first_type key_type;
342  typedef typename _HashIterator::value_type::second_type mapped_type;
343
344public:
345  typedef std::forward_iterator_tag iterator_category;
346  typedef std::pair<key_type, mapped_type> value_type;
347  typedef typename _HashIterator::difference_type difference_type;
348  typedef value_type& reference;
349  typedef std::__rebind_pointer_t<typename _HashIterator::pointer, value_type> pointer;
350
351  _LIBCPP_HIDE_FROM_ABI __hash_map_iterator() {}
352
353  _LIBCPP_HIDE_FROM_ABI __hash_map_iterator(_HashIterator __i) : __i_(__i) {}
354
355  _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *operator->(); }
356  _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return (pointer)__i_.operator->(); }
357
358  _LIBCPP_HIDE_FROM_ABI __hash_map_iterator& operator++() {
359    ++__i_;
360    return *this;
361  }
362  _LIBCPP_HIDE_FROM_ABI __hash_map_iterator operator++(int) {
363    __hash_map_iterator __t(*this);
364    ++(*this);
365    return __t;
366  }
367
368  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {
369    return __x.__i_ == __y.__i_;
370  }
371  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {
372    return __x.__i_ != __y.__i_;
373  }
374
375  template <class, class, class, class, class>
376  friend class _LIBCPP_TEMPLATE_VIS hash_map;
377  template <class, class, class, class, class>
378  friend class _LIBCPP_TEMPLATE_VIS hash_multimap;
379  template <class>
380  friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
381  template <class>
382  friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
383  template <class>
384  friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
385};
386
387template <class _HashIterator>
388class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator {
389  _HashIterator __i_;
390
391  typedef const typename _HashIterator::value_type::first_type key_type;
392  typedef typename _HashIterator::value_type::second_type mapped_type;
393
394public:
395  typedef std::forward_iterator_tag iterator_category;
396  typedef std::pair<key_type, mapped_type> value_type;
397  typedef typename _HashIterator::difference_type difference_type;
398  typedef const value_type& reference;
399  typedef std::__rebind_pointer_t<typename _HashIterator::pointer, const value_type> pointer;
400
401  _LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator() {}
402
403  _LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator(_HashIterator __i) : __i_(__i) {}
404  _LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator(__hash_map_iterator<typename _HashIterator::__non_const_iterator> __i)
405      : __i_(__i.__i_) {}
406
407  _LIBCPP_HIDE_FROM_ABI reference operator*() const { return *operator->(); }
408  _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return (pointer)__i_.operator->(); }
409
410  _LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator& operator++() {
411    ++__i_;
412    return *this;
413  }
414  _LIBCPP_HIDE_FROM_ABI __hash_map_const_iterator operator++(int) {
415    __hash_map_const_iterator __t(*this);
416    ++(*this);
417    return __t;
418  }
419
420  friend _LIBCPP_HIDE_FROM_ABI bool
421  operator==(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {
422    return __x.__i_ == __y.__i_;
423  }
424  friend _LIBCPP_HIDE_FROM_ABI bool
425  operator!=(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {
426    return __x.__i_ != __y.__i_;
427  }
428
429  template <class, class, class, class, class>
430  friend class _LIBCPP_TEMPLATE_VIS hash_map;
431  template <class, class, class, class, class>
432  friend class _LIBCPP_TEMPLATE_VIS hash_multimap;
433  template <class>
434  friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
435  template <class>
436  friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
437};
438
439template <class _Key,
440          class _Tp,
441          class _Hash  = hash<_Key>,
442          class _Pred  = std::equal_to<_Key>,
443          class _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
444class _LIBCPP_TEMPLATE_VIS hash_map {
445public:
446  // types
447  typedef _Key key_type;
448  typedef _Tp mapped_type;
449  typedef _Tp data_type;
450  typedef _Hash hasher;
451  typedef _Pred key_equal;
452  typedef _Alloc allocator_type;
453  typedef std::pair<const key_type, mapped_type> value_type;
454  typedef value_type& reference;
455  typedef const value_type& const_reference;
456
457private:
458  typedef std::pair<key_type, mapped_type> __value_type;
459  typedef __hash_map_hasher<__value_type, hasher> __hasher;
460  typedef __hash_map_equal<__value_type, key_equal> __key_equal;
461  typedef std::__rebind_alloc<std::allocator_traits<allocator_type>, __value_type> __allocator_type;
462
463  typedef std::__hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table;
464
465  __table __table_;
466
467  typedef typename __table::__node_pointer __node_pointer;
468  typedef typename __table::__node_const_pointer __node_const_pointer;
469  typedef typename __table::__node_traits __node_traits;
470  typedef typename __table::__node_allocator __node_allocator;
471  typedef typename __table::__node __node;
472  typedef __hash_map_node_destructor<__node_allocator> _Dp;
473  typedef std::unique_ptr<__node, _Dp> __node_holder;
474  typedef std::allocator_traits<allocator_type> __alloc_traits;
475
476public:
477  typedef typename __alloc_traits::pointer pointer;
478  typedef typename __alloc_traits::const_pointer const_pointer;
479  typedef typename __alloc_traits::size_type size_type;
480  typedef typename __alloc_traits::difference_type difference_type;
481
482  typedef __hash_map_iterator<typename __table::iterator> iterator;
483  typedef __hash_map_const_iterator<typename __table::const_iterator> const_iterator;
484
485  _LIBCPP_HIDE_FROM_ABI hash_map() {}
486  explicit _LIBCPP_HIDE_FROM_ABI
487  hash_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal());
488  _LIBCPP_HIDE_FROM_ABI hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
489  template <class _InputIterator>
490  _LIBCPP_HIDE_FROM_ABI hash_map(_InputIterator __first, _InputIterator __last);
491  template <class _InputIterator>
492  _LIBCPP_HIDE_FROM_ABI
493  hash_map(_InputIterator __first,
494           _InputIterator __last,
495           size_type __n,
496           const hasher& __hf     = hasher(),
497           const key_equal& __eql = key_equal());
498  template <class _InputIterator>
499  _LIBCPP_HIDE_FROM_ABI
500  hash_map(_InputIterator __first,
501           _InputIterator __last,
502           size_type __n,
503           const hasher& __hf,
504           const key_equal& __eql,
505           const allocator_type& __a);
506  _LIBCPP_HIDE_FROM_ABI hash_map(const hash_map& __u);
507
508  _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return allocator_type(__table_.__node_alloc()); }
509
510  _LIBCPP_HIDE_FROM_ABI bool empty() const { return __table_.size() == 0; }
511  _LIBCPP_HIDE_FROM_ABI size_type size() const { return __table_.size(); }
512  _LIBCPP_HIDE_FROM_ABI size_type max_size() const { return __table_.max_size(); }
513
514  _LIBCPP_HIDE_FROM_ABI iterator begin() { return __table_.begin(); }
515  _LIBCPP_HIDE_FROM_ABI iterator end() { return __table_.end(); }
516  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return __table_.begin(); }
517  _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __table_.end(); }
518
519  _LIBCPP_HIDE_FROM_ABI std::pair<iterator, bool> insert(const value_type& __x) {
520    return __table_.__insert_unique(__x);
521  }
522  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x).first; }
523  template <class _InputIterator>
524  _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last);
525
526  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __p) { __table_.erase(__p.__i_); }
527  _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_unique(__k); }
528  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __first, const_iterator __last) {
529    __table_.erase(__first.__i_, __last.__i_);
530  }
531  _LIBCPP_HIDE_FROM_ABI void clear() { __table_.clear(); }
532
533  _LIBCPP_HIDE_FROM_ABI void swap(hash_map& __u) { __table_.swap(__u.__table_); }
534
535  _LIBCPP_HIDE_FROM_ABI hasher hash_funct() const { return __table_.hash_function().hash_function(); }
536  _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq().key_eq(); }
537
538  _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
539  _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
540  _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_unique(__k); }
541  _LIBCPP_HIDE_FROM_ABI std::pair<iterator, iterator> equal_range(const key_type& __k) {
542    return __table_.__equal_range_unique(__k);
543  }
544  _LIBCPP_HIDE_FROM_ABI std::pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
545    return __table_.__equal_range_unique(__k);
546  }
547
548  _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k);
549
550  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const { return __table_.bucket_count(); }
551  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const { return __table_.max_bucket_count(); }
552
553  _LIBCPP_HIDE_FROM_ABI size_type elems_in_bucket(size_type __n) const { return __table_.bucket_size(__n); }
554
555  _LIBCPP_HIDE_FROM_ABI void resize(size_type __n) { __table_.__rehash_unique(__n); }
556
557private:
558  _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(const key_type& __k);
559};
560
561template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
562hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map(size_type __n, const hasher& __hf, const key_equal& __eql)
563    : __table_(__hf, __eql) {
564  __table_.__rehash_unique(__n);
565}
566
567template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
568hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map(
569    size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
570    : __table_(__hf, __eql, __a) {
571  __table_.__rehash_unique(__n);
572}
573
574template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
575template <class _InputIterator>
576hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map(_InputIterator __first, _InputIterator __last) {
577  insert(__first, __last);
578}
579
580template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
581template <class _InputIterator>
582hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map(
583    _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql)
584    : __table_(__hf, __eql) {
585  __table_.__rehash_unique(__n);
586  insert(__first, __last);
587}
588
589template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
590template <class _InputIterator>
591hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map(
592    _InputIterator __first,
593    _InputIterator __last,
594    size_type __n,
595    const hasher& __hf,
596    const key_equal& __eql,
597    const allocator_type& __a)
598    : __table_(__hf, __eql, __a) {
599  __table_.__rehash_unique(__n);
600  insert(__first, __last);
601}
602
603template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
604hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_map(const hash_map& __u) : __table_(__u.__table_) {
605  __table_.__rehash_unique(__u.bucket_count());
606  insert(__u.begin(), __u.end());
607}
608
609template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
610typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__node_holder
611hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::__construct_node(const key_type& __k) {
612  __node_allocator& __na = __table_.__node_alloc();
613  __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
614  __node_traits::construct(__na, std::addressof(__h->__get_value().first), __k);
615  __h.get_deleter().__first_constructed = true;
616  __node_traits::construct(__na, std::addressof(__h->__get_value().second));
617  __h.get_deleter().__second_constructed = true;
618  return __h;
619}
620
621template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
622template <class _InputIterator>
623inline void hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) {
624  for (; __first != __last; ++__first)
625    __table_.__insert_unique(*__first);
626}
627
628template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
629_Tp& hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type& __k) {
630  iterator __i = find(__k);
631  if (__i != end())
632    return __i->second;
633  __node_holder __h             = __construct_node(__k);
634  std::pair<iterator, bool> __r = __table_.__node_insert_unique(__h.get());
635  __h.release();
636  return __r.first->second;
637}
638
639template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
640inline _LIBCPP_HIDE_FROM_ABI void
641swap(hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) {
642  __x.swap(__y);
643}
644
645template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
646_LIBCPP_HIDE_FROM_ABI bool
647operator==(const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) {
648  if (__x.size() != __y.size())
649    return false;
650  typedef typename hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator;
651  for (const_iterator __i = __x.begin(), __ex = __x.end(), __ey = __y.end(); __i != __ex; ++__i) {
652    const_iterator __j = __y.find(__i->first);
653    if (__j == __ey || !(*__i == *__j))
654      return false;
655  }
656  return true;
657}
658
659template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
660inline _LIBCPP_HIDE_FROM_ABI bool
661operator!=(const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, const hash_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) {
662  return !(__x == __y);
663}
664
665template <class _Key,
666          class _Tp,
667          class _Hash  = hash<_Key>,
668          class _Pred  = std::equal_to<_Key>,
669          class _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
670class _LIBCPP_TEMPLATE_VIS hash_multimap {
671public:
672  // types
673  typedef _Key key_type;
674  typedef _Tp mapped_type;
675  typedef _Tp data_type;
676  typedef _Hash hasher;
677  typedef _Pred key_equal;
678  typedef _Alloc allocator_type;
679  typedef std::pair<const key_type, mapped_type> value_type;
680  typedef value_type& reference;
681  typedef const value_type& const_reference;
682
683private:
684  typedef std::pair<key_type, mapped_type> __value_type;
685  typedef __hash_map_hasher<__value_type, hasher> __hasher;
686  typedef __hash_map_equal<__value_type, key_equal> __key_equal;
687  typedef std::__rebind_alloc<std::allocator_traits<allocator_type>, __value_type> __allocator_type;
688
689  typedef std::__hash_table<__value_type, __hasher, __key_equal, __allocator_type> __table;
690
691  __table __table_;
692
693  typedef typename __table::__node_traits __node_traits;
694  typedef typename __table::__node_allocator __node_allocator;
695  typedef typename __table::__node __node;
696  typedef __hash_map_node_destructor<__node_allocator> _Dp;
697  typedef std::unique_ptr<__node, _Dp> __node_holder;
698  typedef std::allocator_traits<allocator_type> __alloc_traits;
699
700public:
701  typedef typename __alloc_traits::pointer pointer;
702  typedef typename __alloc_traits::const_pointer const_pointer;
703  typedef typename __alloc_traits::size_type size_type;
704  typedef typename __alloc_traits::difference_type difference_type;
705
706  typedef __hash_map_iterator<typename __table::iterator> iterator;
707  typedef __hash_map_const_iterator<typename __table::const_iterator> const_iterator;
708
709  _LIBCPP_HIDE_FROM_ABI hash_multimap() {}
710  explicit _LIBCPP_HIDE_FROM_ABI
711  hash_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal());
712  _LIBCPP_HIDE_FROM_ABI
713  hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
714  template <class _InputIterator>
715  _LIBCPP_HIDE_FROM_ABI hash_multimap(_InputIterator __first, _InputIterator __last);
716  template <class _InputIterator>
717  _LIBCPP_HIDE_FROM_ABI
718  hash_multimap(_InputIterator __first,
719                _InputIterator __last,
720                size_type __n,
721                const hasher& __hf     = hasher(),
722                const key_equal& __eql = key_equal());
723  template <class _InputIterator>
724  _LIBCPP_HIDE_FROM_ABI hash_multimap(
725      _InputIterator __first,
726      _InputIterator __last,
727      size_type __n,
728      const hasher& __hf,
729      const key_equal& __eql,
730      const allocator_type& __a);
731  _LIBCPP_HIDE_FROM_ABI hash_multimap(const hash_multimap& __u);
732
733  _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return allocator_type(__table_.__node_alloc()); }
734
735  _LIBCPP_HIDE_FROM_ABI bool empty() const { return __table_.size() == 0; }
736  _LIBCPP_HIDE_FROM_ABI size_type size() const { return __table_.size(); }
737  _LIBCPP_HIDE_FROM_ABI size_type max_size() const { return __table_.max_size(); }
738
739  _LIBCPP_HIDE_FROM_ABI iterator begin() { return __table_.begin(); }
740  _LIBCPP_HIDE_FROM_ABI iterator end() { return __table_.end(); }
741  _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return __table_.begin(); }
742  _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __table_.end(); }
743
744  _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__insert_multi(__x); }
745  _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x); }
746  template <class _InputIterator>
747  _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last);
748
749  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __p) { __table_.erase(__p.__i_); }
750  _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __k) { return __table_.__erase_multi(__k); }
751  _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __first, const_iterator __last) {
752    __table_.erase(__first.__i_, __last.__i_);
753  }
754  _LIBCPP_HIDE_FROM_ABI void clear() { __table_.clear(); }
755
756  _LIBCPP_HIDE_FROM_ABI void swap(hash_multimap& __u) { __table_.swap(__u.__table_); }
757
758  _LIBCPP_HIDE_FROM_ABI hasher hash_funct() const { return __table_.hash_function().hash_function(); }
759  _LIBCPP_HIDE_FROM_ABI key_equal key_eq() const { return __table_.key_eq().key_eq(); }
760
761  _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __table_.find(__k); }
762  _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __table_.find(__k); }
763  _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __k) const { return __table_.__count_multi(__k); }
764  _LIBCPP_HIDE_FROM_ABI std::pair<iterator, iterator> equal_range(const key_type& __k) {
765    return __table_.__equal_range_multi(__k);
766  }
767  _LIBCPP_HIDE_FROM_ABI std::pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {
768    return __table_.__equal_range_multi(__k);
769  }
770
771  _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const { return __table_.bucket_count(); }
772  _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const { return __table_.max_bucket_count(); }
773
774  _LIBCPP_HIDE_FROM_ABI size_type elems_in_bucket(size_type __n) const { return __table_.bucket_size(__n); }
775
776  _LIBCPP_HIDE_FROM_ABI void resize(size_type __n) { __table_.__rehash_multi(__n); }
777};
778
779template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
780hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql)
781    : __table_(__hf, __eql) {
782  __table_.__rehash_multi(__n);
783}
784
785template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
786hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap(
787    size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
788    : __table_(__hf, __eql, __a) {
789  __table_.__rehash_multi(__n);
790}
791
792template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
793template <class _InputIterator>
794hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap(_InputIterator __first, _InputIterator __last) {
795  insert(__first, __last);
796}
797
798template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
799template <class _InputIterator>
800hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap(
801    _InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql)
802    : __table_(__hf, __eql) {
803  __table_.__rehash_multi(__n);
804  insert(__first, __last);
805}
806
807template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
808template <class _InputIterator>
809hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap(
810    _InputIterator __first,
811    _InputIterator __last,
812    size_type __n,
813    const hasher& __hf,
814    const key_equal& __eql,
815    const allocator_type& __a)
816    : __table_(__hf, __eql, __a) {
817  __table_.__rehash_multi(__n);
818  insert(__first, __last);
819}
820
821template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
822hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::hash_multimap(const hash_multimap& __u) : __table_(__u.__table_) {
823  __table_.__rehash_multi(__u.bucket_count());
824  insert(__u.begin(), __u.end());
825}
826
827template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
828template <class _InputIterator>
829inline void hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) {
830  for (; __first != __last; ++__first)
831    __table_.__insert_multi(*__first);
832}
833
834template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
835inline _LIBCPP_HIDE_FROM_ABI void
836swap(hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) {
837  __x.swap(__y);
838}
839
840template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
841_LIBCPP_HIDE_FROM_ABI bool operator==(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
842                                      const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) {
843  if (__x.size() != __y.size())
844    return false;
845  typedef typename hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::const_iterator const_iterator;
846  typedef std::pair<const_iterator, const_iterator> _EqRng;
847  for (const_iterator __i = __x.begin(), __ex = __x.end(); __i != __ex;) {
848    _EqRng __xeq = __x.equal_range(__i->first);
849    _EqRng __yeq = __y.equal_range(__i->first);
850    if (std::distance(__xeq.first, __xeq.second) != std::distance(__yeq.first, __yeq.second) ||
851        !std::is_permutation(__xeq.first, __xeq.second, __yeq.first))
852      return false;
853    __i = __xeq.second;
854  }
855  return true;
856}
857
858template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
859inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
860                                             const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) {
861  return !(__x == __y);
862}
863
864} // namespace __gnu_cxx
865
866#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
867#  include <concepts>
868#  include <iterator>
869#  include <type_traits>
870#endif
871
872#endif // _LIBCPP_HASH_MAP
873