File indexing completed on 2025-01-18 09:53:24
0001
0002
0003
0004
0005
0006
0007
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
0028 #pragma warning(disable : 4127)
0029 #if BOOST_MSVC >= 1400
0030
0031
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
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
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
0136
0137 ~unordered_map() noexcept;
0138
0139
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
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
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
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
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
0418
0419 hasher hash_function() const;
0420 key_equal key_eq() const;
0421
0422
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
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
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 };
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
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
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
0784
0785 ~unordered_multimap() noexcept;
0786
0787
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
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
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
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
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
0963
0964 hasher hash_function() const;
0965 key_equal key_eq() const;
0966
0967
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
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
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 };
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
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
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
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
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
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
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
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
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
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
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
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
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 }
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 }
2343
2344 }
2345
2346 #if defined(BOOST_MSVC)
2347 #pragma warning(pop)
2348 #endif
2349
2350 #endif