File indexing completed on 2025-09-18 09:07:50
0001
0002
0003
0004
0005
0006 #ifndef BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
0007 #define BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
0008
0009 #include <boost/config.hpp>
0010 #if defined(BOOST_HAS_PRAGMA_ONCE)
0011 #pragma once
0012 #endif
0013
0014 #include <boost/unordered/concurrent_node_map_fwd.hpp>
0015 #include <boost/unordered/detail/foa/node_map_handle.hpp>
0016 #include <boost/unordered/detail/foa/node_map_types.hpp>
0017 #include <boost/unordered/detail/foa/table.hpp>
0018 #include <boost/unordered/detail/serialize_container.hpp>
0019 #include <boost/unordered/detail/throw_exception.hpp>
0020 #include <boost/unordered/detail/type_traits.hpp>
0021 #include <boost/unordered/unordered_node_map_fwd.hpp>
0022
0023 #include <boost/core/allocator_access.hpp>
0024 #include <boost/container_hash/hash.hpp>
0025
0026 #include <initializer_list>
0027 #include <iterator>
0028 #include <stdexcept>
0029 #include <type_traits>
0030 #include <utility>
0031
0032 namespace boost {
0033 namespace unordered {
0034
0035 #if defined(BOOST_MSVC)
0036 #pragma warning(push)
0037 #pragma warning(disable : 4714)
0038 #endif
0039
0040 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0041 class unordered_node_map
0042 {
0043 template <class Key2, class T2, class Hash2, class Pred2,
0044 class Allocator2>
0045 friend class concurrent_node_map;
0046
0047 using map_types = detail::foa::node_map_types<Key, T,
0048 typename boost::allocator_void_pointer<Allocator>::type>;
0049
0050 using table_type = detail::foa::table<map_types, Hash, KeyEqual,
0051 typename boost::allocator_rebind<Allocator,
0052 std::pair<Key const, T> >::type>;
0053
0054 table_type table_;
0055
0056 template <class K, class V, class H, class KE, class A>
0057 bool friend operator==(unordered_node_map<K, V, H, KE, A> const& lhs,
0058 unordered_node_map<K, V, H, KE, A> const& rhs);
0059
0060 template <class K, class V, class H, class KE, class A, class Pred>
0061 typename unordered_node_map<K, V, H, KE, A>::size_type friend erase_if(
0062 unordered_node_map<K, V, H, KE, A>& set, Pred pred);
0063
0064 public:
0065 using key_type = Key;
0066 using mapped_type = T;
0067 using value_type = typename map_types::value_type;
0068 using init_type = typename map_types::init_type;
0069 using size_type = std::size_t;
0070 using difference_type = std::ptrdiff_t;
0071 using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
0072 using key_equal = typename boost::unordered::detail::type_identity<KeyEqual>::type;
0073 using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
0074 using reference = value_type&;
0075 using const_reference = value_type const&;
0076 using pointer = typename boost::allocator_pointer<allocator_type>::type;
0077 using const_pointer =
0078 typename boost::allocator_const_pointer<allocator_type>::type;
0079 using iterator = typename table_type::iterator;
0080 using const_iterator = typename table_type::const_iterator;
0081 using node_type = detail::foa::node_map_handle<map_types,
0082 typename boost::allocator_rebind<Allocator,
0083 typename map_types::value_type>::type>;
0084 using insert_return_type =
0085 detail::foa::insert_return_type<iterator, node_type>;
0086
0087 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0088 using stats = typename table_type::stats;
0089 #endif
0090
0091 unordered_node_map() : unordered_node_map(0) {}
0092
0093 explicit unordered_node_map(size_type n, hasher const& h = hasher(),
0094 key_equal const& pred = key_equal(),
0095 allocator_type const& a = allocator_type())
0096 : table_(n, h, pred, a)
0097 {
0098 }
0099
0100 unordered_node_map(size_type n, allocator_type const& a)
0101 : unordered_node_map(n, hasher(), key_equal(), a)
0102 {
0103 }
0104
0105 unordered_node_map(size_type n, hasher const& h, allocator_type const& a)
0106 : unordered_node_map(n, h, key_equal(), a)
0107 {
0108 }
0109
0110 template <class InputIterator>
0111 unordered_node_map(
0112 InputIterator f, InputIterator l, allocator_type const& a)
0113 : unordered_node_map(f, l, size_type(0), hasher(), key_equal(), a)
0114 {
0115 }
0116
0117 explicit unordered_node_map(allocator_type const& a)
0118 : unordered_node_map(0, a)
0119 {
0120 }
0121
0122 template <class Iterator>
0123 unordered_node_map(Iterator first, Iterator last, size_type n = 0,
0124 hasher const& h = hasher(), key_equal const& pred = key_equal(),
0125 allocator_type const& a = allocator_type())
0126 : unordered_node_map(n, h, pred, a)
0127 {
0128 this->insert(first, last);
0129 }
0130
0131 template <class Iterator>
0132 unordered_node_map(
0133 Iterator first, Iterator last, size_type n, allocator_type const& a)
0134 : unordered_node_map(first, last, n, hasher(), key_equal(), a)
0135 {
0136 }
0137
0138 template <class Iterator>
0139 unordered_node_map(Iterator first, Iterator last, size_type n,
0140 hasher const& h, allocator_type const& a)
0141 : unordered_node_map(first, last, n, h, key_equal(), a)
0142 {
0143 }
0144
0145 unordered_node_map(unordered_node_map const& other) : table_(other.table_)
0146 {
0147 }
0148
0149 unordered_node_map(
0150 unordered_node_map const& other, allocator_type const& a)
0151 : table_(other.table_, a)
0152 {
0153 }
0154
0155 unordered_node_map(unordered_node_map&& other)
0156 noexcept(std::is_nothrow_move_constructible<table_type>::value)
0157 : table_(std::move(other.table_))
0158 {
0159 }
0160
0161 unordered_node_map(unordered_node_map&& other, allocator_type const& al)
0162 : table_(std::move(other.table_), al)
0163 {
0164 }
0165
0166 unordered_node_map(std::initializer_list<value_type> ilist,
0167 size_type n = 0, hasher const& h = hasher(),
0168 key_equal const& pred = key_equal(),
0169 allocator_type const& a = allocator_type())
0170 : unordered_node_map(ilist.begin(), ilist.end(), n, h, pred, a)
0171 {
0172 }
0173
0174 unordered_node_map(
0175 std::initializer_list<value_type> il, allocator_type const& a)
0176 : unordered_node_map(il, size_type(0), hasher(), key_equal(), a)
0177 {
0178 }
0179
0180 unordered_node_map(std::initializer_list<value_type> init, size_type n,
0181 allocator_type const& a)
0182 : unordered_node_map(init, n, hasher(), key_equal(), a)
0183 {
0184 }
0185
0186 unordered_node_map(std::initializer_list<value_type> init, size_type n,
0187 hasher const& h, allocator_type const& a)
0188 : unordered_node_map(init, n, h, key_equal(), a)
0189 {
0190 }
0191
0192 template <bool avoid_explicit_instantiation = true>
0193 unordered_node_map(
0194 concurrent_node_map<Key, T, Hash, KeyEqual, Allocator>&& other)
0195 : table_(std::move(other.table_))
0196 {
0197 }
0198
0199 ~unordered_node_map() = default;
0200
0201 unordered_node_map& operator=(unordered_node_map const& other)
0202 {
0203 table_ = other.table_;
0204 return *this;
0205 }
0206
0207 unordered_node_map& operator=(unordered_node_map&& other) noexcept(
0208 noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
0209 {
0210 table_ = std::move(other.table_);
0211 return *this;
0212 }
0213
0214 unordered_node_map& operator=(std::initializer_list<value_type> il)
0215 {
0216 this->clear();
0217 this->insert(il.begin(), il.end());
0218 return *this;
0219 }
0220
0221 allocator_type get_allocator() const noexcept
0222 {
0223 return table_.get_allocator();
0224 }
0225
0226
0227
0228
0229 iterator begin() noexcept { return table_.begin(); }
0230 const_iterator begin() const noexcept { return table_.begin(); }
0231 const_iterator cbegin() const noexcept { return table_.cbegin(); }
0232
0233 iterator end() noexcept { return table_.end(); }
0234 const_iterator end() const noexcept { return table_.end(); }
0235 const_iterator cend() const noexcept { return table_.cend(); }
0236
0237
0238
0239
0240 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0241 {
0242 return table_.empty();
0243 }
0244
0245 size_type size() const noexcept { return table_.size(); }
0246
0247 size_type max_size() const noexcept { return table_.max_size(); }
0248
0249
0250
0251
0252 void clear() noexcept { table_.clear(); }
0253
0254 template <class Ty>
0255 BOOST_FORCEINLINE auto insert(Ty&& value)
0256 -> decltype(table_.insert(std::forward<Ty>(value)))
0257 {
0258 return table_.insert(std::forward<Ty>(value));
0259 }
0260
0261 BOOST_FORCEINLINE std::pair<iterator, bool> insert(init_type&& value)
0262 {
0263 return table_.insert(std::move(value));
0264 }
0265
0266 template <class Ty>
0267 BOOST_FORCEINLINE auto insert(const_iterator, Ty&& value)
0268 -> decltype(table_.insert(std::forward<Ty>(value)).first)
0269 {
0270 return table_.insert(std::forward<Ty>(value)).first;
0271 }
0272
0273 BOOST_FORCEINLINE iterator insert(const_iterator, init_type&& value)
0274 {
0275 return table_.insert(std::move(value)).first;
0276 }
0277
0278 template <class InputIterator>
0279 BOOST_FORCEINLINE void insert(InputIterator first, InputIterator last)
0280 {
0281 for (auto pos = first; pos != last; ++pos) {
0282 table_.emplace(*pos);
0283 }
0284 }
0285
0286 void insert(std::initializer_list<value_type> ilist)
0287 {
0288 this->insert(ilist.begin(), ilist.end());
0289 }
0290
0291 insert_return_type insert(node_type&& nh)
0292 {
0293 using access = detail::foa::node_handle_access;
0294
0295 if (nh.empty()) {
0296 return {end(), false, node_type{}};
0297 }
0298
0299 BOOST_ASSERT(get_allocator() == nh.get_allocator());
0300
0301 auto itp = table_.insert(std::move(access::element(nh)));
0302 if (itp.second) {
0303 access::reset(nh);
0304 return {itp.first, true, node_type{}};
0305 } else {
0306 return {itp.first, false, std::move(nh)};
0307 }
0308 }
0309
0310 iterator insert(const_iterator, node_type&& nh)
0311 {
0312 using access = detail::foa::node_handle_access;
0313
0314 if (nh.empty()) {
0315 return end();
0316 }
0317
0318 BOOST_ASSERT(get_allocator() == nh.get_allocator());
0319
0320 auto itp = table_.insert(std::move(access::element(nh)));
0321 if (itp.second) {
0322 access::reset(nh);
0323 return itp.first;
0324 } else {
0325 return itp.first;
0326 }
0327 }
0328
0329 template <class M>
0330 std::pair<iterator, bool> insert_or_assign(key_type const& key, M&& obj)
0331 {
0332 auto ibp = table_.try_emplace(key, std::forward<M>(obj));
0333 if (ibp.second) {
0334 return ibp;
0335 }
0336 ibp.first->second = std::forward<M>(obj);
0337 return ibp;
0338 }
0339
0340 template <class M>
0341 std::pair<iterator, bool> insert_or_assign(key_type&& key, M&& obj)
0342 {
0343 auto ibp = table_.try_emplace(std::move(key), std::forward<M>(obj));
0344 if (ibp.second) {
0345 return ibp;
0346 }
0347 ibp.first->second = std::forward<M>(obj);
0348 return ibp;
0349 }
0350
0351 template <class K, class M>
0352 typename std::enable_if<
0353 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0354 std::pair<iterator, bool> >::type
0355 insert_or_assign(K&& k, M&& obj)
0356 {
0357 auto ibp = table_.try_emplace(std::forward<K>(k), std::forward<M>(obj));
0358 if (ibp.second) {
0359 return ibp;
0360 }
0361 ibp.first->second = std::forward<M>(obj);
0362 return ibp;
0363 }
0364
0365 template <class M>
0366 iterator insert_or_assign(const_iterator, key_type const& key, M&& obj)
0367 {
0368 return this->insert_or_assign(key, std::forward<M>(obj)).first;
0369 }
0370
0371 template <class M>
0372 iterator insert_or_assign(const_iterator, key_type&& key, M&& obj)
0373 {
0374 return this->insert_or_assign(std::move(key), std::forward<M>(obj))
0375 .first;
0376 }
0377
0378 template <class K, class M>
0379 typename std::enable_if<
0380 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0381 iterator>::type
0382 insert_or_assign(const_iterator, K&& k, M&& obj)
0383 {
0384 return this->insert_or_assign(std::forward<K>(k), std::forward<M>(obj))
0385 .first;
0386 }
0387
0388 template <class... Args>
0389 BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
0390 {
0391 return table_.emplace(std::forward<Args>(args)...);
0392 }
0393
0394 template <class... Args>
0395 BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
0396 {
0397 return table_.emplace(std::forward<Args>(args)...).first;
0398 }
0399
0400 template <class... Args>
0401 BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
0402 key_type const& key, Args&&... args)
0403 {
0404 return table_.try_emplace(key, std::forward<Args>(args)...);
0405 }
0406
0407 template <class... Args>
0408 BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
0409 key_type&& key, Args&&... args)
0410 {
0411 return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
0412 }
0413
0414 template <class K, class... Args>
0415 BOOST_FORCEINLINE typename std::enable_if<
0416 boost::unordered::detail::transparent_non_iterable<K,
0417 unordered_node_map>::value,
0418 std::pair<iterator, bool> >::type
0419 try_emplace(K&& key, Args&&... args)
0420 {
0421 return table_.try_emplace(
0422 std::forward<K>(key), std::forward<Args>(args)...);
0423 }
0424
0425 template <class... Args>
0426 BOOST_FORCEINLINE iterator try_emplace(
0427 const_iterator, key_type const& key, Args&&... args)
0428 {
0429 return table_.try_emplace(key, std::forward<Args>(args)...).first;
0430 }
0431
0432 template <class... Args>
0433 BOOST_FORCEINLINE iterator try_emplace(
0434 const_iterator, key_type&& key, Args&&... args)
0435 {
0436 return table_.try_emplace(std::move(key), std::forward<Args>(args)...)
0437 .first;
0438 }
0439
0440 template <class K, class... Args>
0441 BOOST_FORCEINLINE typename std::enable_if<
0442 boost::unordered::detail::transparent_non_iterable<K,
0443 unordered_node_map>::value,
0444 iterator>::type
0445 try_emplace(const_iterator, K&& key, Args&&... args)
0446 {
0447 return table_
0448 .try_emplace(std::forward<K>(key), std::forward<Args>(args)...)
0449 .first;
0450 }
0451
0452 BOOST_FORCEINLINE typename table_type::erase_return_type erase(
0453 iterator pos)
0454 {
0455 return table_.erase(pos);
0456 }
0457
0458 BOOST_FORCEINLINE typename table_type::erase_return_type erase(
0459 const_iterator pos)
0460 {
0461 return table_.erase(pos);
0462 }
0463
0464 iterator erase(const_iterator first, const_iterator last)
0465 {
0466 while (first != last) {
0467 this->erase(first++);
0468 }
0469 return iterator{detail::foa::const_iterator_cast_tag{}, last};
0470 }
0471
0472 BOOST_FORCEINLINE size_type erase(key_type const& key)
0473 {
0474 return table_.erase(key);
0475 }
0476
0477 template <class K>
0478 BOOST_FORCEINLINE typename std::enable_if<
0479 detail::transparent_non_iterable<K, unordered_node_map>::value,
0480 size_type>::type
0481 erase(K const& key)
0482 {
0483 return table_.erase(key);
0484 }
0485
0486 void swap(unordered_node_map& rhs) noexcept(
0487 noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
0488 {
0489 table_.swap(rhs.table_);
0490 }
0491
0492 node_type extract(const_iterator pos)
0493 {
0494 BOOST_ASSERT(pos != end());
0495 node_type nh;
0496 auto elem = table_.extract(pos);
0497 detail::foa::node_handle_emplacer(nh)(
0498 std::move(elem), get_allocator());
0499 return nh;
0500 }
0501
0502 node_type extract(key_type const& key)
0503 {
0504 auto pos = find(key);
0505 return pos != end() ? extract(pos) : node_type();
0506 }
0507
0508 template <class K>
0509 typename std::enable_if<
0510 boost::unordered::detail::transparent_non_iterable<K,
0511 unordered_node_map>::value,
0512 node_type>::type
0513 extract(K const& key)
0514 {
0515 auto pos = find(key);
0516 return pos != end() ? extract(pos) : node_type();
0517 }
0518
0519 template <class H2, class P2>
0520 void merge(
0521 unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&
0522 source)
0523 {
0524 BOOST_ASSERT(get_allocator() == source.get_allocator());
0525 table_.merge(source.table_);
0526 }
0527
0528 template <class H2, class P2>
0529 void merge(
0530 unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&&
0531 source)
0532 {
0533 BOOST_ASSERT(get_allocator() == source.get_allocator());
0534 table_.merge(std::move(source.table_));
0535 }
0536
0537
0538
0539
0540 mapped_type& at(key_type const& key)
0541 {
0542 auto pos = table_.find(key);
0543 if (pos != table_.end()) {
0544 return pos->second;
0545 }
0546
0547
0548
0549 boost::unordered::detail::throw_out_of_range(
0550 "key was not found in unordered_node_map");
0551 }
0552
0553 mapped_type const& at(key_type const& key) const
0554 {
0555 auto pos = table_.find(key);
0556 if (pos != table_.end()) {
0557 return pos->second;
0558 }
0559 boost::unordered::detail::throw_out_of_range(
0560 "key was not found in unordered_node_map");
0561 }
0562
0563 template <class K>
0564 typename std::enable_if<
0565 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0566 mapped_type&>::type
0567 at(K&& key)
0568 {
0569 auto pos = table_.find(std::forward<K>(key));
0570 if (pos != table_.end()) {
0571 return pos->second;
0572 }
0573 boost::unordered::detail::throw_out_of_range(
0574 "key was not found in unordered_node_map");
0575 }
0576
0577 template <class K>
0578 typename std::enable_if<
0579 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0580 mapped_type const&>::type
0581 at(K&& key) const
0582 {
0583 auto pos = table_.find(std::forward<K>(key));
0584 if (pos != table_.end()) {
0585 return pos->second;
0586 }
0587 boost::unordered::detail::throw_out_of_range(
0588 "key was not found in unordered_node_map");
0589 }
0590
0591 BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
0592 {
0593 return table_.try_emplace(key).first->second;
0594 }
0595
0596 BOOST_FORCEINLINE mapped_type& operator[](key_type&& key)
0597 {
0598 return table_.try_emplace(std::move(key)).first->second;
0599 }
0600
0601 template <class K>
0602 typename std::enable_if<
0603 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0604 mapped_type&>::type
0605 operator[](K&& key)
0606 {
0607 return table_.try_emplace(std::forward<K>(key)).first->second;
0608 }
0609
0610 BOOST_FORCEINLINE size_type count(key_type const& key) const
0611 {
0612 auto pos = table_.find(key);
0613 return pos != table_.end() ? 1 : 0;
0614 }
0615
0616 template <class K>
0617 BOOST_FORCEINLINE typename std::enable_if<
0618 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0619 count(K const& key) const
0620 {
0621 auto pos = table_.find(key);
0622 return pos != table_.end() ? 1 : 0;
0623 }
0624
0625 BOOST_FORCEINLINE iterator find(key_type const& key)
0626 {
0627 return table_.find(key);
0628 }
0629
0630 BOOST_FORCEINLINE const_iterator find(key_type const& key) const
0631 {
0632 return table_.find(key);
0633 }
0634
0635 template <class K>
0636 BOOST_FORCEINLINE typename std::enable_if<
0637 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0638 iterator>::type
0639 find(K const& key)
0640 {
0641 return table_.find(key);
0642 }
0643
0644 template <class K>
0645 BOOST_FORCEINLINE typename std::enable_if<
0646 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0647 const_iterator>::type
0648 find(K const& key) const
0649 {
0650 return table_.find(key);
0651 }
0652
0653 BOOST_FORCEINLINE bool contains(key_type const& key) const
0654 {
0655 return this->find(key) != this->end();
0656 }
0657
0658 template <class K>
0659 BOOST_FORCEINLINE typename std::enable_if<
0660 boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0661 bool>::type
0662 contains(K const& key) const
0663 {
0664 return this->find(key) != this->end();
0665 }
0666
0667 std::pair<iterator, iterator> equal_range(key_type const& key)
0668 {
0669 auto pos = table_.find(key);
0670 if (pos == table_.end()) {
0671 return {pos, pos};
0672 }
0673
0674 auto next = pos;
0675 ++next;
0676 return {pos, next};
0677 }
0678
0679 std::pair<const_iterator, const_iterator> equal_range(
0680 key_type const& key) const
0681 {
0682 auto pos = table_.find(key);
0683 if (pos == table_.end()) {
0684 return {pos, pos};
0685 }
0686
0687 auto next = pos;
0688 ++next;
0689 return {pos, next};
0690 }
0691
0692 template <class K>
0693 typename std::enable_if<
0694 detail::are_transparent<K, hasher, key_equal>::value,
0695 std::pair<iterator, iterator> >::type
0696 equal_range(K const& key)
0697 {
0698 auto pos = table_.find(key);
0699 if (pos == table_.end()) {
0700 return {pos, pos};
0701 }
0702
0703 auto next = pos;
0704 ++next;
0705 return {pos, next};
0706 }
0707
0708 template <class K>
0709 typename std::enable_if<
0710 detail::are_transparent<K, hasher, key_equal>::value,
0711 std::pair<const_iterator, const_iterator> >::type
0712 equal_range(K const& key) const
0713 {
0714 auto pos = table_.find(key);
0715 if (pos == table_.end()) {
0716 return {pos, pos};
0717 }
0718
0719 auto next = pos;
0720 ++next;
0721 return {pos, next};
0722 }
0723
0724
0725
0726
0727 size_type bucket_count() const noexcept { return table_.capacity(); }
0728
0729 float load_factor() const noexcept { return table_.load_factor(); }
0730
0731 float max_load_factor() const noexcept
0732 {
0733 return table_.max_load_factor();
0734 }
0735
0736 void max_load_factor(float) {}
0737
0738 size_type max_load() const noexcept { return table_.max_load(); }
0739
0740 void rehash(size_type n) { table_.rehash(n); }
0741
0742 void reserve(size_type n) { table_.reserve(n); }
0743
0744 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0745
0746
0747 stats get_stats() const { return table_.get_stats(); }
0748
0749 void reset_stats() noexcept { table_.reset_stats(); }
0750 #endif
0751
0752
0753
0754
0755 hasher hash_function() const { return table_.hash_function(); }
0756
0757 key_equal key_eq() const { return table_.key_eq(); }
0758 };
0759
0760 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0761 bool operator==(
0762 unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
0763 unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
0764 {
0765 return lhs.table_ == rhs.table_;
0766 }
0767
0768 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0769 bool operator!=(
0770 unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
0771 unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
0772 {
0773 return !(lhs == rhs);
0774 }
0775
0776 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0777 void swap(unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
0778 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
0779 noexcept(noexcept(lhs.swap(rhs)))
0780 {
0781 lhs.swap(rhs);
0782 }
0783
0784 template <class Key, class T, class Hash, class KeyEqual, class Allocator,
0785 class Pred>
0786 typename unordered_node_map<Key, T, Hash, KeyEqual, Allocator>::size_type
0787 erase_if(
0788 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& map, Pred pred)
0789 {
0790 return erase_if(map.table_, pred);
0791 }
0792
0793 template <class Archive, class Key, class T, class Hash, class KeyEqual,
0794 class Allocator>
0795 void serialize(Archive& ar,
0796 unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& map,
0797 unsigned int version)
0798 {
0799 detail::serialize_container(ar, map, version);
0800 }
0801
0802 #if defined(BOOST_MSVC)
0803 #pragma warning(pop)
0804 #endif
0805
0806 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0807
0808 template <class InputIterator,
0809 class Hash =
0810 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0811 class Pred =
0812 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0813 class Allocator = std::allocator<
0814 boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
0815 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0816 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0817 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0818 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0819 unordered_node_map(InputIterator, InputIterator,
0820 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0821 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0822 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
0823 boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
0824 Allocator>;
0825
0826 template <class Key, class T,
0827 class Hash = boost::hash<std::remove_const_t<Key> >,
0828 class Pred = std::equal_to<std::remove_const_t<Key> >,
0829 class Allocator = std::allocator<std::pair<const Key, T> >,
0830 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0831 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0832 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0833 unordered_node_map(std::initializer_list<std::pair<Key, T> >,
0834 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0835 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0836 -> unordered_node_map<std::remove_const_t<Key>, T, Hash, Pred,
0837 Allocator>;
0838
0839 template <class InputIterator, class Allocator,
0840 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0841 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0842 unordered_node_map(InputIterator, InputIterator, std::size_t, Allocator)
0843 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
0844 boost::unordered::detail::iter_val_t<InputIterator>,
0845 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0846 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0847 Allocator>;
0848
0849 template <class InputIterator, class Allocator,
0850 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0851 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0852 unordered_node_map(InputIterator, InputIterator, Allocator)
0853 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
0854 boost::unordered::detail::iter_val_t<InputIterator>,
0855 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0856 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0857 Allocator>;
0858
0859 template <class InputIterator, class Hash, class Allocator,
0860 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0861 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0862 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0863 unordered_node_map(
0864 InputIterator, InputIterator, std::size_t, Hash, Allocator)
0865 -> unordered_node_map<boost::unordered::detail::iter_key_t<InputIterator>,
0866 boost::unordered::detail::iter_val_t<InputIterator>, Hash,
0867 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0868 Allocator>;
0869
0870 template <class Key, class T, class Allocator,
0871 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0872 unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
0873 Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
0874 boost::hash<std::remove_const_t<Key> >,
0875 std::equal_to<std::remove_const_t<Key> >, Allocator>;
0876
0877 template <class Key, class T, class Allocator,
0878 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0879 unordered_node_map(std::initializer_list<std::pair<Key, T> >, Allocator)
0880 -> unordered_node_map<std::remove_const_t<Key>, T,
0881 boost::hash<std::remove_const_t<Key> >,
0882 std::equal_to<std::remove_const_t<Key> >, Allocator>;
0883
0884 template <class Key, class T, class Hash, class Allocator,
0885 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0886 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0887 unordered_node_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
0888 Hash, Allocator) -> unordered_node_map<std::remove_const_t<Key>, T,
0889 Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
0890 #endif
0891
0892 }
0893 }
0894
0895 #endif