Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 08:51:09

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_SET_HPP_INCLUDED
0006 #define BOOST_UNORDERED_UNORDERED_FLAT_SET_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_set_fwd.hpp>
0014 #include <boost/unordered/detail/foa/flat_set_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_set_fwd.hpp>
0019 
0020 #include <boost/core/allocator_access.hpp>
0021 #include <boost/container_hash/hash.hpp>
0022 
0023 #include <initializer_list>
0024 #include <iterator>
0025 #include <type_traits>
0026 #include <utility>
0027 
0028 namespace boost {
0029   namespace unordered {
0030 
0031 #if defined(BOOST_MSVC)
0032 #pragma warning(push)
0033 #pragma warning(disable : 4714) /* marked as __forceinline not inlined */
0034 #endif
0035 
0036     template <class Key, class Hash, class KeyEqual, class Allocator>
0037     class unordered_flat_set
0038     {
0039       template <class Key2, class Hash2, class KeyEqual2, class Allocator2>
0040       friend class concurrent_flat_set;
0041 
0042       using set_types = detail::foa::flat_set_types<Key>;
0043 
0044       using table_type = detail::foa::table<set_types, Hash, KeyEqual,
0045         typename boost::allocator_rebind<Allocator,
0046           typename set_types::value_type>::type>;
0047 
0048       table_type table_;
0049 
0050       template <class K, class H, class KE, class A>
0051       bool friend operator==(unordered_flat_set<K, H, KE, A> const& lhs,
0052         unordered_flat_set<K, H, KE, A> const& rhs);
0053 
0054       template <class K, class H, class KE, class A, class Pred>
0055       typename unordered_flat_set<K, H, KE, A>::size_type friend erase_if(
0056         unordered_flat_set<K, H, KE, A>& set, Pred pred);
0057 
0058     public:
0059       using key_type = Key;
0060       using value_type = typename set_types::value_type;
0061       using init_type = typename set_types::init_type;
0062       using size_type = std::size_t;
0063       using difference_type = std::ptrdiff_t;
0064       using hasher = Hash;
0065       using key_equal = KeyEqual;
0066       using allocator_type = Allocator;
0067       using reference = value_type&;
0068       using const_reference = value_type const&;
0069       using pointer = typename boost::allocator_pointer<allocator_type>::type;
0070       using const_pointer =
0071         typename boost::allocator_const_pointer<allocator_type>::type;
0072       using iterator = typename table_type::iterator;
0073       using const_iterator = typename table_type::const_iterator;
0074 
0075 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0076       using stats = typename table_type::stats;
0077 #endif
0078 
0079       unordered_flat_set() : unordered_flat_set(0) {}
0080 
0081       explicit unordered_flat_set(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_set(size_type n, allocator_type const& a)
0089           : unordered_flat_set(n, hasher(), key_equal(), a)
0090       {
0091       }
0092 
0093       unordered_flat_set(size_type n, hasher const& h, allocator_type const& a)
0094           : unordered_flat_set(n, h, key_equal(), a)
0095       {
0096       }
0097 
0098       template <class InputIterator>
0099       unordered_flat_set(
0100         InputIterator f, InputIterator l, allocator_type const& a)
0101           : unordered_flat_set(f, l, size_type(0), hasher(), key_equal(), a)
0102       {
0103       }
0104 
0105       explicit unordered_flat_set(allocator_type const& a)
0106           : unordered_flat_set(0, a)
0107       {
0108       }
0109 
0110       template <class Iterator>
0111       unordered_flat_set(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_set(n, h, pred, a)
0115       {
0116         this->insert(first, last);
0117       }
0118 
0119       template <class InputIt>
0120       unordered_flat_set(
0121         InputIt first, InputIt last, size_type n, allocator_type const& a)
0122           : unordered_flat_set(first, last, n, hasher(), key_equal(), a)
0123       {
0124       }
0125 
0126       template <class Iterator>
0127       unordered_flat_set(Iterator first, Iterator last, size_type n,
0128         hasher const& h, allocator_type const& a)
0129           : unordered_flat_set(first, last, n, h, key_equal(), a)
0130       {
0131       }
0132 
0133       unordered_flat_set(unordered_flat_set const& other) : table_(other.table_)
0134       {
0135       }
0136 
0137       unordered_flat_set(
0138         unordered_flat_set const& other, allocator_type const& a)
0139           : table_(other.table_, a)
0140       {
0141       }
0142 
0143       unordered_flat_set(unordered_flat_set&& other)
0144         noexcept(std::is_nothrow_move_constructible<table_type>::value)
0145           : table_(std::move(other.table_))
0146       {
0147       }
0148 
0149       unordered_flat_set(unordered_flat_set&& other, allocator_type const& al)
0150           : table_(std::move(other.table_), al)
0151       {
0152       }
0153 
0154       unordered_flat_set(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_set(ilist.begin(), ilist.end(), n, h, pred, a)
0159       {
0160       }
0161 
0162       unordered_flat_set(
0163         std::initializer_list<value_type> il, allocator_type const& a)
0164           : unordered_flat_set(il, size_type(0), hasher(), key_equal(), a)
0165       {
0166       }
0167 
0168       unordered_flat_set(std::initializer_list<value_type> init, size_type n,
0169         allocator_type const& a)
0170           : unordered_flat_set(init, n, hasher(), key_equal(), a)
0171       {
0172       }
0173 
0174       unordered_flat_set(std::initializer_list<value_type> init, size_type n,
0175         hasher const& h, allocator_type const& a)
0176           : unordered_flat_set(init, n, h, key_equal(), a)
0177       {
0178       }
0179 
0180       unordered_flat_set(
0181         concurrent_flat_set<Key, Hash, KeyEqual, Allocator>&& other)
0182           : table_(std::move(other.table_))
0183       {
0184       }
0185 
0186       ~unordered_flat_set() = default;
0187 
0188       unordered_flat_set& operator=(unordered_flat_set const& other)
0189       {
0190         table_ = other.table_;
0191         return *this;
0192       }
0193 
0194       unordered_flat_set& operator=(unordered_flat_set&& 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       BOOST_FORCEINLINE std::pair<iterator, bool> insert(
0235         value_type const& value)
0236       {
0237         return table_.insert(value);
0238       }
0239 
0240       BOOST_FORCEINLINE std::pair<iterator, bool> insert(value_type&& value)
0241       {
0242         return table_.insert(std::move(value));
0243       }
0244 
0245       template <class K>
0246       BOOST_FORCEINLINE typename std::enable_if<
0247         detail::transparent_non_iterable<K, unordered_flat_set>::value,
0248         std::pair<iterator, bool> >::type
0249       insert(K&& k)
0250       {
0251         return table_.try_emplace(std::forward<K>(k));
0252       }
0253 
0254       BOOST_FORCEINLINE iterator insert(const_iterator, value_type const& value)
0255       {
0256         return table_.insert(value).first;
0257       }
0258 
0259       BOOST_FORCEINLINE iterator insert(const_iterator, value_type&& value)
0260       {
0261         return table_.insert(std::move(value)).first;
0262       }
0263 
0264       template <class K>
0265       BOOST_FORCEINLINE typename std::enable_if<
0266         detail::transparent_non_iterable<K, unordered_flat_set>::value,
0267         iterator>::type
0268       insert(const_iterator, K&& k)
0269       {
0270         return table_.try_emplace(std::forward<K>(k)).first;
0271       }
0272 
0273       template <class InputIterator>
0274       void insert(InputIterator first, InputIterator last)
0275       {
0276         for (auto pos = first; pos != last; ++pos) {
0277           table_.emplace(*pos);
0278         }
0279       }
0280 
0281       void insert(std::initializer_list<value_type> ilist)
0282       {
0283         this->insert(ilist.begin(), ilist.end());
0284       }
0285 
0286       template <class... Args>
0287       BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
0288       {
0289         return table_.emplace(std::forward<Args>(args)...);
0290       }
0291 
0292       template <class... Args>
0293       BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
0294       {
0295         return table_.emplace(std::forward<Args>(args)...).first;
0296       }
0297 
0298       BOOST_FORCEINLINE typename table_type::erase_return_type erase(
0299         const_iterator pos)
0300       {
0301         return table_.erase(pos);
0302       }
0303 
0304       iterator erase(const_iterator first, const_iterator last)
0305       {
0306         while (first != last) {
0307           this->erase(first++);
0308         }
0309         return iterator{detail::foa::const_iterator_cast_tag{}, last};
0310       }
0311 
0312       BOOST_FORCEINLINE size_type erase(key_type const& key)
0313       {
0314         return table_.erase(key);
0315       }
0316 
0317       template <class K>
0318       BOOST_FORCEINLINE typename std::enable_if<
0319         detail::transparent_non_iterable<K, unordered_flat_set>::value,
0320         size_type>::type
0321       erase(K const& key)
0322       {
0323         return table_.erase(key);
0324       }
0325 
0326       void swap(unordered_flat_set& rhs) noexcept(
0327         noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
0328       {
0329         table_.swap(rhs.table_);
0330       }
0331 
0332       template <class H2, class P2>
0333       void merge(unordered_flat_set<key_type, H2, P2, allocator_type>& source)
0334       {
0335         table_.merge(source.table_);
0336       }
0337 
0338       template <class H2, class P2>
0339       void merge(unordered_flat_set<key_type, H2, P2, allocator_type>&& source)
0340       {
0341         table_.merge(std::move(source.table_));
0342       }
0343 
0344       /// Lookup
0345       ///
0346 
0347       BOOST_FORCEINLINE size_type count(key_type const& key) const
0348       {
0349         auto pos = table_.find(key);
0350         return pos != table_.end() ? 1 : 0;
0351       }
0352 
0353       template <class K>
0354       BOOST_FORCEINLINE typename std::enable_if<
0355         detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0356       count(K const& key) const
0357       {
0358         auto pos = table_.find(key);
0359         return pos != table_.end() ? 1 : 0;
0360       }
0361 
0362       BOOST_FORCEINLINE iterator find(key_type const& key)
0363       {
0364         return table_.find(key);
0365       }
0366 
0367       BOOST_FORCEINLINE const_iterator find(key_type const& key) const
0368       {
0369         return table_.find(key);
0370       }
0371 
0372       template <class K>
0373       BOOST_FORCEINLINE typename std::enable_if<
0374         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0375         iterator>::type
0376       find(K const& key)
0377       {
0378         return table_.find(key);
0379       }
0380 
0381       template <class K>
0382       BOOST_FORCEINLINE typename std::enable_if<
0383         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0384         const_iterator>::type
0385       find(K const& key) const
0386       {
0387         return table_.find(key);
0388       }
0389 
0390       BOOST_FORCEINLINE bool contains(key_type const& key) const
0391       {
0392         return this->find(key) != this->end();
0393       }
0394 
0395       template <class K>
0396       BOOST_FORCEINLINE typename std::enable_if<
0397         boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
0398         bool>::type
0399       contains(K const& key) const
0400       {
0401         return this->find(key) != this->end();
0402       }
0403 
0404       std::pair<iterator, iterator> equal_range(key_type const& key)
0405       {
0406         auto pos = table_.find(key);
0407         if (pos == table_.end()) {
0408           return {pos, pos};
0409         }
0410 
0411         auto next = pos;
0412         ++next;
0413         return {pos, next};
0414       }
0415 
0416       std::pair<const_iterator, const_iterator> equal_range(
0417         key_type const& key) const
0418       {
0419         auto pos = table_.find(key);
0420         if (pos == table_.end()) {
0421           return {pos, pos};
0422         }
0423 
0424         auto next = pos;
0425         ++next;
0426         return {pos, next};
0427       }
0428 
0429       template <class K>
0430       typename std::enable_if<
0431         detail::are_transparent<K, hasher, key_equal>::value,
0432         std::pair<iterator, iterator> >::type
0433       equal_range(K const& key)
0434       {
0435         auto pos = table_.find(key);
0436         if (pos == table_.end()) {
0437           return {pos, pos};
0438         }
0439 
0440         auto next = pos;
0441         ++next;
0442         return {pos, next};
0443       }
0444 
0445       template <class K>
0446       typename std::enable_if<
0447         detail::are_transparent<K, hasher, key_equal>::value,
0448         std::pair<const_iterator, const_iterator> >::type
0449       equal_range(K const& key) const
0450       {
0451         auto pos = table_.find(key);
0452         if (pos == table_.end()) {
0453           return {pos, pos};
0454         }
0455 
0456         auto next = pos;
0457         ++next;
0458         return {pos, next};
0459       }
0460 
0461       /// Hash Policy
0462       ///
0463 
0464       size_type bucket_count() const noexcept { return table_.capacity(); }
0465 
0466       float load_factor() const noexcept { return table_.load_factor(); }
0467 
0468       float max_load_factor() const noexcept
0469       {
0470         return table_.max_load_factor();
0471       }
0472 
0473       void max_load_factor(float) {}
0474 
0475       size_type max_load() const noexcept { return table_.max_load(); }
0476 
0477       void rehash(size_type n) { table_.rehash(n); }
0478 
0479       void reserve(size_type n) { table_.reserve(n); }
0480 
0481 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0482       /// Stats
0483       ///
0484       stats get_stats() const { return table_.get_stats(); }
0485 
0486       void reset_stats() noexcept { table_.reset_stats(); }
0487 #endif
0488 
0489       /// Observers
0490       ///
0491 
0492       hasher hash_function() const { return table_.hash_function(); }
0493 
0494       key_equal key_eq() const { return table_.key_eq(); }
0495     };
0496 
0497     template <class Key, class Hash, class KeyEqual, class Allocator>
0498     bool operator==(
0499       unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
0500       unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
0501     {
0502       return lhs.table_ == rhs.table_;
0503     }
0504 
0505     template <class Key, class Hash, class KeyEqual, class Allocator>
0506     bool operator!=(
0507       unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
0508       unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
0509     {
0510       return !(lhs == rhs);
0511     }
0512 
0513     template <class Key, class Hash, class KeyEqual, class Allocator>
0514     void swap(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& lhs,
0515       unordered_flat_set<Key, Hash, KeyEqual, Allocator>& rhs)
0516       noexcept(noexcept(lhs.swap(rhs)))
0517     {
0518       lhs.swap(rhs);
0519     }
0520 
0521     template <class Key, class Hash, class KeyEqual, class Allocator,
0522       class Pred>
0523     typename unordered_flat_set<Key, Hash, KeyEqual, Allocator>::size_type
0524     erase_if(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& set, Pred pred)
0525     {
0526       return erase_if(set.table_, pred);
0527     }
0528 
0529     template <class Archive, class Key, class Hash, class KeyEqual,
0530       class Allocator>
0531     void serialize(Archive& ar,
0532       unordered_flat_set<Key, Hash, KeyEqual, Allocator>& set,
0533       unsigned int version)
0534     {
0535       detail::serialize_container(ar, set, version);
0536     }
0537 
0538 #if defined(BOOST_MSVC)
0539 #pragma warning(pop) /* C4714 */
0540 #endif
0541 
0542 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0543     template <class InputIterator,
0544       class Hash =
0545         boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0546       class Pred =
0547         std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0548       class Allocator = std::allocator<
0549         typename std::iterator_traits<InputIterator>::value_type>,
0550       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0551       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0552       class = std::enable_if_t<detail::is_pred_v<Pred> >,
0553       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0554     unordered_flat_set(InputIterator, InputIterator,
0555       std::size_t = boost::unordered::detail::foa::default_bucket_count,
0556       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0557       -> unordered_flat_set<
0558         typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
0559         Allocator>;
0560 
0561     template <class T, class Hash = boost::hash<T>,
0562       class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
0563       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0564       class = std::enable_if_t<detail::is_pred_v<Pred> >,
0565       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0566     unordered_flat_set(std::initializer_list<T>,
0567       std::size_t = boost::unordered::detail::foa::default_bucket_count,
0568       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0569       -> unordered_flat_set<T, Hash, Pred, Allocator>;
0570 
0571     template <class InputIterator, class Allocator,
0572       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0573       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0574     unordered_flat_set(InputIterator, InputIterator, std::size_t, Allocator)
0575       -> unordered_flat_set<
0576         typename std::iterator_traits<InputIterator>::value_type,
0577         boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0578         std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0579         Allocator>;
0580 
0581     template <class InputIterator, class Hash, class Allocator,
0582       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0583       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0584       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0585     unordered_flat_set(
0586       InputIterator, InputIterator, std::size_t, Hash, Allocator)
0587       -> unordered_flat_set<
0588         typename std::iterator_traits<InputIterator>::value_type, Hash,
0589         std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0590         Allocator>;
0591 
0592     template <class T, class Allocator,
0593       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0594     unordered_flat_set(std::initializer_list<T>, std::size_t, Allocator)
0595       -> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0596 
0597     template <class T, class Hash, class Allocator,
0598       class = std::enable_if_t<detail::is_hash_v<Hash> >,
0599       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0600     unordered_flat_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
0601       -> unordered_flat_set<T, Hash, std::equal_to<T>, Allocator>;
0602 
0603     template <class InputIterator, class Allocator,
0604       class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0605       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0606     unordered_flat_set(InputIterator, InputIterator, Allocator)
0607       -> unordered_flat_set<
0608         typename std::iterator_traits<InputIterator>::value_type,
0609         boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0610         std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0611         Allocator>;
0612 
0613     template <class T, class Allocator,
0614       class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0615     unordered_flat_set(std::initializer_list<T>, Allocator)
0616       -> unordered_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0617 #endif
0618 
0619   } // namespace unordered
0620 } // namespace boost
0621 
0622 #endif