Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:53:53

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