Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:07:50

0001 // Copyright (C) 2022-2023 Christian Mazakas
0002 // Copyright (C) 2024 Joaquin M Lopez Munoz
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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) /* marked as __forceinline not inlined */
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       /// Iterators
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       /// Capacity
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       /// Modifiers
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       /// Lookup
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         // TODO: someday refactor this to conditionally serialize the key and
0547         // include it in the error message
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       /// Hash Policy
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       /// Stats
0746       ///
0747       stats get_stats() const { return table_.get_stats(); }
0748 
0749       void reset_stats() noexcept { table_.reset_stats(); }
0750 #endif
0751 
0752       /// Observers
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) /* C4714 */
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   } // namespace unordered
0893 } // namespace boost
0894 
0895 #endif