Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/unordered/unordered_node_set.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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