Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:24

0001 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
0002 // Copyright (C) 2005-2011 Daniel James.
0003 // Copyright (C) 2022-2023 Christian Mazakas
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 //  See http://www.boost.org/libs/unordered for documentation
0008 
0009 #ifndef BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
0010 #define BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
0011 
0012 #include <boost/config.hpp>
0013 #if defined(BOOST_HAS_PRAGMA_ONCE)
0014 #pragma once
0015 #endif
0016 
0017 #include <boost/unordered/detail/map.hpp>
0018 #include <boost/unordered/detail/serialize_fca_container.hpp>
0019 #include <boost/unordered/detail/type_traits.hpp>
0020 
0021 #include <boost/container_hash/hash.hpp>
0022 
0023 #include <initializer_list>
0024 
0025 #if defined(BOOST_MSVC)
0026 #pragma warning(push)
0027 // conditional expression is constant
0028 #pragma warning(disable : 4127)
0029 #if BOOST_MSVC >= 1400
0030 // the inline specifier cannot be used when a friend declaration refers to a
0031 // specialization of a function template
0032 #pragma warning(disable : 4396)
0033 #endif
0034 #endif
0035 
0036 namespace boost {
0037   namespace unordered {
0038     template <class K, class T, class H, class P, class A> class unordered_map
0039     {
0040       template <typename, typename, typename, typename, typename>
0041       friend class unordered_multimap;
0042 
0043     public:
0044       typedef K key_type;
0045       typedef T mapped_type;
0046       typedef std::pair<const K, T> value_type;
0047       typedef typename boost::unordered::detail::type_identity<H>::type hasher;
0048       typedef
0049         typename boost::unordered::detail::type_identity<P>::type key_equal;
0050       typedef typename boost::unordered::detail::type_identity<A>::type
0051         allocator_type;
0052 
0053     private:
0054       typedef boost::unordered::detail::map<A, K, T, H, P> types;
0055       typedef typename types::value_allocator_traits value_allocator_traits;
0056       typedef typename types::table table;
0057 
0058     public:
0059       typedef typename value_allocator_traits::pointer pointer;
0060       typedef typename value_allocator_traits::const_pointer const_pointer;
0061 
0062       typedef value_type& reference;
0063       typedef value_type const& const_reference;
0064 
0065       typedef std::size_t size_type;
0066       typedef std::ptrdiff_t difference_type;
0067 
0068       typedef typename table::iterator iterator;
0069       typedef typename table::c_iterator const_iterator;
0070       typedef typename table::l_iterator local_iterator;
0071       typedef typename table::cl_iterator const_local_iterator;
0072       typedef typename types::node_type node_type;
0073       typedef typename types::insert_return_type insert_return_type;
0074 
0075     private:
0076       table table_;
0077 
0078     public:
0079       // constructors
0080 
0081       unordered_map();
0082 
0083       explicit unordered_map(size_type, const hasher& = hasher(),
0084         const key_equal& = key_equal(),
0085         const allocator_type& = allocator_type());
0086 
0087       template <class InputIt>
0088       unordered_map(InputIt, InputIt,
0089         size_type = boost::unordered::detail::default_bucket_count,
0090         const hasher& = hasher(), const key_equal& = key_equal(),
0091         const allocator_type& = allocator_type());
0092 
0093       unordered_map(unordered_map const&);
0094 
0095       unordered_map(unordered_map&& other)
0096         noexcept(table::nothrow_move_constructible)
0097           : table_(other.table_, boost::unordered::detail::move_tag())
0098       {
0099         // The move is done in table_
0100       }
0101 
0102       explicit unordered_map(allocator_type const&);
0103 
0104       unordered_map(unordered_map const&, allocator_type const&);
0105 
0106       unordered_map(unordered_map&&, allocator_type const&);
0107 
0108       unordered_map(std::initializer_list<value_type>,
0109         size_type = boost::unordered::detail::default_bucket_count,
0110         const hasher& = hasher(), const key_equal& l = key_equal(),
0111         const allocator_type& = allocator_type());
0112 
0113       explicit unordered_map(size_type, const allocator_type&);
0114 
0115       explicit unordered_map(size_type, const hasher&, const allocator_type&);
0116 
0117       template <class InputIterator>
0118       unordered_map(InputIterator, InputIterator, const allocator_type&);
0119 
0120       template <class InputIt>
0121       unordered_map(InputIt, InputIt, size_type, const allocator_type&);
0122 
0123       template <class InputIt>
0124       unordered_map(
0125         InputIt, InputIt, size_type, const hasher&, const allocator_type&);
0126 
0127       unordered_map(std::initializer_list<value_type>, const allocator_type&);
0128 
0129       unordered_map(
0130         std::initializer_list<value_type>, size_type, const allocator_type&);
0131 
0132       unordered_map(std::initializer_list<value_type>, size_type, const hasher&,
0133         const allocator_type&);
0134 
0135       // Destructor
0136 
0137       ~unordered_map() noexcept;
0138 
0139       // Assign
0140 
0141       unordered_map& operator=(unordered_map const& x)
0142       {
0143         table_.assign(x.table_, std::true_type());
0144         return *this;
0145       }
0146 
0147       unordered_map& operator=(unordered_map&& x)
0148         noexcept(value_allocator_traits::is_always_equal::value&&
0149             std::is_nothrow_move_assignable<H>::value&&
0150               std::is_nothrow_move_assignable<P>::value)
0151       {
0152         table_.move_assign(x.table_, std::true_type());
0153         return *this;
0154       }
0155 
0156       unordered_map& operator=(std::initializer_list<value_type>);
0157 
0158       allocator_type get_allocator() const noexcept
0159       {
0160         return table_.node_alloc();
0161       }
0162 
0163       //       // iterators
0164 
0165       iterator begin() noexcept { return table_.begin(); }
0166 
0167       const_iterator begin() const noexcept
0168       {
0169         return const_iterator(table_.begin());
0170       }
0171 
0172       iterator end() noexcept { return iterator(); }
0173 
0174       const_iterator end() const noexcept { return const_iterator(); }
0175 
0176       const_iterator cbegin() const noexcept
0177       {
0178         return const_iterator(table_.begin());
0179       }
0180 
0181       const_iterator cend() const noexcept { return const_iterator(); }
0182 
0183       // size and capacity
0184 
0185       BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0186       {
0187         return table_.size_ == 0;
0188       }
0189 
0190       size_type size() const noexcept { return table_.size_; }
0191 
0192       size_type max_size() const noexcept;
0193 
0194       // emplace
0195 
0196       template <class... Args> std::pair<iterator, bool> emplace(Args&&... args)
0197       {
0198         return table_.emplace_unique(
0199           table::extractor::extract(std::forward<Args>(args)...),
0200           std::forward<Args>(args)...);
0201       }
0202 
0203       template <class... Args>
0204       iterator emplace_hint(const_iterator hint, Args&&... args)
0205       {
0206         return table_.emplace_hint_unique(hint,
0207           table::extractor::extract(std::forward<Args>(args)...),
0208           std::forward<Args>(args)...);
0209       }
0210 
0211       std::pair<iterator, bool> insert(value_type const& x)
0212       {
0213         return this->emplace(x);
0214       }
0215 
0216       std::pair<iterator, bool> insert(value_type&& x)
0217       {
0218         return this->emplace(std::move(x));
0219       }
0220 
0221       template <class P2>
0222       typename boost::enable_if<std::is_constructible<value_type, P2&&>,
0223         std::pair<iterator, bool> >::type
0224       insert(P2&& obj)
0225       {
0226         return this->emplace(std::forward<P2>(obj));
0227       }
0228 
0229       iterator insert(const_iterator hint, value_type const& x)
0230       {
0231         return this->emplace_hint(hint, x);
0232       }
0233 
0234       iterator insert(const_iterator hint, value_type&& x)
0235       {
0236         return this->emplace_hint(hint, std::move(x));
0237       }
0238 
0239       template <class P2>
0240       typename boost::enable_if<std::is_constructible<value_type, P2&&>,
0241         iterator>::type
0242       insert(const_iterator hint, P2&& obj)
0243       {
0244         return this->emplace_hint(hint, std::forward<P2>(obj));
0245       }
0246 
0247       template <class InputIt> void insert(InputIt, InputIt);
0248 
0249       void insert(std::initializer_list<value_type>);
0250 
0251       // extract
0252 
0253       node_type extract(const_iterator position)
0254       {
0255         return node_type(
0256           table_.extract_by_iterator_unique(position), table_.node_alloc());
0257       }
0258 
0259       node_type extract(const key_type& k)
0260       {
0261         return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0262       }
0263 
0264       template <class Key>
0265       typename boost::enable_if_c<
0266         detail::transparent_non_iterable<Key, unordered_map>::value,
0267         node_type>::type
0268       extract(Key&& k)
0269       {
0270         return node_type(table_.extract_by_key_impl(std::forward<Key>(k)),
0271           table_.node_alloc());
0272       }
0273 
0274       insert_return_type insert(node_type&& np)
0275       {
0276         insert_return_type result;
0277         table_.move_insert_node_type_unique((node_type&)np, result);
0278         return result;
0279       }
0280 
0281       iterator insert(const_iterator hint, node_type&& np)
0282       {
0283         return table_.move_insert_node_type_with_hint_unique(hint, np);
0284       }
0285 
0286       template <class... Args>
0287       std::pair<iterator, bool> try_emplace(key_type const& k, Args&&... args)
0288       {
0289         return table_.try_emplace_unique(k, std::forward<Args>(args)...);
0290       }
0291 
0292       template <class... Args>
0293       std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args)
0294       {
0295         return table_.try_emplace_unique(
0296           std::move(k), std::forward<Args>(args)...);
0297       }
0298 
0299       template <class Key, class... Args>
0300       typename boost::enable_if_c<
0301         detail::transparent_non_iterable<Key, unordered_map>::value,
0302         std::pair<iterator, bool> >::type
0303       try_emplace(Key&& k, Args&&... args)
0304       {
0305         return table_.try_emplace_unique(
0306           std::forward<Key>(k), std::forward<Args>(args)...);
0307       }
0308 
0309       template <class... Args>
0310       iterator try_emplace(
0311         const_iterator hint, key_type const& k, Args&&... args)
0312       {
0313         return table_.try_emplace_hint_unique(
0314           hint, k, std::forward<Args>(args)...);
0315       }
0316 
0317       template <class... Args>
0318       iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args)
0319       {
0320         return table_.try_emplace_hint_unique(
0321           hint, std::move(k), std::forward<Args>(args)...);
0322       }
0323 
0324       template <class Key, class... Args>
0325       typename boost::enable_if_c<
0326         detail::transparent_non_iterable<Key, unordered_map>::value,
0327         iterator>::type
0328       try_emplace(const_iterator hint, Key&& k, Args&&... args)
0329       {
0330         return table_.try_emplace_hint_unique(
0331           hint, std::forward<Key>(k), std::forward<Args>(args)...);
0332       }
0333 
0334       template <class M>
0335       std::pair<iterator, bool> insert_or_assign(key_type const& k, M&& obj)
0336       {
0337         return table_.insert_or_assign_unique(k, std::forward<M>(obj));
0338       }
0339 
0340       template <class M>
0341       std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj)
0342       {
0343         return table_.insert_or_assign_unique(
0344           std::move(k), std::forward<M>(obj));
0345       }
0346 
0347       template <class Key, class M>
0348       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0349         std::pair<iterator, bool> >::type
0350       insert_or_assign(Key&& k, M&& obj)
0351       {
0352         return table_.insert_or_assign_unique(
0353           std::forward<Key>(k), std::forward<M>(obj));
0354       }
0355 
0356       template <class M>
0357       iterator insert_or_assign(const_iterator, key_type const& k, M&& obj)
0358       {
0359         return table_.insert_or_assign_unique(k, std::forward<M>(obj)).first;
0360       }
0361 
0362       template <class M>
0363       iterator insert_or_assign(const_iterator, key_type&& k, M&& obj)
0364       {
0365         return table_
0366           .insert_or_assign_unique(std::move(k), std::forward<M>(obj))
0367           .first;
0368       }
0369 
0370       template <class Key, class M>
0371       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0372         iterator>::type
0373       insert_or_assign(const_iterator, Key&& k, M&& obj)
0374       {
0375         return table_
0376           .insert_or_assign_unique(std::forward<Key>(k), std::forward<M>(obj))
0377           .first;
0378       }
0379 
0380       iterator erase(iterator);
0381       iterator erase(const_iterator);
0382       size_type erase(const key_type&);
0383       iterator erase(const_iterator, const_iterator);
0384 
0385       template <class Key>
0386       typename boost::enable_if_c<
0387         detail::transparent_non_iterable<Key, unordered_map>::value,
0388         size_type>::type
0389       erase(Key&& k)
0390       {
0391         return table_.erase_key_unique_impl(std::forward<Key>(k));
0392       }
0393 
0394       BOOST_UNORDERED_DEPRECATED("Use erase instead")
0395       void quick_erase(const_iterator it) { erase(it); }
0396       BOOST_UNORDERED_DEPRECATED("Use erase instead")
0397       void erase_return_void(const_iterator it) { erase(it); }
0398 
0399       void swap(unordered_map&)
0400         noexcept(value_allocator_traits::is_always_equal::value&&
0401             boost::unordered::detail::is_nothrow_swappable<H>::value&&
0402               boost::unordered::detail::is_nothrow_swappable<P>::value);
0403       void clear() noexcept { table_.clear_impl(); }
0404 
0405       template <typename H2, typename P2>
0406       void merge(boost::unordered_map<K, T, H2, P2, A>& source);
0407 
0408       template <typename H2, typename P2>
0409       void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
0410 
0411       template <typename H2, typename P2>
0412       void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
0413 
0414       template <typename H2, typename P2>
0415       void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
0416 
0417       // observers
0418 
0419       hasher hash_function() const;
0420       key_equal key_eq() const;
0421 
0422       // lookup
0423 
0424       iterator find(const key_type&);
0425       const_iterator find(const key_type&) const;
0426 
0427       template <class Key>
0428       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0429         iterator>::type
0430       find(const Key& key)
0431       {
0432         return table_.find(key);
0433       }
0434 
0435       template <class Key>
0436       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0437         const_iterator>::type
0438       find(const Key& key) const
0439       {
0440         return const_iterator(table_.find(key));
0441       }
0442 
0443       template <class CompatibleKey, class CompatibleHash,
0444         class CompatiblePredicate>
0445       iterator find(CompatibleKey const&, CompatibleHash const&,
0446         CompatiblePredicate const&);
0447 
0448       template <class CompatibleKey, class CompatibleHash,
0449         class CompatiblePredicate>
0450       const_iterator find(CompatibleKey const&, CompatibleHash const&,
0451         CompatiblePredicate const&) const;
0452 
0453       bool contains(const key_type& k) const
0454       {
0455         return table_.find(k) != this->end();
0456       }
0457 
0458       template <class Key>
0459       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0460         bool>::type
0461       contains(const Key& k) const
0462       {
0463         return table_.find(k) != this->end();
0464       }
0465 
0466       size_type count(const key_type&) const;
0467 
0468       template <class Key>
0469       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0470         size_type>::type
0471       count(const Key& k) const
0472       {
0473         return (table_.find(k) != this->end() ? 1 : 0);
0474       }
0475 
0476       std::pair<iterator, iterator> equal_range(const key_type&);
0477       std::pair<const_iterator, const_iterator> equal_range(
0478         const key_type&) const;
0479 
0480       template <class Key>
0481       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0482         std::pair<iterator, iterator> >::type
0483       equal_range(const Key& key)
0484       {
0485         iterator first = table_.find(key);
0486         iterator last = first;
0487         if (last != this->end()) {
0488           ++last;
0489         }
0490 
0491         return std::make_pair(first, last);
0492       }
0493 
0494       template <class Key>
0495       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0496         std::pair<const_iterator, const_iterator> >::type
0497       equal_range(const Key& key) const
0498       {
0499         iterator first = table_.find(key);
0500         iterator last = first;
0501         if (last != this->end()) {
0502           ++last;
0503         }
0504 
0505         return std::make_pair(first, last);
0506       }
0507 
0508       mapped_type& operator[](const key_type&);
0509       mapped_type& operator[](key_type&&);
0510 
0511       template <class Key>
0512       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0513         mapped_type&>::type
0514       operator[](Key&& k);
0515 
0516       mapped_type& at(const key_type&);
0517       mapped_type const& at(const key_type&) const;
0518 
0519       template <class Key>
0520       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0521         mapped_type&>::type
0522       at(Key&& k);
0523 
0524       template <class Key>
0525       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0526         mapped_type const&>::type
0527       at(Key&& k) const;
0528 
0529       // bucket interface
0530 
0531       size_type bucket_count() const noexcept { return table_.bucket_count(); }
0532 
0533       size_type max_bucket_count() const noexcept
0534       {
0535         return table_.max_bucket_count();
0536       }
0537 
0538       size_type bucket_size(size_type) const;
0539 
0540       size_type bucket(const key_type& k) const
0541       {
0542         return table_.hash_to_bucket(table_.hash(k));
0543       }
0544 
0545       template <class Key>
0546       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0547         size_type>::type
0548       bucket(Key&& k) const
0549       {
0550         return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
0551       }
0552 
0553       local_iterator begin(size_type n) { return table_.begin(n); }
0554 
0555       const_local_iterator begin(size_type n) const
0556       {
0557         return const_local_iterator(table_.begin(n));
0558       }
0559 
0560       local_iterator end(size_type) { return local_iterator(); }
0561       const_local_iterator end(size_type) const
0562       {
0563         return const_local_iterator();
0564       }
0565 
0566       const_local_iterator cbegin(size_type n) const
0567       {
0568         return const_local_iterator(table_.begin(n));
0569       }
0570 
0571       const_local_iterator cend(size_type) const
0572       {
0573         return const_local_iterator();
0574       }
0575 
0576       // hash policy
0577 
0578       float load_factor() const noexcept;
0579       float max_load_factor() const noexcept { return table_.mlf_; }
0580       void max_load_factor(float) noexcept;
0581       void rehash(size_type);
0582       void reserve(size_type);
0583 
0584 #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
0585       friend bool operator==
0586         <K, T, H, P, A>(unordered_map const&, unordered_map const&);
0587       friend bool operator!=
0588         <K, T, H, P, A>(unordered_map const&, unordered_map const&);
0589 #endif
0590     }; // class template unordered_map
0591 
0592     template <class Archive, class K, class T, class H, class P, class A>
0593     void serialize(
0594       Archive& ar, unordered_map<K, T, H, P, A>& m, unsigned int version)
0595     {
0596       detail::serialize_fca_container(ar, m, version);
0597     }
0598 
0599 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0600 
0601     template <class InputIterator,
0602       class Hash =
0603         boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0604       class Pred =
0605         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0606       class Allocator = std::allocator<
0607         boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
0608       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0609       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0610       class = std::enable_if_t<detail::is_pred_v<Pred> >,
0611       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0612     unordered_map(InputIterator, InputIterator,
0613       std::size_t = boost::unordered::detail::default_bucket_count,
0614       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0615       -> unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
0616         boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
0617         Allocator>;
0618 
0619     template <class Key, class T,
0620       class Hash = boost::hash<std::remove_const_t<Key> >,
0621       class Pred = std::equal_to<std::remove_const_t<Key> >,
0622       class Allocator = std::allocator<std::pair<const Key, T> >,
0623       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0624       class = std::enable_if_t<detail::is_pred_v<Pred> >,
0625       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0626     unordered_map(std::initializer_list<std::pair<Key, T> >,
0627       std::size_t = boost::unordered::detail::default_bucket_count,
0628       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0629       -> unordered_map<std::remove_const_t<Key>, T, Hash, Pred, Allocator>;
0630 
0631     template <class InputIterator, class Allocator,
0632       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0633       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0634     unordered_map(InputIterator, InputIterator, std::size_t, Allocator)
0635       -> unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
0636         boost::unordered::detail::iter_val_t<InputIterator>,
0637         boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0638         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0639         Allocator>;
0640 
0641     template <class InputIterator, class Allocator,
0642       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0643       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0644     unordered_map(InputIterator, InputIterator, Allocator)
0645       -> unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
0646         boost::unordered::detail::iter_val_t<InputIterator>,
0647         boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0648         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0649         Allocator>;
0650 
0651     template <class InputIterator, class Hash, class Allocator,
0652       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0653       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0654       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0655     unordered_map(InputIterator, InputIterator, std::size_t, Hash, Allocator)
0656       -> unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
0657         boost::unordered::detail::iter_val_t<InputIterator>, Hash,
0658         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0659         Allocator>;
0660 
0661     template <class Key, class T, class Allocator,
0662       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0663     unordered_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
0664       Allocator) -> unordered_map<std::remove_const_t<Key>, T,
0665       boost::hash<std::remove_const_t<Key> >,
0666       std::equal_to<std::remove_const_t<Key> >, Allocator>;
0667 
0668     template <class Key, class T, class Allocator,
0669       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0670     unordered_map(std::initializer_list<std::pair<Key, T> >, Allocator)
0671       -> unordered_map<std::remove_const_t<Key>, T,
0672         boost::hash<std::remove_const_t<Key> >,
0673         std::equal_to<std::remove_const_t<Key> >, Allocator>;
0674 
0675     template <class Key, class T, class Hash, class Allocator,
0676       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0677       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0678     unordered_map(std::initializer_list<std::pair<Key, T> >, std::size_t, Hash,
0679       Allocator) -> unordered_map<std::remove_const_t<Key>, T, Hash,
0680       std::equal_to<std::remove_const_t<Key> >, Allocator>;
0681 
0682 #endif
0683 
0684     template <class K, class T, class H, class P, class A>
0685     class unordered_multimap
0686     {
0687       template <typename, typename, typename, typename, typename>
0688       friend class unordered_map;
0689 
0690     public:
0691       typedef K key_type;
0692       typedef T mapped_type;
0693       typedef std::pair<const K, T> value_type;
0694       typedef typename boost::unordered::detail::type_identity<H>::type hasher;
0695       typedef
0696         typename boost::unordered::detail::type_identity<P>::type key_equal;
0697       typedef typename boost::unordered::detail::type_identity<A>::type
0698         allocator_type;
0699 
0700     private:
0701       typedef boost::unordered::detail::map<A, K, T, H, P> types;
0702       typedef typename types::value_allocator_traits value_allocator_traits;
0703       typedef typename types::table table;
0704 
0705     public:
0706       typedef typename value_allocator_traits::pointer pointer;
0707       typedef typename value_allocator_traits::const_pointer const_pointer;
0708 
0709       typedef value_type& reference;
0710       typedef value_type const& const_reference;
0711 
0712       typedef std::size_t size_type;
0713       typedef std::ptrdiff_t difference_type;
0714 
0715       typedef typename table::iterator iterator;
0716       typedef typename table::c_iterator const_iterator;
0717       typedef typename table::l_iterator local_iterator;
0718       typedef typename table::cl_iterator const_local_iterator;
0719       typedef typename types::node_type node_type;
0720 
0721     private:
0722       table table_;
0723 
0724     public:
0725       // constructors
0726 
0727       unordered_multimap();
0728 
0729       explicit unordered_multimap(size_type, const hasher& = hasher(),
0730         const key_equal& = key_equal(),
0731         const allocator_type& = allocator_type());
0732 
0733       template <class InputIt>
0734       unordered_multimap(InputIt, InputIt,
0735         size_type = boost::unordered::detail::default_bucket_count,
0736         const hasher& = hasher(), const key_equal& = key_equal(),
0737         const allocator_type& = allocator_type());
0738 
0739       unordered_multimap(unordered_multimap const&);
0740 
0741       unordered_multimap(unordered_multimap&& other)
0742         noexcept(table::nothrow_move_constructible)
0743           : table_(other.table_, boost::unordered::detail::move_tag())
0744       {
0745         // The move is done in table_
0746       }
0747 
0748       explicit unordered_multimap(allocator_type const&);
0749 
0750       unordered_multimap(unordered_multimap const&, allocator_type const&);
0751 
0752       unordered_multimap(unordered_multimap&&, allocator_type const&);
0753 
0754       unordered_multimap(std::initializer_list<value_type>,
0755         size_type = boost::unordered::detail::default_bucket_count,
0756         const hasher& = hasher(), const key_equal& l = key_equal(),
0757         const allocator_type& = allocator_type());
0758 
0759       explicit unordered_multimap(size_type, const allocator_type&);
0760 
0761       explicit unordered_multimap(
0762         size_type, const hasher&, const allocator_type&);
0763 
0764       template <class InputIterator>
0765       unordered_multimap(InputIterator, InputIterator, const allocator_type&);
0766 
0767       template <class InputIt>
0768       unordered_multimap(InputIt, InputIt, size_type, const allocator_type&);
0769 
0770       template <class InputIt>
0771       unordered_multimap(
0772         InputIt, InputIt, size_type, const hasher&, const allocator_type&);
0773 
0774       unordered_multimap(
0775         std::initializer_list<value_type>, const allocator_type&);
0776 
0777       unordered_multimap(
0778         std::initializer_list<value_type>, size_type, const allocator_type&);
0779 
0780       unordered_multimap(std::initializer_list<value_type>, size_type,
0781         const hasher&, const allocator_type&);
0782 
0783       // Destructor
0784 
0785       ~unordered_multimap() noexcept;
0786 
0787       // Assign
0788 
0789       unordered_multimap& operator=(unordered_multimap const& x)
0790       {
0791         table_.assign(x.table_, std::false_type());
0792         return *this;
0793       }
0794 
0795       unordered_multimap& operator=(unordered_multimap&& x)
0796         noexcept(value_allocator_traits::is_always_equal::value&&
0797             std::is_nothrow_move_assignable<H>::value&&
0798               std::is_nothrow_move_assignable<P>::value)
0799       {
0800         table_.move_assign(x.table_, std::false_type());
0801         return *this;
0802       }
0803 
0804       unordered_multimap& operator=(std::initializer_list<value_type>);
0805 
0806       allocator_type get_allocator() const noexcept
0807       {
0808         return table_.node_alloc();
0809       }
0810 
0811       // iterators
0812 
0813       iterator begin() noexcept { return iterator(table_.begin()); }
0814 
0815       const_iterator begin() const noexcept
0816       {
0817         return const_iterator(table_.begin());
0818       }
0819 
0820       iterator end() noexcept { return iterator(); }
0821 
0822       const_iterator end() const noexcept { return const_iterator(); }
0823 
0824       const_iterator cbegin() const noexcept
0825       {
0826         return const_iterator(table_.begin());
0827       }
0828 
0829       const_iterator cend() const noexcept { return const_iterator(); }
0830 
0831       // size and capacity
0832 
0833       BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0834       {
0835         return table_.size_ == 0;
0836       }
0837 
0838       size_type size() const noexcept { return table_.size_; }
0839 
0840       size_type max_size() const noexcept;
0841 
0842       // emplace
0843 
0844       template <class... Args> iterator emplace(Args&&... args)
0845       {
0846         return iterator(table_.emplace_equiv(
0847           boost::unordered::detail::func::construct_node_from_args(
0848             table_.node_alloc(), std::forward<Args>(args)...)));
0849       }
0850 
0851       template <class... Args>
0852       iterator emplace_hint(const_iterator hint, Args&&... args)
0853       {
0854         return iterator(table_.emplace_hint_equiv(
0855           hint, boost::unordered::detail::func::construct_node_from_args(
0856                   table_.node_alloc(), std::forward<Args>(args)...)));
0857       }
0858 
0859       iterator insert(value_type const& x) { return this->emplace(x); }
0860 
0861       iterator insert(value_type&& x) { return this->emplace(std::move(x)); }
0862 
0863       template <class P2>
0864       typename boost::enable_if<std::is_constructible<value_type, P2&&>,
0865         iterator>::type
0866       insert(P2&& obj)
0867       {
0868         return this->emplace(std::forward<P2>(obj));
0869       }
0870 
0871       iterator insert(const_iterator hint, value_type const& x)
0872       {
0873         return this->emplace_hint(hint, x);
0874       }
0875 
0876       iterator insert(const_iterator hint, value_type&& x)
0877       {
0878         return this->emplace_hint(hint, std::move(x));
0879       }
0880 
0881       template <class P2>
0882       typename boost::enable_if<std::is_constructible<value_type, P2&&>,
0883         iterator>::type
0884       insert(const_iterator hint, P2&& obj)
0885       {
0886         return this->emplace_hint(hint, std::forward<P2>(obj));
0887       }
0888 
0889       template <class InputIt> void insert(InputIt, InputIt);
0890 
0891       void insert(std::initializer_list<value_type>);
0892 
0893       // extract
0894 
0895       node_type extract(const_iterator position)
0896       {
0897         return node_type(
0898           table_.extract_by_iterator_equiv(position), table_.node_alloc());
0899       }
0900 
0901       node_type extract(const key_type& k)
0902       {
0903         return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0904       }
0905 
0906       template <class Key>
0907       typename boost::enable_if_c<
0908         detail::transparent_non_iterable<Key, unordered_multimap>::value,
0909         node_type>::type
0910       extract(const Key& k)
0911       {
0912         return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0913       }
0914 
0915       iterator insert(node_type&& np)
0916       {
0917         return table_.move_insert_node_type_equiv(np);
0918       }
0919 
0920       iterator insert(const_iterator hint, node_type&& np)
0921       {
0922         return table_.move_insert_node_type_with_hint_equiv(hint, np);
0923       }
0924 
0925       iterator erase(iterator);
0926       iterator erase(const_iterator);
0927       size_type erase(const key_type&);
0928       iterator erase(const_iterator, const_iterator);
0929 
0930       template <class Key>
0931       typename boost::enable_if_c<
0932         detail::transparent_non_iterable<Key, unordered_multimap>::value,
0933         size_type>::type
0934       erase(Key&& k)
0935       {
0936         return table_.erase_key_equiv_impl(std::forward<Key>(k));
0937       }
0938 
0939       BOOST_UNORDERED_DEPRECATED("Use erase instead")
0940       void quick_erase(const_iterator it) { erase(it); }
0941       BOOST_UNORDERED_DEPRECATED("Use erase instead")
0942       void erase_return_void(const_iterator it) { erase(it); }
0943 
0944       void swap(unordered_multimap&)
0945         noexcept(value_allocator_traits::is_always_equal::value&&
0946             boost::unordered::detail::is_nothrow_swappable<H>::value&&
0947               boost::unordered::detail::is_nothrow_swappable<P>::value);
0948       void clear() noexcept { table_.clear_impl(); }
0949 
0950       template <typename H2, typename P2>
0951       void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
0952 
0953       template <typename H2, typename P2>
0954       void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
0955 
0956       template <typename H2, typename P2>
0957       void merge(boost::unordered_map<K, T, H2, P2, A>& source);
0958 
0959       template <typename H2, typename P2>
0960       void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
0961 
0962       // observers
0963 
0964       hasher hash_function() const;
0965       key_equal key_eq() const;
0966 
0967       // lookup
0968 
0969       iterator find(const key_type&);
0970       const_iterator find(const key_type&) const;
0971 
0972       template <class Key>
0973       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0974         iterator>::type
0975       find(const Key& key)
0976       {
0977         return table_.find(key);
0978       }
0979 
0980       template <class Key>
0981       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0982         const_iterator>::type
0983       find(const Key& key) const
0984       {
0985         return const_iterator(table_.find(key));
0986       }
0987 
0988       template <class CompatibleKey, class CompatibleHash,
0989         class CompatiblePredicate>
0990       iterator find(CompatibleKey const&, CompatibleHash const&,
0991         CompatiblePredicate const&);
0992 
0993       template <class CompatibleKey, class CompatibleHash,
0994         class CompatiblePredicate>
0995       const_iterator find(CompatibleKey const&, CompatibleHash const&,
0996         CompatiblePredicate const&) const;
0997 
0998       bool contains(key_type const& k) const
0999       {
1000         return table_.find(k) != this->end();
1001       }
1002 
1003       template <class Key>
1004       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1005         bool>::type
1006       contains(const Key& k) const
1007       {
1008         return table_.find(k) != this->end();
1009       }
1010 
1011       size_type count(const key_type&) const;
1012 
1013       template <class Key>
1014       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1015         size_type>::type
1016       count(const Key& k) const
1017       {
1018         return table_.group_count(k);
1019       }
1020 
1021       std::pair<iterator, iterator> equal_range(const key_type&);
1022       std::pair<const_iterator, const_iterator> equal_range(
1023         const key_type&) const;
1024 
1025       template <class Key>
1026       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1027         std::pair<iterator, iterator> >::type
1028       equal_range(const Key& key)
1029       {
1030         iterator p = table_.find(key);
1031         return std::make_pair(p, table_.next_group(key, p));
1032       }
1033 
1034       template <class Key>
1035       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1036         std::pair<const_iterator, const_iterator> >::type
1037       equal_range(const Key& key) const
1038       {
1039         iterator p = table_.find(key);
1040         return std::make_pair(
1041           const_iterator(p), const_iterator(table_.next_group(key, p)));
1042       }
1043 
1044       // bucket interface
1045 
1046       size_type bucket_count() const noexcept { return table_.bucket_count(); }
1047 
1048       size_type max_bucket_count() const noexcept
1049       {
1050         return table_.max_bucket_count();
1051       }
1052 
1053       size_type bucket_size(size_type) const;
1054 
1055       size_type bucket(const key_type& k) const
1056       {
1057         return table_.hash_to_bucket(table_.hash(k));
1058       }
1059 
1060       template <class Key>
1061       typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1062         size_type>::type
1063       bucket(Key&& k) const
1064       {
1065         return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
1066       }
1067 
1068       local_iterator begin(size_type n)
1069       {
1070         return local_iterator(table_.begin(n));
1071       }
1072 
1073       const_local_iterator begin(size_type n) const
1074       {
1075         return const_local_iterator(table_.begin(n));
1076       }
1077 
1078       local_iterator end(size_type) { return local_iterator(); }
1079 
1080       const_local_iterator end(size_type) const
1081       {
1082         return const_local_iterator();
1083       }
1084 
1085       const_local_iterator cbegin(size_type n) const
1086       {
1087         return const_local_iterator(table_.begin(n));
1088       }
1089 
1090       const_local_iterator cend(size_type) const
1091       {
1092         return const_local_iterator();
1093       }
1094 
1095       // hash policy
1096 
1097       float load_factor() const noexcept;
1098       float max_load_factor() const noexcept { return table_.mlf_; }
1099       void max_load_factor(float) noexcept;
1100       void rehash(size_type);
1101       void reserve(size_type);
1102 
1103 #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
1104       friend bool operator==
1105         <K, T, H, P, A>(unordered_multimap const&, unordered_multimap const&);
1106       friend bool operator!=
1107         <K, T, H, P, A>(unordered_multimap const&, unordered_multimap const&);
1108 #endif
1109     }; // class template unordered_multimap
1110 
1111     template <class Archive, class K, class T, class H, class P, class A>
1112     void serialize(
1113       Archive& ar, unordered_multimap<K, T, H, P, A>& m, unsigned int version)
1114     {
1115       detail::serialize_fca_container(ar, m, version);
1116     }
1117 
1118 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
1119 
1120     template <class InputIterator,
1121       class Hash =
1122         boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
1123       class Pred =
1124         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
1125       class Allocator = std::allocator<
1126         boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
1127       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
1128       class = std::enable_if_t<detail::is_hash_v<Hash> >,
1129       class = std::enable_if_t<detail::is_pred_v<Pred> >,
1130       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1131     unordered_multimap(InputIterator, InputIterator,
1132       std::size_t = boost::unordered::detail::default_bucket_count,
1133       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
1134       -> unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
1135         boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
1136         Allocator>;
1137 
1138     template <class Key, class T,
1139       class Hash = boost::hash<std::remove_const_t<Key> >,
1140       class Pred = std::equal_to<std::remove_const_t<Key> >,
1141       class Allocator = std::allocator<std::pair<const Key, T> >,
1142       class = std::enable_if_t<detail::is_hash_v<Hash> >,
1143       class = std::enable_if_t<detail::is_pred_v<Pred> >,
1144       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1145     unordered_multimap(std::initializer_list<std::pair<Key, T> >,
1146       std::size_t = boost::unordered::detail::default_bucket_count,
1147       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
1148       -> unordered_multimap<std::remove_const_t<Key>, T, Hash, Pred, Allocator>;
1149 
1150     template <class InputIterator, class Allocator,
1151       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
1152       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1153     unordered_multimap(InputIterator, InputIterator, std::size_t, Allocator)
1154       -> unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
1155         boost::unordered::detail::iter_val_t<InputIterator>,
1156         boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
1157         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
1158         Allocator>;
1159 
1160     template <class InputIterator, class Allocator,
1161       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
1162       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1163     unordered_multimap(InputIterator, InputIterator, Allocator)
1164       -> unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
1165         boost::unordered::detail::iter_val_t<InputIterator>,
1166         boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
1167         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
1168         Allocator>;
1169 
1170     template <class InputIterator, class Hash, class Allocator,
1171       class = std::enable_if_t<detail::is_hash_v<Hash> >,
1172       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
1173       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1174     unordered_multimap(
1175       InputIterator, InputIterator, std::size_t, Hash, Allocator)
1176       -> unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
1177         boost::unordered::detail::iter_val_t<InputIterator>, Hash,
1178         std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
1179         Allocator>;
1180 
1181     template <class Key, class T, class Allocator,
1182       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1183     unordered_multimap(std::initializer_list<std::pair<Key, T> >, std::size_t,
1184       Allocator) -> unordered_multimap<std::remove_const_t<Key>, T,
1185       boost::hash<std::remove_const_t<Key> >,
1186       std::equal_to<std::remove_const_t<Key> >, Allocator>;
1187 
1188     template <class Key, class T, class Allocator,
1189       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1190     unordered_multimap(std::initializer_list<std::pair<Key, T> >, Allocator)
1191       -> unordered_multimap<std::remove_const_t<Key>, T,
1192         boost::hash<std::remove_const_t<Key> >,
1193         std::equal_to<std::remove_const_t<Key> >, Allocator>;
1194 
1195     template <class Key, class T, class Hash, class Allocator,
1196       class = std::enable_if_t<detail::is_hash_v<Hash> >,
1197       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
1198     unordered_multimap(std::initializer_list<std::pair<Key, T> >, std::size_t,
1199       Hash, Allocator) -> unordered_multimap<std::remove_const_t<Key>, T, Hash,
1200       std::equal_to<std::remove_const_t<Key> >, Allocator>;
1201 
1202 #endif
1203 
1204     ////////////////////////////////////////////////////////////////////////////
1205 
1206     template <class K, class T, class H, class P, class A>
1207     unordered_map<K, T, H, P, A>::unordered_map()
1208     {
1209     }
1210 
1211     template <class K, class T, class H, class P, class A>
1212     unordered_map<K, T, H, P, A>::unordered_map(size_type n, const hasher& hf,
1213       const key_equal& eql, const allocator_type& a)
1214         : table_(n, hf, eql, a)
1215     {
1216     }
1217 
1218     template <class K, class T, class H, class P, class A>
1219     template <class InputIt>
1220     unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l,
1221       size_type n, const hasher& hf, const key_equal& eql,
1222       const allocator_type& a)
1223         : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1224     {
1225       this->insert(f, l);
1226     }
1227 
1228     template <class K, class T, class H, class P, class A>
1229     unordered_map<K, T, H, P, A>::unordered_map(unordered_map const& other)
1230         : table_(other.table_,
1231             unordered_map::value_allocator_traits::
1232               select_on_container_copy_construction(other.get_allocator()))
1233     {
1234       if (other.size()) {
1235         table_.copy_buckets(other.table_, std::true_type());
1236       }
1237     }
1238 
1239     template <class K, class T, class H, class P, class A>
1240     unordered_map<K, T, H, P, A>::unordered_map(allocator_type const& a)
1241         : table_(boost::unordered::detail::default_bucket_count, hasher(),
1242             key_equal(), a)
1243     {
1244     }
1245 
1246     template <class K, class T, class H, class P, class A>
1247     unordered_map<K, T, H, P, A>::unordered_map(
1248       unordered_map const& other, allocator_type const& a)
1249         : table_(other.table_, a)
1250     {
1251       if (other.table_.size_) {
1252         table_.copy_buckets(other.table_, std::true_type());
1253       }
1254     }
1255 
1256     template <class K, class T, class H, class P, class A>
1257     unordered_map<K, T, H, P, A>::unordered_map(
1258       unordered_map&& other, allocator_type const& a)
1259         : table_(other.table_, a, boost::unordered::detail::move_tag())
1260     {
1261       table_.move_construct_buckets(other.table_);
1262     }
1263 
1264     template <class K, class T, class H, class P, class A>
1265     unordered_map<K, T, H, P, A>::unordered_map(
1266       std::initializer_list<value_type> list, size_type n, const hasher& hf,
1267       const key_equal& eql, const allocator_type& a)
1268         : table_(
1269             boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1270             hf, eql, a)
1271     {
1272       this->insert(list.begin(), list.end());
1273     }
1274 
1275     template <class K, class T, class H, class P, class A>
1276     unordered_map<K, T, H, P, A>::unordered_map(
1277       size_type n, const allocator_type& a)
1278         : table_(n, hasher(), key_equal(), a)
1279     {
1280     }
1281 
1282     template <class K, class T, class H, class P, class A>
1283     unordered_map<K, T, H, P, A>::unordered_map(
1284       size_type n, const hasher& hf, const allocator_type& a)
1285         : table_(n, hf, key_equal(), a)
1286     {
1287     }
1288 
1289     template <class K, class T, class H, class P, class A>
1290     template <class InputIterator>
1291     unordered_map<K, T, H, P, A>::unordered_map(
1292       InputIterator f, InputIterator l, const allocator_type& a)
1293         : table_(boost::unordered::detail::initial_size(
1294                    f, l, detail::default_bucket_count),
1295             hasher(), key_equal(), a)
1296     {
1297       this->insert(f, l);
1298     }
1299 
1300     template <class K, class T, class H, class P, class A>
1301     template <class InputIt>
1302     unordered_map<K, T, H, P, A>::unordered_map(
1303       InputIt f, InputIt l, size_type n, const allocator_type& a)
1304         : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1305             key_equal(), a)
1306     {
1307       this->insert(f, l);
1308     }
1309 
1310     template <class K, class T, class H, class P, class A>
1311     template <class InputIt>
1312     unordered_map<K, T, H, P, A>::unordered_map(InputIt f, InputIt l,
1313       size_type n, const hasher& hf, const allocator_type& a)
1314         : table_(
1315             boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1316     {
1317       this->insert(f, l);
1318     }
1319 
1320     template <class K, class T, class H, class P, class A>
1321     unordered_map<K, T, H, P, A>::unordered_map(
1322       std::initializer_list<value_type> list, const allocator_type& a)
1323         : table_(boost::unordered::detail::initial_size(
1324                    list.begin(), list.end(), detail::default_bucket_count),
1325             hasher(), key_equal(), a)
1326     {
1327       this->insert(list.begin(), list.end());
1328     }
1329 
1330     template <class K, class T, class H, class P, class A>
1331     unordered_map<K, T, H, P, A>::unordered_map(
1332       std::initializer_list<value_type> list, size_type n,
1333       const allocator_type& a)
1334         : table_(
1335             boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1336             hasher(), key_equal(), a)
1337     {
1338       this->insert(list.begin(), list.end());
1339     }
1340 
1341     template <class K, class T, class H, class P, class A>
1342     unordered_map<K, T, H, P, A>::unordered_map(
1343       std::initializer_list<value_type> list, size_type n, const hasher& hf,
1344       const allocator_type& a)
1345         : table_(
1346             boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1347             hf, key_equal(), a)
1348     {
1349       this->insert(list.begin(), list.end());
1350     }
1351 
1352     template <class K, class T, class H, class P, class A>
1353     unordered_map<K, T, H, P, A>::~unordered_map() noexcept
1354     {
1355     }
1356 
1357     template <class K, class T, class H, class P, class A>
1358     unordered_map<K, T, H, P, A>& unordered_map<K, T, H, P, A>::operator=(
1359       std::initializer_list<value_type> list)
1360     {
1361       this->clear();
1362       this->insert(list.begin(), list.end());
1363       return *this;
1364     }
1365 
1366     // size and capacity
1367 
1368     template <class K, class T, class H, class P, class A>
1369     std::size_t unordered_map<K, T, H, P, A>::max_size() const noexcept
1370     {
1371       using namespace std;
1372 
1373       // size <= mlf_ * count
1374       return boost::unordered::detail::double_to_size(
1375                ceil(static_cast<double>(table_.mlf_) *
1376                     static_cast<double>(table_.max_bucket_count()))) -
1377              1;
1378     }
1379 
1380     // modifiers
1381 
1382     template <class K, class T, class H, class P, class A>
1383     template <class InputIt>
1384     void unordered_map<K, T, H, P, A>::insert(InputIt first, InputIt last)
1385     {
1386       if (first != last) {
1387         table_.insert_range_unique(
1388           table::extractor::extract(*first), first, last);
1389       }
1390     }
1391 
1392     template <class K, class T, class H, class P, class A>
1393     void unordered_map<K, T, H, P, A>::insert(
1394       std::initializer_list<value_type> list)
1395     {
1396       this->insert(list.begin(), list.end());
1397     }
1398 
1399     template <class K, class T, class H, class P, class A>
1400     typename unordered_map<K, T, H, P, A>::iterator
1401     unordered_map<K, T, H, P, A>::erase(iterator position)
1402     {
1403       return table_.erase_node(position);
1404     }
1405 
1406     template <class K, class T, class H, class P, class A>
1407     typename unordered_map<K, T, H, P, A>::iterator
1408     unordered_map<K, T, H, P, A>::erase(const_iterator position)
1409     {
1410       return table_.erase_node(position);
1411     }
1412 
1413     template <class K, class T, class H, class P, class A>
1414     typename unordered_map<K, T, H, P, A>::size_type
1415     unordered_map<K, T, H, P, A>::erase(const key_type& k)
1416     {
1417       return table_.erase_key_unique_impl(k);
1418     }
1419 
1420     template <class K, class T, class H, class P, class A>
1421     typename unordered_map<K, T, H, P, A>::iterator
1422     unordered_map<K, T, H, P, A>::erase(
1423       const_iterator first, const_iterator last)
1424     {
1425       return table_.erase_nodes_range(first, last);
1426     }
1427 
1428     template <class K, class T, class H, class P, class A>
1429     void unordered_map<K, T, H, P, A>::swap(unordered_map& other)
1430       noexcept(value_allocator_traits::is_always_equal::value&&
1431           boost::unordered::detail::is_nothrow_swappable<H>::value&&
1432             boost::unordered::detail::is_nothrow_swappable<P>::value)
1433     {
1434       table_.swap(other.table_);
1435     }
1436 
1437     template <class K, class T, class H, class P, class A>
1438     template <typename H2, typename P2>
1439     void unordered_map<K, T, H, P, A>::merge(
1440       boost::unordered_map<K, T, H2, P2, A>& source)
1441     {
1442       table_.merge_unique(source.table_);
1443     }
1444 
1445     template <class K, class T, class H, class P, class A>
1446     template <typename H2, typename P2>
1447     void unordered_map<K, T, H, P, A>::merge(
1448       boost::unordered_map<K, T, H2, P2, A>&& source)
1449     {
1450       table_.merge_unique(source.table_);
1451     }
1452 
1453     template <class K, class T, class H, class P, class A>
1454     template <typename H2, typename P2>
1455     void unordered_map<K, T, H, P, A>::merge(
1456       boost::unordered_multimap<K, T, H2, P2, A>& source)
1457     {
1458       table_.merge_unique(source.table_);
1459     }
1460 
1461     template <class K, class T, class H, class P, class A>
1462     template <typename H2, typename P2>
1463     void unordered_map<K, T, H, P, A>::merge(
1464       boost::unordered_multimap<K, T, H2, P2, A>&& source)
1465     {
1466       table_.merge_unique(source.table_);
1467     }
1468 
1469     // observers
1470 
1471     template <class K, class T, class H, class P, class A>
1472     typename unordered_map<K, T, H, P, A>::hasher
1473     unordered_map<K, T, H, P, A>::hash_function() const
1474     {
1475       return table_.hash_function();
1476     }
1477 
1478     template <class K, class T, class H, class P, class A>
1479     typename unordered_map<K, T, H, P, A>::key_equal
1480     unordered_map<K, T, H, P, A>::key_eq() const
1481     {
1482       return table_.key_eq();
1483     }
1484 
1485     // lookup
1486 
1487     template <class K, class T, class H, class P, class A>
1488     typename unordered_map<K, T, H, P, A>::iterator
1489     unordered_map<K, T, H, P, A>::find(const key_type& k)
1490     {
1491       return iterator(table_.find(k));
1492     }
1493 
1494     template <class K, class T, class H, class P, class A>
1495     typename unordered_map<K, T, H, P, A>::const_iterator
1496     unordered_map<K, T, H, P, A>::find(const key_type& k) const
1497     {
1498       return const_iterator(table_.find(k));
1499     }
1500 
1501     template <class K, class T, class H, class P, class A>
1502     template <class CompatibleKey, class CompatibleHash,
1503       class CompatiblePredicate>
1504     typename unordered_map<K, T, H, P, A>::iterator
1505     unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
1506       CompatibleHash const& hash, CompatiblePredicate const& eq)
1507     {
1508       return table_.transparent_find(k, hash, eq);
1509     }
1510 
1511     template <class K, class T, class H, class P, class A>
1512     template <class CompatibleKey, class CompatibleHash,
1513       class CompatiblePredicate>
1514     typename unordered_map<K, T, H, P, A>::const_iterator
1515     unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
1516       CompatibleHash const& hash, CompatiblePredicate const& eq) const
1517     {
1518       return table_.transparent_find(k, hash, eq);
1519     }
1520 
1521     template <class K, class T, class H, class P, class A>
1522     typename unordered_map<K, T, H, P, A>::size_type
1523     unordered_map<K, T, H, P, A>::count(const key_type& k) const
1524     {
1525       return table_.find_node(k) ? 1 : 0;
1526     }
1527 
1528     template <class K, class T, class H, class P, class A>
1529     std::pair<typename unordered_map<K, T, H, P, A>::iterator,
1530       typename unordered_map<K, T, H, P, A>::iterator>
1531     unordered_map<K, T, H, P, A>::equal_range(const key_type& k)
1532     {
1533       iterator first = table_.find(k);
1534       iterator second = first;
1535       if (second != this->end()) {
1536         ++second;
1537       }
1538       return std::make_pair(first, second);
1539     }
1540 
1541     template <class K, class T, class H, class P, class A>
1542     std::pair<typename unordered_map<K, T, H, P, A>::const_iterator,
1543       typename unordered_map<K, T, H, P, A>::const_iterator>
1544     unordered_map<K, T, H, P, A>::equal_range(const key_type& k) const
1545     {
1546       iterator first = table_.find(k);
1547       iterator second = first;
1548       if (second != this->end()) {
1549         ++second;
1550       }
1551       return std::make_pair(const_iterator(first), const_iterator(second));
1552     }
1553 
1554     template <class K, class T, class H, class P, class A>
1555     typename unordered_map<K, T, H, P, A>::mapped_type&
1556     unordered_map<K, T, H, P, A>::operator[](const key_type& k)
1557     {
1558       return table_.try_emplace_unique(k).first->second;
1559     }
1560 
1561     template <class K, class T, class H, class P, class A>
1562     typename unordered_map<K, T, H, P, A>::mapped_type&
1563     unordered_map<K, T, H, P, A>::operator[](key_type&& k)
1564     {
1565       return table_.try_emplace_unique(std::move(k)).first->second;
1566     }
1567 
1568     template <class K, class T, class H, class P, class A>
1569     template <class Key>
1570     typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1571       typename unordered_map<K, T, H, P, A>::mapped_type&>::type
1572     unordered_map<K, T, H, P, A>::operator[](Key&& k)
1573     {
1574       return table_.try_emplace_unique(std::forward<Key>(k)).first->second;
1575     }
1576 
1577     template <class K, class T, class H, class P, class A>
1578     typename unordered_map<K, T, H, P, A>::mapped_type&
1579     unordered_map<K, T, H, P, A>::at(const key_type& k)
1580     {
1581       typedef typename table::node_pointer node_pointer;
1582 
1583       if (table_.size_) {
1584         node_pointer p = table_.find_node(k);
1585         if (p)
1586           return p->value().second;
1587       }
1588 
1589       boost::throw_exception(
1590         std::out_of_range("Unable to find key in unordered_map."));
1591     }
1592 
1593     template <class K, class T, class H, class P, class A>
1594     typename unordered_map<K, T, H, P, A>::mapped_type const&
1595     unordered_map<K, T, H, P, A>::at(const key_type& k) const
1596     {
1597       typedef typename table::node_pointer node_pointer;
1598 
1599       if (table_.size_) {
1600         node_pointer p = table_.find_node(k);
1601         if (p)
1602           return p->value().second;
1603       }
1604 
1605       boost::throw_exception(
1606         std::out_of_range("Unable to find key in unordered_map."));
1607     }
1608 
1609     template <class K, class T, class H, class P, class A>
1610     template <class Key>
1611     typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1612       typename unordered_map<K, T, H, P, A>::mapped_type&>::type
1613     unordered_map<K, T, H, P, A>::at(Key&& k)
1614     {
1615       typedef typename table::node_pointer node_pointer;
1616 
1617       if (table_.size_) {
1618         node_pointer p = table_.find_node(std::forward<Key>(k));
1619         if (p)
1620           return p->value().second;
1621       }
1622 
1623       boost::throw_exception(
1624         std::out_of_range("Unable to find key in unordered_map."));
1625     }
1626 
1627     template <class K, class T, class H, class P, class A>
1628     template <class Key>
1629     typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
1630       typename unordered_map<K, T, H, P, A>::mapped_type const&>::type
1631     unordered_map<K, T, H, P, A>::at(Key&& k) const
1632     {
1633       typedef typename table::node_pointer node_pointer;
1634 
1635       if (table_.size_) {
1636         node_pointer p = table_.find_node(std::forward<Key>(k));
1637         if (p)
1638           return p->value().second;
1639       }
1640 
1641       boost::throw_exception(
1642         std::out_of_range("Unable to find key in unordered_map."));
1643     }
1644 
1645     template <class K, class T, class H, class P, class A>
1646     typename unordered_map<K, T, H, P, A>::size_type
1647     unordered_map<K, T, H, P, A>::bucket_size(size_type n) const
1648     {
1649       return table_.bucket_size(n);
1650     }
1651 
1652     // hash policy
1653 
1654     template <class K, class T, class H, class P, class A>
1655     float unordered_map<K, T, H, P, A>::load_factor() const noexcept
1656     {
1657       if (table_.size_ == 0) {
1658         return 0.0f;
1659       }
1660 
1661       BOOST_ASSERT(table_.bucket_count() != 0);
1662       return static_cast<float>(table_.size_) /
1663              static_cast<float>(table_.bucket_count());
1664     }
1665 
1666     template <class K, class T, class H, class P, class A>
1667     void unordered_map<K, T, H, P, A>::max_load_factor(float m) noexcept
1668     {
1669       table_.max_load_factor(m);
1670     }
1671 
1672     template <class K, class T, class H, class P, class A>
1673     void unordered_map<K, T, H, P, A>::rehash(size_type n)
1674     {
1675       table_.rehash(n);
1676     }
1677 
1678     template <class K, class T, class H, class P, class A>
1679     void unordered_map<K, T, H, P, A>::reserve(size_type n)
1680     {
1681       table_.reserve(n);
1682     }
1683 
1684     template <class K, class T, class H, class P, class A>
1685     inline bool operator==(unordered_map<K, T, H, P, A> const& m1,
1686       unordered_map<K, T, H, P, A> const& m2)
1687     {
1688 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1689       struct dummy
1690       {
1691         unordered_map<K, T, H, P, A> x;
1692       };
1693 #endif
1694       return m1.table_.equals_unique(m2.table_);
1695     }
1696 
1697     template <class K, class T, class H, class P, class A>
1698     inline bool operator!=(unordered_map<K, T, H, P, A> const& m1,
1699       unordered_map<K, T, H, P, A> const& m2)
1700     {
1701 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1702       struct dummy
1703       {
1704         unordered_map<K, T, H, P, A> x;
1705       };
1706 #endif
1707       return !m1.table_.equals_unique(m2.table_);
1708     }
1709 
1710     template <class K, class T, class H, class P, class A>
1711     inline void swap(unordered_map<K, T, H, P, A>& m1,
1712       unordered_map<K, T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
1713     {
1714 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1715       struct dummy
1716       {
1717         unordered_map<K, T, H, P, A> x;
1718       };
1719 #endif
1720       m1.swap(m2);
1721     }
1722 
1723     template <class K, class T, class H, class P, class A, class Predicate>
1724     typename unordered_map<K, T, H, P, A>::size_type erase_if(
1725       unordered_map<K, T, H, P, A>& c, Predicate pred)
1726     {
1727       return detail::erase_if(c, pred);
1728     }
1729 
1730     ////////////////////////////////////////////////////////////////////////////
1731 
1732     template <class K, class T, class H, class P, class A>
1733     unordered_multimap<K, T, H, P, A>::unordered_multimap()
1734     {
1735     }
1736 
1737     template <class K, class T, class H, class P, class A>
1738     unordered_multimap<K, T, H, P, A>::unordered_multimap(size_type n,
1739       const hasher& hf, const key_equal& eql, const allocator_type& a)
1740         : table_(n, hf, eql, a)
1741     {
1742     }
1743 
1744     template <class K, class T, class H, class P, class A>
1745     template <class InputIt>
1746     unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
1747       size_type n, const hasher& hf, const key_equal& eql,
1748       const allocator_type& a)
1749         : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1750     {
1751       this->insert(f, l);
1752     }
1753 
1754     template <class K, class T, class H, class P, class A>
1755     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1756       unordered_multimap const& other)
1757         : table_(other.table_,
1758             unordered_multimap::value_allocator_traits::
1759               select_on_container_copy_construction(other.get_allocator()))
1760     {
1761       if (other.table_.size_) {
1762         table_.copy_buckets(other.table_, std::false_type());
1763       }
1764     }
1765 
1766     template <class K, class T, class H, class P, class A>
1767     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1768       allocator_type const& a)
1769         : table_(boost::unordered::detail::default_bucket_count, hasher(),
1770             key_equal(), a)
1771     {
1772     }
1773 
1774     template <class K, class T, class H, class P, class A>
1775     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1776       unordered_multimap const& other, allocator_type const& a)
1777         : table_(other.table_, a)
1778     {
1779       if (other.table_.size_) {
1780         table_.copy_buckets(other.table_, std::false_type());
1781       }
1782     }
1783 
1784     template <class K, class T, class H, class P, class A>
1785     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1786       unordered_multimap&& other, allocator_type const& a)
1787         : table_(other.table_, a, boost::unordered::detail::move_tag())
1788     {
1789       table_.move_construct_buckets(other.table_);
1790     }
1791 
1792     template <class K, class T, class H, class P, class A>
1793     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1794       std::initializer_list<value_type> list, size_type n, const hasher& hf,
1795       const key_equal& eql, const allocator_type& a)
1796         : table_(
1797             boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1798             hf, eql, a)
1799     {
1800       this->insert(list.begin(), list.end());
1801     }
1802 
1803     template <class K, class T, class H, class P, class A>
1804     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1805       size_type n, const allocator_type& a)
1806         : table_(n, hasher(), key_equal(), a)
1807     {
1808     }
1809 
1810     template <class K, class T, class H, class P, class A>
1811     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1812       size_type n, const hasher& hf, const allocator_type& a)
1813         : table_(n, hf, key_equal(), a)
1814     {
1815     }
1816 
1817     template <class K, class T, class H, class P, class A>
1818     template <class InputIterator>
1819     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1820       InputIterator f, InputIterator l, const allocator_type& a)
1821         : table_(boost::unordered::detail::initial_size(
1822                    f, l, detail::default_bucket_count),
1823             hasher(), key_equal(), a)
1824     {
1825       this->insert(f, l);
1826     }
1827 
1828     template <class K, class T, class H, class P, class A>
1829     template <class InputIt>
1830     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1831       InputIt f, InputIt l, size_type n, const allocator_type& a)
1832         : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1833             key_equal(), a)
1834     {
1835       this->insert(f, l);
1836     }
1837 
1838     template <class K, class T, class H, class P, class A>
1839     template <class InputIt>
1840     unordered_multimap<K, T, H, P, A>::unordered_multimap(InputIt f, InputIt l,
1841       size_type n, const hasher& hf, const allocator_type& a)
1842         : table_(
1843             boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1844     {
1845       this->insert(f, l);
1846     }
1847 
1848     template <class K, class T, class H, class P, class A>
1849     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1850       std::initializer_list<value_type> list, const allocator_type& a)
1851         : table_(boost::unordered::detail::initial_size(
1852                    list.begin(), list.end(), detail::default_bucket_count),
1853             hasher(), key_equal(), a)
1854     {
1855       this->insert(list.begin(), list.end());
1856     }
1857 
1858     template <class K, class T, class H, class P, class A>
1859     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1860       std::initializer_list<value_type> list, size_type n,
1861       const allocator_type& a)
1862         : table_(
1863             boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1864             hasher(), key_equal(), a)
1865     {
1866       this->insert(list.begin(), list.end());
1867     }
1868 
1869     template <class K, class T, class H, class P, class A>
1870     unordered_multimap<K, T, H, P, A>::unordered_multimap(
1871       std::initializer_list<value_type> list, size_type n, const hasher& hf,
1872       const allocator_type& a)
1873         : table_(
1874             boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1875             hf, key_equal(), a)
1876     {
1877       this->insert(list.begin(), list.end());
1878     }
1879 
1880     template <class K, class T, class H, class P, class A>
1881     unordered_multimap<K, T, H, P, A>::~unordered_multimap() noexcept
1882     {
1883     }
1884 
1885     template <class K, class T, class H, class P, class A>
1886     unordered_multimap<K, T, H, P, A>&
1887     unordered_multimap<K, T, H, P, A>::operator=(
1888       std::initializer_list<value_type> list)
1889     {
1890       this->clear();
1891       this->insert(list.begin(), list.end());
1892       return *this;
1893     }
1894 
1895     // size and capacity
1896 
1897     template <class K, class T, class H, class P, class A>
1898     std::size_t unordered_multimap<K, T, H, P, A>::max_size() const noexcept
1899     {
1900       using namespace std;
1901 
1902       // size <= mlf_ * count
1903       return boost::unordered::detail::double_to_size(
1904                ceil(static_cast<double>(table_.mlf_) *
1905                     static_cast<double>(table_.max_bucket_count()))) -
1906              1;
1907     }
1908 
1909     // modifiers
1910 
1911     template <class K, class T, class H, class P, class A>
1912     template <class InputIt>
1913     void unordered_multimap<K, T, H, P, A>::insert(InputIt first, InputIt last)
1914     {
1915       table_.insert_range_equiv(first, last);
1916     }
1917 
1918     template <class K, class T, class H, class P, class A>
1919     void unordered_multimap<K, T, H, P, A>::insert(
1920       std::initializer_list<value_type> list)
1921     {
1922       this->insert(list.begin(), list.end());
1923     }
1924 
1925     template <class K, class T, class H, class P, class A>
1926     typename unordered_multimap<K, T, H, P, A>::iterator
1927     unordered_multimap<K, T, H, P, A>::erase(iterator position)
1928     {
1929       BOOST_ASSERT(position != this->end());
1930       return table_.erase_node(position);
1931     }
1932 
1933     template <class K, class T, class H, class P, class A>
1934     typename unordered_multimap<K, T, H, P, A>::iterator
1935     unordered_multimap<K, T, H, P, A>::erase(const_iterator position)
1936     {
1937       BOOST_ASSERT(position != this->end());
1938       return table_.erase_node(position);
1939     }
1940 
1941     template <class K, class T, class H, class P, class A>
1942     typename unordered_multimap<K, T, H, P, A>::size_type
1943     unordered_multimap<K, T, H, P, A>::erase(const key_type& k)
1944     {
1945       return table_.erase_key_equiv(k);
1946     }
1947 
1948     template <class K, class T, class H, class P, class A>
1949     typename unordered_multimap<K, T, H, P, A>::iterator
1950     unordered_multimap<K, T, H, P, A>::erase(
1951       const_iterator first, const_iterator last)
1952     {
1953       return table_.erase_nodes_range(first, last);
1954     }
1955 
1956     template <class K, class T, class H, class P, class A>
1957     void unordered_multimap<K, T, H, P, A>::swap(unordered_multimap& other)
1958       noexcept(value_allocator_traits::is_always_equal::value&&
1959           boost::unordered::detail::is_nothrow_swappable<H>::value&&
1960             boost::unordered::detail::is_nothrow_swappable<P>::value)
1961     {
1962       table_.swap(other.table_);
1963     }
1964 
1965     // observers
1966 
1967     template <class K, class T, class H, class P, class A>
1968     typename unordered_multimap<K, T, H, P, A>::hasher
1969     unordered_multimap<K, T, H, P, A>::hash_function() const
1970     {
1971       return table_.hash_function();
1972     }
1973 
1974     template <class K, class T, class H, class P, class A>
1975     typename unordered_multimap<K, T, H, P, A>::key_equal
1976     unordered_multimap<K, T, H, P, A>::key_eq() const
1977     {
1978       return table_.key_eq();
1979     }
1980 
1981     template <class K, class T, class H, class P, class A>
1982     template <typename H2, typename P2>
1983     void unordered_multimap<K, T, H, P, A>::merge(
1984       boost::unordered_multimap<K, T, H2, P2, A>& source)
1985     {
1986       while (!source.empty()) {
1987         insert(source.extract(source.begin()));
1988       }
1989     }
1990 
1991     template <class K, class T, class H, class P, class A>
1992     template <typename H2, typename P2>
1993     void unordered_multimap<K, T, H, P, A>::merge(
1994       boost::unordered_multimap<K, T, H2, P2, A>&& source)
1995     {
1996       while (!source.empty()) {
1997         insert(source.extract(source.begin()));
1998       }
1999     }
2000 
2001     template <class K, class T, class H, class P, class A>
2002     template <typename H2, typename P2>
2003     void unordered_multimap<K, T, H, P, A>::merge(
2004       boost::unordered_map<K, T, H2, P2, A>& source)
2005     {
2006       while (!source.empty()) {
2007         insert(source.extract(source.begin()));
2008       }
2009     }
2010 
2011     template <class K, class T, class H, class P, class A>
2012     template <typename H2, typename P2>
2013     void unordered_multimap<K, T, H, P, A>::merge(
2014       boost::unordered_map<K, T, H2, P2, A>&& source)
2015     {
2016       while (!source.empty()) {
2017         insert(source.extract(source.begin()));
2018       }
2019     }
2020 
2021     // lookup
2022 
2023     template <class K, class T, class H, class P, class A>
2024     typename unordered_multimap<K, T, H, P, A>::iterator
2025     unordered_multimap<K, T, H, P, A>::find(const key_type& k)
2026     {
2027       return iterator(table_.find(k));
2028     }
2029 
2030     template <class K, class T, class H, class P, class A>
2031     typename unordered_multimap<K, T, H, P, A>::const_iterator
2032     unordered_multimap<K, T, H, P, A>::find(const key_type& k) const
2033     {
2034       return const_iterator(table_.find(k));
2035     }
2036 
2037     template <class K, class T, class H, class P, class A>
2038     template <class CompatibleKey, class CompatibleHash,
2039       class CompatiblePredicate>
2040     typename unordered_multimap<K, T, H, P, A>::iterator
2041     unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k,
2042       CompatibleHash const& hash, CompatiblePredicate const& eq)
2043     {
2044       return table_.transparent_find(k, hash, eq);
2045     }
2046 
2047     template <class K, class T, class H, class P, class A>
2048     template <class CompatibleKey, class CompatibleHash,
2049       class CompatiblePredicate>
2050     typename unordered_multimap<K, T, H, P, A>::const_iterator
2051     unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k,
2052       CompatibleHash const& hash, CompatiblePredicate const& eq) const
2053     {
2054       return const_iterator(
2055         table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
2056     }
2057 
2058     template <class K, class T, class H, class P, class A>
2059     typename unordered_multimap<K, T, H, P, A>::size_type
2060     unordered_multimap<K, T, H, P, A>::count(const key_type& k) const
2061     {
2062       return table_.group_count(k);
2063     }
2064 
2065     template <class K, class T, class H, class P, class A>
2066     std::pair<typename unordered_multimap<K, T, H, P, A>::iterator,
2067       typename unordered_multimap<K, T, H, P, A>::iterator>
2068     unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k)
2069     {
2070       iterator n = table_.find(k);
2071       return std::make_pair(n, (n == end() ? n : table_.next_group(k, n)));
2072     }
2073 
2074     template <class K, class T, class H, class P, class A>
2075     std::pair<typename unordered_multimap<K, T, H, P, A>::const_iterator,
2076       typename unordered_multimap<K, T, H, P, A>::const_iterator>
2077     unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) const
2078     {
2079       iterator n = table_.find(k);
2080       return std::make_pair(const_iterator(n),
2081         const_iterator(n == end() ? n : table_.next_group(k, n)));
2082     }
2083 
2084     template <class K, class T, class H, class P, class A>
2085     typename unordered_multimap<K, T, H, P, A>::size_type
2086     unordered_multimap<K, T, H, P, A>::bucket_size(size_type n) const
2087     {
2088       return table_.bucket_size(n);
2089     }
2090 
2091     // hash policy
2092 
2093     template <class K, class T, class H, class P, class A>
2094     float unordered_multimap<K, T, H, P, A>::load_factor() const noexcept
2095     {
2096       if (table_.size_ == 0) {
2097         return 0.0f;
2098       }
2099 
2100       BOOST_ASSERT(table_.bucket_count() != 0);
2101       return static_cast<float>(table_.size_) /
2102              static_cast<float>(table_.bucket_count());
2103     }
2104 
2105     template <class K, class T, class H, class P, class A>
2106     void unordered_multimap<K, T, H, P, A>::max_load_factor(float m) noexcept
2107     {
2108       table_.max_load_factor(m);
2109     }
2110 
2111     template <class K, class T, class H, class P, class A>
2112     void unordered_multimap<K, T, H, P, A>::rehash(size_type n)
2113     {
2114       table_.rehash(n);
2115     }
2116 
2117     template <class K, class T, class H, class P, class A>
2118     void unordered_multimap<K, T, H, P, A>::reserve(size_type n)
2119     {
2120       table_.reserve(n);
2121     }
2122 
2123     template <class K, class T, class H, class P, class A>
2124     inline bool operator==(unordered_multimap<K, T, H, P, A> const& m1,
2125       unordered_multimap<K, T, H, P, A> const& m2)
2126     {
2127 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
2128       struct dummy
2129       {
2130         unordered_multimap<K, T, H, P, A> x;
2131       };
2132 #endif
2133       return m1.table_.equals_equiv(m2.table_);
2134     }
2135 
2136     template <class K, class T, class H, class P, class A>
2137     inline bool operator!=(unordered_multimap<K, T, H, P, A> const& m1,
2138       unordered_multimap<K, T, H, P, A> const& m2)
2139     {
2140 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
2141       struct dummy
2142       {
2143         unordered_multimap<K, T, H, P, A> x;
2144       };
2145 #endif
2146       return !m1.table_.equals_equiv(m2.table_);
2147     }
2148 
2149     template <class K, class T, class H, class P, class A>
2150     inline void swap(unordered_multimap<K, T, H, P, A>& m1,
2151       unordered_multimap<K, T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
2152     {
2153 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
2154       struct dummy
2155       {
2156         unordered_multimap<K, T, H, P, A> x;
2157       };
2158 #endif
2159       m1.swap(m2);
2160     }
2161 
2162     template <class K, class T, class H, class P, class A, class Predicate>
2163     typename unordered_multimap<K, T, H, P, A>::size_type erase_if(
2164       unordered_multimap<K, T, H, P, A>& c, Predicate pred)
2165     {
2166       return detail::erase_if(c, pred);
2167     }
2168 
2169     template <typename N, class K, class T, class A> class node_handle_map
2170     {
2171       template <typename Types> friend struct ::boost::unordered::detail::table;
2172       template <class K2, class T2, class H2, class P2, class A2>
2173       friend class boost::unordered::unordered_map;
2174       template <class K2, class T2, class H2, class P2, class A2>
2175       friend class boost::unordered::unordered_multimap;
2176 
2177       typedef typename boost::allocator_rebind<A, std::pair<K const, T> >::type
2178         value_allocator;
2179 
2180       typedef N node;
2181       typedef typename boost::allocator_rebind<A, node>::type node_allocator;
2182 
2183       typedef
2184         typename boost::allocator_pointer<node_allocator>::type node_pointer;
2185 
2186     public:
2187       typedef K key_type;
2188       typedef T mapped_type;
2189       typedef A allocator_type;
2190 
2191     private:
2192       node_pointer ptr_;
2193       boost::unordered::detail::optional<value_allocator> alloc_;
2194 
2195       node_handle_map(node_pointer ptr, allocator_type const& a)
2196           : ptr_(ptr), alloc_(a)
2197       {
2198       }
2199 
2200     public:
2201       constexpr node_handle_map() noexcept : ptr_(), alloc_() {}
2202       node_handle_map(node_handle_map const&) = delete;
2203       node_handle_map& operator=(node_handle_map const&) = delete;
2204 
2205       ~node_handle_map()
2206       {
2207         if (ptr_) {
2208           node_allocator node_alloc(*alloc_);
2209           boost::unordered::detail::node_tmp<node_allocator> tmp(
2210             ptr_, node_alloc);
2211         }
2212       }
2213 
2214       node_handle_map(node_handle_map&& n) noexcept
2215           : ptr_(n.ptr_),
2216             alloc_(std::move(n.alloc_))
2217       {
2218         n.ptr_ = node_pointer();
2219       }
2220 
2221       node_handle_map& operator=(node_handle_map&& n)
2222       {
2223         BOOST_ASSERT(!alloc_.has_value() ||
2224                      boost::allocator_propagate_on_container_move_assignment<
2225                        value_allocator>::type::value ||
2226                      (n.alloc_.has_value() && alloc_ == n.alloc_));
2227 
2228         if (ptr_) {
2229           node_allocator node_alloc(*alloc_);
2230           boost::unordered::detail::node_tmp<node_allocator> tmp(
2231             ptr_, node_alloc);
2232           ptr_ = node_pointer();
2233         }
2234 
2235         if (!alloc_.has_value() ||
2236             boost::allocator_propagate_on_container_move_assignment<
2237               value_allocator>::type::value) {
2238           alloc_ = std::move(n.alloc_);
2239         }
2240         ptr_ = n.ptr_;
2241         n.ptr_ = node_pointer();
2242 
2243         return *this;
2244       }
2245 
2246       key_type& key() const
2247       {
2248         return const_cast<key_type&>(ptr_->value().first);
2249       }
2250 
2251       mapped_type& mapped() const { return ptr_->value().second; }
2252 
2253       allocator_type get_allocator() const { return *alloc_; }
2254 
2255       explicit operator bool() const noexcept
2256       {
2257         return !this->operator!();
2258       }
2259 
2260       bool operator!() const noexcept { return ptr_ ? 0 : 1; }
2261 
2262       BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
2263       {
2264         return ptr_ ? 0 : 1;
2265       }
2266 
2267       void swap(node_handle_map& n)
2268         noexcept(boost::allocator_propagate_on_container_swap<
2269                    value_allocator>::type::value ||
2270                  boost::allocator_is_always_equal<value_allocator>::type::value)
2271       {
2272 
2273         BOOST_ASSERT(!alloc_.has_value() || !n.alloc_.has_value() ||
2274                      boost::allocator_propagate_on_container_swap<
2275                        value_allocator>::type::value ||
2276                      alloc_ == n.alloc_);
2277         if (boost::allocator_propagate_on_container_swap<
2278               value_allocator>::type::value ||
2279             !alloc_.has_value() || !n.alloc_.has_value()) {
2280           boost::core::invoke_swap(alloc_, n.alloc_);
2281         }
2282         boost::core::invoke_swap(ptr_, n.ptr_);
2283       }
2284     };
2285 
2286     template <class N, class K, class T, class A>
2287     void swap(node_handle_map<N, K, T, A>& x, node_handle_map<N, K, T, A>& y)
2288       noexcept(noexcept(x.swap(y)))
2289     {
2290       x.swap(y);
2291     }
2292 
2293     template <class Iter, class NodeType> struct insert_return_type_map
2294     {
2295     public:
2296       Iter position;
2297       bool inserted;
2298       NodeType node;
2299 
2300       insert_return_type_map() : position(), inserted(false), node() {}
2301       insert_return_type_map(insert_return_type_map const&) = delete;
2302       insert_return_type_map& operator=(insert_return_type_map const&) = delete;
2303 
2304       insert_return_type_map(insert_return_type_map&& x) noexcept
2305           : position(x.position),
2306             inserted(x.inserted),
2307             node(std::move(x.node))
2308       {
2309       }
2310 
2311       insert_return_type_map& operator=(insert_return_type_map&& x)
2312       {
2313         inserted = x.inserted;
2314         position = x.position;
2315         node = std::move(x.node);
2316         return *this;
2317       }
2318     };
2319 
2320     template <class Iter, class NodeType>
2321     void swap(insert_return_type_map<Iter, NodeType>& x,
2322       insert_return_type_map<Iter, NodeType>& y)
2323     {
2324       boost::core::invoke_swap(x.node, y.node);
2325       boost::core::invoke_swap(x.inserted, y.inserted);
2326       boost::core::invoke_swap(x.position, y.position);
2327     }
2328   } // namespace unordered
2329 
2330   namespace serialization {
2331     template <class K, class T, class H, class P, class A>
2332     struct version<boost::unordered_map<K, T, H, P, A> >
2333     {
2334       BOOST_STATIC_CONSTANT(int, value = 1);
2335     };
2336 
2337     template <class K, class T, class H, class P, class A>
2338     struct version<boost::unordered_multimap<K, T, H, P, A> >
2339     {
2340       BOOST_STATIC_CONSTANT(int, value = 1);
2341     };
2342   } // namespace serialization
2343 
2344 } // namespace boost
2345 
2346 #if defined(BOOST_MSVC)
2347 #pragma warning(pop)
2348 #endif
2349 
2350 #endif // BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED