Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (C) 2022-2023 Christian Mazakas
0002 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0003 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0004 
0005 #ifndef BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
0006 #define BOOST_UNORDERED_UNORDERED_NODE_MAP_HPP_INCLUDED
0007 
0008 #include <boost/config.hpp>
0009 #if defined(BOOST_HAS_PRAGMA_ONCE)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/unordered/detail/foa/element_type.hpp>
0014 #include <boost/unordered/detail/foa/node_handle.hpp>
0015 #include <boost/unordered/detail/foa/node_map_types.hpp>
0016 #include <boost/unordered/detail/foa/table.hpp>
0017 #include <boost/unordered/detail/serialize_container.hpp>
0018 #include <boost/unordered/detail/type_traits.hpp>
0019 #include <boost/unordered/unordered_node_map_fwd.hpp>
0020 
0021 #include <boost/core/allocator_access.hpp>
0022 #include <boost/container_hash/hash.hpp>
0023 #include <boost/throw_exception.hpp>
0024 
0025 #include <initializer_list>
0026 #include <iterator>
0027 #include <stdexcept>
0028 #include <type_traits>
0029 #include <utility>
0030 
0031 namespace boost {
0032   namespace unordered {
0033 
0034 #if defined(BOOST_MSVC)
0035 #pragma warning(push)
0036 #pragma warning(disable : 4714) /* marked as __forceinline not inlined */
0037 #endif
0038 
0039     namespace detail {
0040       template <class TypePolicy, class Allocator>
0041       struct node_map_handle
0042           : public detail::foa::node_handle_base<TypePolicy, Allocator>
0043       {
0044       private:
0045         using base_type = detail::foa::node_handle_base<TypePolicy, Allocator>;
0046 
0047         using typename base_type::type_policy;
0048 
0049         template <class Key, class T, class Hash, class Pred, class Alloc>
0050         friend class boost::unordered::unordered_node_map;
0051 
0052       public:
0053         using key_type = typename TypePolicy::key_type;
0054         using mapped_type = typename TypePolicy::mapped_type;
0055 
0056         constexpr node_map_handle() noexcept = default;
0057         node_map_handle(node_map_handle&& nh) noexcept = default;
0058 
0059         node_map_handle& operator=(node_map_handle&&) noexcept = default;
0060 
0061         key_type& key() const
0062         {
0063           BOOST_ASSERT(!this->empty());
0064           return const_cast<key_type&>(this->data().first);
0065         }
0066 
0067         mapped_type& mapped() const
0068         {
0069           BOOST_ASSERT(!this->empty());
0070           return const_cast<mapped_type&>(this->data().second);
0071         }
0072       };
0073     } // namespace detail
0074 
0075     template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0076     class unordered_node_map
0077     {
0078       using map_types = detail::foa::node_map_types<Key, T,
0079         typename boost::allocator_void_pointer<Allocator>::type>;
0080 
0081       using table_type = detail::foa::table<map_types, Hash, KeyEqual,
0082         typename boost::allocator_rebind<Allocator,
0083           std::pair<Key const, T> >::type>;
0084 
0085       table_type table_;
0086 
0087       template <class K, class V, class H, class KE, class A>
0088       bool friend operator==(unordered_node_map<K, V, H, KE, A> const& lhs,
0089         unordered_node_map<K, V, H, KE, A> const& rhs);
0090 
0091       template <class K, class V, class H, class KE, class A, class Pred>
0092       typename unordered_node_map<K, V, H, KE, A>::size_type friend erase_if(
0093         unordered_node_map<K, V, H, KE, A>& set, Pred pred);
0094 
0095     public:
0096       using key_type = Key;
0097       using mapped_type = T;
0098       using value_type = typename map_types::value_type;
0099       using init_type = typename map_types::init_type;
0100       using size_type = std::size_t;
0101       using difference_type = std::ptrdiff_t;
0102       using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
0103       using key_equal = typename boost::unordered::detail::type_identity<KeyEqual>::type;
0104       using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
0105       using reference = value_type&;
0106       using const_reference = value_type const&;
0107       using pointer = typename boost::allocator_pointer<allocator_type>::type;
0108       using const_pointer =
0109         typename boost::allocator_const_pointer<allocator_type>::type;
0110       using iterator = typename table_type::iterator;
0111       using const_iterator = typename table_type::const_iterator;
0112       using node_type = detail::node_map_handle<map_types,
0113         typename boost::allocator_rebind<Allocator,
0114           typename map_types::value_type>::type>;
0115       using insert_return_type =
0116         detail::foa::insert_return_type<iterator, node_type>;
0117 
0118       unordered_node_map() : unordered_node_map(0) {}
0119 
0120       explicit unordered_node_map(size_type n, hasher const& h = hasher(),
0121         key_equal const& pred = key_equal(),
0122         allocator_type const& a = allocator_type())
0123           : table_(n, h, pred, a)
0124       {
0125       }
0126 
0127       unordered_node_map(size_type n, allocator_type const& a)
0128           : unordered_node_map(n, hasher(), key_equal(), a)
0129       {
0130       }
0131 
0132       unordered_node_map(size_type n, hasher const& h, allocator_type const& a)
0133           : unordered_node_map(n, h, key_equal(), a)
0134       {
0135       }
0136 
0137       template <class InputIterator>
0138       unordered_node_map(
0139         InputIterator f, InputIterator l, allocator_type const& a)
0140           : unordered_node_map(f, l, size_type(0), hasher(), key_equal(), a)
0141       {
0142       }
0143 
0144       explicit unordered_node_map(allocator_type const& a)
0145           : unordered_node_map(0, a)
0146       {
0147       }
0148 
0149       template <class Iterator>
0150       unordered_node_map(Iterator first, Iterator last, size_type n = 0,
0151         hasher const& h = hasher(), key_equal const& pred = key_equal(),
0152         allocator_type const& a = allocator_type())
0153           : unordered_node_map(n, h, pred, a)
0154       {
0155         this->insert(first, last);
0156       }
0157 
0158       template <class Iterator>
0159       unordered_node_map(
0160         Iterator first, Iterator last, size_type n, allocator_type const& a)
0161           : unordered_node_map(first, last, n, hasher(), key_equal(), a)
0162       {
0163       }
0164 
0165       template <class Iterator>
0166       unordered_node_map(Iterator first, Iterator last, size_type n,
0167         hasher const& h, allocator_type const& a)
0168           : unordered_node_map(first, last, n, h, key_equal(), a)
0169       {
0170       }
0171 
0172       unordered_node_map(unordered_node_map const& other) : table_(other.table_)
0173       {
0174       }
0175 
0176       unordered_node_map(
0177         unordered_node_map const& other, allocator_type const& a)
0178           : table_(other.table_, a)
0179       {
0180       }
0181 
0182       unordered_node_map(unordered_node_map&& other)
0183         noexcept(std::is_nothrow_move_constructible<table_type>::value)
0184           : table_(std::move(other.table_))
0185       {
0186       }
0187 
0188       unordered_node_map(unordered_node_map&& other, allocator_type const& al)
0189           : table_(std::move(other.table_), al)
0190       {
0191       }
0192 
0193       unordered_node_map(std::initializer_list<value_type> ilist,
0194         size_type n = 0, hasher const& h = hasher(),
0195         key_equal const& pred = key_equal(),
0196         allocator_type const& a = allocator_type())
0197           : unordered_node_map(ilist.begin(), ilist.end(), n, h, pred, a)
0198       {
0199       }
0200 
0201       unordered_node_map(
0202         std::initializer_list<value_type> il, allocator_type const& a)
0203           : unordered_node_map(il, size_type(0), hasher(), key_equal(), a)
0204       {
0205       }
0206 
0207       unordered_node_map(std::initializer_list<value_type> init, size_type n,
0208         allocator_type const& a)
0209           : unordered_node_map(init, n, hasher(), key_equal(), a)
0210       {
0211       }
0212 
0213       unordered_node_map(std::initializer_list<value_type> init, size_type n,
0214         hasher const& h, allocator_type const& a)
0215           : unordered_node_map(init, n, h, key_equal(), a)
0216       {
0217       }
0218 
0219       ~unordered_node_map() = default;
0220 
0221       unordered_node_map& operator=(unordered_node_map const& other)
0222       {
0223         table_ = other.table_;
0224         return *this;
0225       }
0226 
0227       unordered_node_map& operator=(unordered_node_map&& other) noexcept(
0228         noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
0229       {
0230         table_ = std::move(other.table_);
0231         return *this;
0232       }
0233 
0234       allocator_type get_allocator() const noexcept
0235       {
0236         return table_.get_allocator();
0237       }
0238 
0239       /// Iterators
0240       ///
0241 
0242       iterator begin() noexcept { return table_.begin(); }
0243       const_iterator begin() const noexcept { return table_.begin(); }
0244       const_iterator cbegin() const noexcept { return table_.cbegin(); }
0245 
0246       iterator end() noexcept { return table_.end(); }
0247       const_iterator end() const noexcept { return table_.end(); }
0248       const_iterator cend() const noexcept { return table_.cend(); }
0249 
0250       /// Capacity
0251       ///
0252 
0253       BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0254       {
0255         return table_.empty();
0256       }
0257 
0258       size_type size() const noexcept { return table_.size(); }
0259 
0260       size_type max_size() const noexcept { return table_.max_size(); }
0261 
0262       /// Modifiers
0263       ///
0264 
0265       void clear() noexcept { table_.clear(); }
0266 
0267       template <class Ty>
0268       BOOST_FORCEINLINE auto insert(Ty&& value)
0269         -> decltype(table_.insert(std::forward<Ty>(value)))
0270       {
0271         return table_.insert(std::forward<Ty>(value));
0272       }
0273 
0274       BOOST_FORCEINLINE std::pair<iterator, bool> insert(init_type&& value)
0275       {
0276         return table_.insert(std::move(value));
0277       }
0278 
0279       template <class Ty>
0280       BOOST_FORCEINLINE auto insert(const_iterator, Ty&& value)
0281         -> decltype(table_.insert(std::forward<Ty>(value)).first)
0282       {
0283         return table_.insert(std::forward<Ty>(value)).first;
0284       }
0285 
0286       BOOST_FORCEINLINE iterator insert(const_iterator, init_type&& value)
0287       {
0288         return table_.insert(std::move(value)).first;
0289       }
0290 
0291       template <class InputIterator>
0292       BOOST_FORCEINLINE void insert(InputIterator first, InputIterator last)
0293       {
0294         for (auto pos = first; pos != last; ++pos) {
0295           table_.emplace(*pos);
0296         }
0297       }
0298 
0299       void insert(std::initializer_list<value_type> ilist)
0300       {
0301         this->insert(ilist.begin(), ilist.end());
0302       }
0303 
0304       insert_return_type insert(node_type&& nh)
0305       {
0306         if (nh.empty()) {
0307           return {end(), false, node_type{}};
0308         }
0309 
0310         BOOST_ASSERT(get_allocator() == nh.get_allocator());
0311 
0312         auto itp = table_.insert(std::move(nh.element()));
0313         if (itp.second) {
0314           nh.reset();
0315           return {itp.first, true, node_type{}};
0316         } else {
0317           return {itp.first, false, std::move(nh)};
0318         }
0319       }
0320 
0321       iterator insert(const_iterator, node_type&& nh)
0322       {
0323         if (nh.empty()) {
0324           return end();
0325         }
0326 
0327         BOOST_ASSERT(get_allocator() == nh.get_allocator());
0328 
0329         auto itp = table_.insert(std::move(nh.element()));
0330         if (itp.second) {
0331           nh.reset();
0332           return itp.first;
0333         } else {
0334           return itp.first;
0335         }
0336       }
0337 
0338       template <class M>
0339       std::pair<iterator, bool> insert_or_assign(key_type const& key, M&& obj)
0340       {
0341         auto ibp = table_.try_emplace(key, std::forward<M>(obj));
0342         if (ibp.second) {
0343           return ibp;
0344         }
0345         ibp.first->second = std::forward<M>(obj);
0346         return ibp;
0347       }
0348 
0349       template <class M>
0350       std::pair<iterator, bool> insert_or_assign(key_type&& key, M&& obj)
0351       {
0352         auto ibp = table_.try_emplace(std::move(key), std::forward<M>(obj));
0353         if (ibp.second) {
0354           return ibp;
0355         }
0356         ibp.first->second = std::forward<M>(obj);
0357         return ibp;
0358       }
0359 
0360       template <class K, class M>
0361       typename std::enable_if<
0362         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0363         std::pair<iterator, bool> >::type
0364       insert_or_assign(K&& k, M&& obj)
0365       {
0366         auto ibp = table_.try_emplace(std::forward<K>(k), std::forward<M>(obj));
0367         if (ibp.second) {
0368           return ibp;
0369         }
0370         ibp.first->second = std::forward<M>(obj);
0371         return ibp;
0372       }
0373 
0374       template <class M>
0375       iterator insert_or_assign(const_iterator, key_type const& key, M&& obj)
0376       {
0377         return this->insert_or_assign(key, std::forward<M>(obj)).first;
0378       }
0379 
0380       template <class M>
0381       iterator insert_or_assign(const_iterator, key_type&& key, M&& obj)
0382       {
0383         return this->insert_or_assign(std::move(key), std::forward<M>(obj))
0384           .first;
0385       }
0386 
0387       template <class K, class M>
0388       typename std::enable_if<
0389         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0390         iterator>::type
0391       insert_or_assign(const_iterator, K&& k, M&& obj)
0392       {
0393         return this->insert_or_assign(std::forward<K>(k), std::forward<M>(obj))
0394           .first;
0395       }
0396 
0397       template <class... Args>
0398       BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
0399       {
0400         return table_.emplace(std::forward<Args>(args)...);
0401       }
0402 
0403       template <class... Args>
0404       BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
0405       {
0406         return table_.emplace(std::forward<Args>(args)...).first;
0407       }
0408 
0409       template <class... Args>
0410       BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
0411         key_type const& key, Args&&... args)
0412       {
0413         return table_.try_emplace(key, std::forward<Args>(args)...);
0414       }
0415 
0416       template <class... Args>
0417       BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
0418         key_type&& key, Args&&... args)
0419       {
0420         return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
0421       }
0422 
0423       template <class K, class... Args>
0424       BOOST_FORCEINLINE typename std::enable_if<
0425         boost::unordered::detail::transparent_non_iterable<K,
0426           unordered_node_map>::value,
0427         std::pair<iterator, bool> >::type
0428       try_emplace(K&& key, Args&&... args)
0429       {
0430         return table_.try_emplace(
0431           std::forward<K>(key), std::forward<Args>(args)...);
0432       }
0433 
0434       template <class... Args>
0435       BOOST_FORCEINLINE iterator try_emplace(
0436         const_iterator, key_type const& key, Args&&... args)
0437       {
0438         return table_.try_emplace(key, std::forward<Args>(args)...).first;
0439       }
0440 
0441       template <class... Args>
0442       BOOST_FORCEINLINE iterator try_emplace(
0443         const_iterator, key_type&& key, Args&&... args)
0444       {
0445         return table_.try_emplace(std::move(key), std::forward<Args>(args)...)
0446           .first;
0447       }
0448 
0449       template <class K, class... Args>
0450       BOOST_FORCEINLINE typename std::enable_if<
0451         boost::unordered::detail::transparent_non_iterable<K,
0452           unordered_node_map>::value,
0453         iterator>::type
0454       try_emplace(const_iterator, K&& key, Args&&... args)
0455       {
0456         return table_
0457           .try_emplace(std::forward<K>(key), std::forward<Args>(args)...)
0458           .first;
0459       }
0460 
0461       BOOST_FORCEINLINE typename table_type::erase_return_type erase(
0462         iterator pos)
0463       {
0464         return table_.erase(pos);
0465       }
0466 
0467       BOOST_FORCEINLINE typename table_type::erase_return_type erase(
0468         const_iterator pos)
0469       {
0470         return table_.erase(pos);
0471       }
0472 
0473       iterator erase(const_iterator first, const_iterator last)
0474       {
0475         while (first != last) {
0476           this->erase(first++);
0477         }
0478         return iterator{detail::foa::const_iterator_cast_tag{}, last};
0479       }
0480 
0481       BOOST_FORCEINLINE size_type erase(key_type const& key)
0482       {
0483         return table_.erase(key);
0484       }
0485 
0486       template <class K>
0487       BOOST_FORCEINLINE typename std::enable_if<
0488         detail::transparent_non_iterable<K, unordered_node_map>::value,
0489         size_type>::type
0490       erase(K const& key)
0491       {
0492         return table_.erase(key);
0493       }
0494 
0495       void swap(unordered_node_map& rhs) noexcept(
0496         noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
0497       {
0498         table_.swap(rhs.table_);
0499       }
0500 
0501       node_type extract(const_iterator pos)
0502       {
0503         BOOST_ASSERT(pos != end());
0504         node_type nh;
0505         auto elem = table_.extract(pos);
0506         nh.emplace(std::move(elem), get_allocator());
0507         return nh;
0508       }
0509 
0510       node_type extract(key_type const& key)
0511       {
0512         auto pos = find(key);
0513         return pos != end() ? extract(pos) : node_type();
0514       }
0515 
0516       template <class K>
0517       typename std::enable_if<
0518         boost::unordered::detail::transparent_non_iterable<K,
0519           unordered_node_map>::value,
0520         node_type>::type
0521       extract(K const& key)
0522       {
0523         auto pos = find(key);
0524         return pos != end() ? extract(pos) : node_type();
0525       }
0526 
0527       template <class H2, class P2>
0528       void merge(
0529         unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&
0530           source)
0531       {
0532         BOOST_ASSERT(get_allocator() == source.get_allocator());
0533         table_.merge(source.table_);
0534       }
0535 
0536       template <class H2, class P2>
0537       void merge(
0538         unordered_node_map<key_type, mapped_type, H2, P2, allocator_type>&&
0539           source)
0540       {
0541         BOOST_ASSERT(get_allocator() == source.get_allocator());
0542         table_.merge(std::move(source.table_));
0543       }
0544 
0545       /// Lookup
0546       ///
0547 
0548       mapped_type& at(key_type const& key)
0549       {
0550         auto pos = table_.find(key);
0551         if (pos != table_.end()) {
0552           return pos->second;
0553         }
0554         // TODO: someday refactor this to conditionally serialize the key and
0555         // include it in the error message
0556         //
0557         boost::throw_exception(
0558           std::out_of_range("key was not found in unordered_node_map"));
0559       }
0560 
0561       mapped_type const& at(key_type const& key) const
0562       {
0563         auto pos = table_.find(key);
0564         if (pos != table_.end()) {
0565           return pos->second;
0566         }
0567         boost::throw_exception(
0568           std::out_of_range("key was not found in unordered_node_map"));
0569       }
0570 
0571       template <class K>
0572       typename std::enable_if<
0573         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0574         mapped_type&>::type
0575       at(K&& key)
0576       {
0577         auto pos = table_.find(std::forward<K>(key));
0578         if (pos != table_.end()) {
0579           return pos->second;
0580         }
0581         boost::throw_exception(
0582           std::out_of_range("key was not found in unordered_node_map"));
0583       }
0584 
0585       template <class K>
0586       typename std::enable_if<
0587         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0588         mapped_type const&>::type
0589       at(K&& key) const
0590       {
0591         auto pos = table_.find(std::forward<K>(key));
0592         if (pos != table_.end()) {
0593           return pos->second;
0594         }
0595         boost::throw_exception(
0596           std::out_of_range("key was not found in unordered_node_map"));
0597       }
0598 
0599       BOOST_FORCEINLINE mapped_type& operator[](key_type const& key)
0600       {
0601         return table_.try_emplace(key).first->second;
0602       }
0603 
0604       BOOST_FORCEINLINE mapped_type& operator[](key_type&& key)
0605       {
0606         return table_.try_emplace(std::move(key)).first->second;
0607       }
0608 
0609       template <class K>
0610       typename std::enable_if<
0611         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0612         mapped_type&>::type
0613       operator[](K&& key)
0614       {
0615         return table_.try_emplace(std::forward<K>(key)).first->second;
0616       }
0617 
0618       BOOST_FORCEINLINE size_type count(key_type const& key) const
0619       {
0620         auto pos = table_.find(key);
0621         return pos != table_.end() ? 1 : 0;
0622       }
0623 
0624       template <class K>
0625       BOOST_FORCEINLINE typename std::enable_if<
0626         detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0627       count(K const& key) const
0628       {
0629         auto pos = table_.find(key);
0630         return pos != table_.end() ? 1 : 0;
0631       }
0632 
0633       BOOST_FORCEINLINE iterator find(key_type const& key)
0634       {
0635         return table_.find(key);
0636       }
0637 
0638       BOOST_FORCEINLINE const_iterator find(key_type const& key) const
0639       {
0640         return table_.find(key);
0641       }
0642 
0643       template <class K>
0644       BOOST_FORCEINLINE typename std::enable_if<
0645         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0646         iterator>::type
0647       find(K const& key)
0648       {
0649         return table_.find(key);
0650       }
0651 
0652       template <class K>
0653       BOOST_FORCEINLINE typename std::enable_if<
0654         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0655         const_iterator>::type
0656       find(K const& key) const
0657       {
0658         return table_.find(key);
0659       }
0660 
0661       BOOST_FORCEINLINE bool contains(key_type const& key) const
0662       {
0663         return this->find(key) != this->end();
0664       }
0665 
0666       template <class K>
0667       BOOST_FORCEINLINE typename std::enable_if<
0668         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0669         bool>::type
0670       contains(K const& key) const
0671       {
0672         return this->find(key) != this->end();
0673       }
0674 
0675       std::pair<iterator, iterator> equal_range(key_type const& key)
0676       {
0677         auto pos = table_.find(key);
0678         if (pos == table_.end()) {
0679           return {pos, pos};
0680         }
0681 
0682         auto next = pos;
0683         ++next;
0684         return {pos, next};
0685       }
0686 
0687       std::pair<const_iterator, const_iterator> equal_range(
0688         key_type const& key) const
0689       {
0690         auto pos = table_.find(key);
0691         if (pos == table_.end()) {
0692           return {pos, pos};
0693         }
0694 
0695         auto next = pos;
0696         ++next;
0697         return {pos, next};
0698       }
0699 
0700       template <class K>
0701       typename std::enable_if<
0702         detail::are_transparent<K, hasher, key_equal>::value,
0703         std::pair<iterator, iterator> >::type
0704       equal_range(K const& key)
0705       {
0706         auto pos = table_.find(key);
0707         if (pos == table_.end()) {
0708           return {pos, pos};
0709         }
0710 
0711         auto next = pos;
0712         ++next;
0713         return {pos, next};
0714       }
0715 
0716       template <class K>
0717       typename std::enable_if<
0718         detail::are_transparent<K, hasher, key_equal>::value,
0719         std::pair<const_iterator, const_iterator> >::type
0720       equal_range(K const& key) const
0721       {
0722         auto pos = table_.find(key);
0723         if (pos == table_.end()) {
0724           return {pos, pos};
0725         }
0726 
0727         auto next = pos;
0728         ++next;
0729         return {pos, next};
0730       }
0731 
0732       /// Hash Policy
0733       ///
0734 
0735       size_type bucket_count() const noexcept { return table_.capacity(); }
0736 
0737       float load_factor() const noexcept { return table_.load_factor(); }
0738 
0739       float max_load_factor() const noexcept
0740       {
0741         return table_.max_load_factor();
0742       }
0743 
0744       void max_load_factor(float) {}
0745 
0746       size_type max_load() const noexcept { return table_.max_load(); }
0747 
0748       void rehash(size_type n) { table_.rehash(n); }
0749 
0750       void reserve(size_type n) { table_.reserve(n); }
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