Back to home page

EIC code displayed by LXR

 
 

    


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

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