Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:01:57

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