File indexing completed on 2025-07-15 08:51:09
0001
0002
0003
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)
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
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
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
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
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
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
0483
0484 stats get_stats() const { return table_.get_stats(); }
0485
0486 void reset_stats() noexcept { table_.reset_stats(); }
0487 #endif
0488
0489
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)
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 }
0620 }
0621
0622 #endif