File indexing completed on 2025-01-30 10:01:57
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 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
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
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
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
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
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
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)
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 }
0608 }
0609
0610 #endif