File indexing completed on 2025-09-16 08:51:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_UNORDERED_CONCURRENT_FLAT_SET_HPP
0013 #define BOOST_UNORDERED_CONCURRENT_FLAT_SET_HPP
0014
0015 #include <boost/unordered/concurrent_flat_set_fwd.hpp>
0016 #include <boost/unordered/detail/concurrent_static_asserts.hpp>
0017 #include <boost/unordered/detail/foa/concurrent_table.hpp>
0018 #include <boost/unordered/detail/foa/flat_set_types.hpp>
0019 #include <boost/unordered/detail/type_traits.hpp>
0020 #include <boost/unordered/unordered_flat_set_fwd.hpp>
0021
0022 #include <boost/container_hash/hash.hpp>
0023 #include <boost/core/allocator_access.hpp>
0024 #include <boost/core/serialization.hpp>
0025
0026 #include <utility>
0027
0028 namespace boost {
0029 namespace unordered {
0030 template <class Key, class Hash, class Pred, class Allocator>
0031 class concurrent_flat_set
0032 {
0033 private:
0034 template <class Key2, class Hash2, class Pred2, class Allocator2>
0035 friend class concurrent_flat_set;
0036 template <class Key2, class Hash2, class Pred2, class Allocator2>
0037 friend class unordered_flat_set;
0038
0039 using type_policy = detail::foa::flat_set_types<Key>;
0040
0041 using table_type =
0042 detail::foa::concurrent_table<type_policy, Hash, Pred, Allocator>;
0043
0044 table_type table_;
0045
0046 template <class K, class H, class KE, class A>
0047 bool friend operator==(concurrent_flat_set<K, H, KE, A> const& lhs,
0048 concurrent_flat_set<K, H, KE, A> const& rhs);
0049
0050 template <class K, class H, class KE, class A, class Predicate>
0051 friend typename concurrent_flat_set<K, H, KE, A>::size_type erase_if(
0052 concurrent_flat_set<K, H, KE, A>& set, Predicate pred);
0053
0054 template<class Archive, class K, class H, class KE, class A>
0055 friend void serialize(
0056 Archive& ar, concurrent_flat_set<K, H, KE, A>& c,
0057 unsigned int version);
0058
0059 public:
0060 using key_type = Key;
0061 using value_type = typename type_policy::value_type;
0062 using init_type = typename type_policy::init_type;
0063 using size_type = std::size_t;
0064 using difference_type = std::ptrdiff_t;
0065 using hasher = typename boost::unordered::detail::type_identity<Hash>::type;
0066 using key_equal = typename boost::unordered::detail::type_identity<Pred>::type;
0067 using allocator_type = typename boost::unordered::detail::type_identity<Allocator>::type;
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 static constexpr size_type bulk_visit_size = table_type::bulk_visit_size;
0074
0075 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0076 using stats = typename table_type::stats;
0077 #endif
0078
0079 concurrent_flat_set()
0080 : concurrent_flat_set(detail::foa::default_bucket_count)
0081 {
0082 }
0083
0084 explicit concurrent_flat_set(size_type n, const hasher& hf = hasher(),
0085 const key_equal& eql = key_equal(),
0086 const allocator_type& a = allocator_type())
0087 : table_(n, hf, eql, a)
0088 {
0089 }
0090
0091 template <class InputIterator>
0092 concurrent_flat_set(InputIterator f, InputIterator l,
0093 size_type n = detail::foa::default_bucket_count,
0094 const hasher& hf = hasher(), const key_equal& eql = key_equal(),
0095 const allocator_type& a = allocator_type())
0096 : table_(n, hf, eql, a)
0097 {
0098 this->insert(f, l);
0099 }
0100
0101 concurrent_flat_set(concurrent_flat_set const& rhs)
0102 : table_(rhs.table_,
0103 boost::allocator_select_on_container_copy_construction(
0104 rhs.get_allocator()))
0105 {
0106 }
0107
0108 concurrent_flat_set(concurrent_flat_set&& rhs)
0109 : table_(std::move(rhs.table_))
0110 {
0111 }
0112
0113 template <class InputIterator>
0114 concurrent_flat_set(
0115 InputIterator f, InputIterator l, allocator_type const& a)
0116 : concurrent_flat_set(f, l, 0, hasher(), key_equal(), a)
0117 {
0118 }
0119
0120 explicit concurrent_flat_set(allocator_type const& a)
0121 : table_(detail::foa::default_bucket_count, hasher(), key_equal(), a)
0122 {
0123 }
0124
0125 concurrent_flat_set(
0126 concurrent_flat_set const& rhs, allocator_type const& a)
0127 : table_(rhs.table_, a)
0128 {
0129 }
0130
0131 concurrent_flat_set(concurrent_flat_set&& rhs, allocator_type const& a)
0132 : table_(std::move(rhs.table_), a)
0133 {
0134 }
0135
0136 concurrent_flat_set(std::initializer_list<value_type> il,
0137 size_type n = detail::foa::default_bucket_count,
0138 const hasher& hf = hasher(), const key_equal& eql = key_equal(),
0139 const allocator_type& a = allocator_type())
0140 : concurrent_flat_set(n, hf, eql, a)
0141 {
0142 this->insert(il.begin(), il.end());
0143 }
0144
0145 concurrent_flat_set(size_type n, const allocator_type& a)
0146 : concurrent_flat_set(n, hasher(), key_equal(), a)
0147 {
0148 }
0149
0150 concurrent_flat_set(
0151 size_type n, const hasher& hf, const allocator_type& a)
0152 : concurrent_flat_set(n, hf, key_equal(), a)
0153 {
0154 }
0155
0156 template <typename InputIterator>
0157 concurrent_flat_set(
0158 InputIterator f, InputIterator l, size_type n, const allocator_type& a)
0159 : concurrent_flat_set(f, l, n, hasher(), key_equal(), a)
0160 {
0161 }
0162
0163 template <typename InputIterator>
0164 concurrent_flat_set(InputIterator f, InputIterator l, size_type n,
0165 const hasher& hf, const allocator_type& a)
0166 : concurrent_flat_set(f, l, n, hf, key_equal(), a)
0167 {
0168 }
0169
0170 concurrent_flat_set(
0171 std::initializer_list<value_type> il, const allocator_type& a)
0172 : concurrent_flat_set(
0173 il, detail::foa::default_bucket_count, hasher(), key_equal(), a)
0174 {
0175 }
0176
0177 concurrent_flat_set(std::initializer_list<value_type> il, size_type n,
0178 const allocator_type& a)
0179 : concurrent_flat_set(il, n, hasher(), key_equal(), a)
0180 {
0181 }
0182
0183 concurrent_flat_set(std::initializer_list<value_type> il, size_type n,
0184 const hasher& hf, const allocator_type& a)
0185 : concurrent_flat_set(il, n, hf, key_equal(), a)
0186 {
0187 }
0188
0189
0190 template <bool avoid_explicit_instantiation = true>
0191 concurrent_flat_set(
0192 unordered_flat_set<Key, Hash, Pred, Allocator>&& other)
0193 : table_(std::move(other.table_))
0194 {
0195 }
0196
0197 ~concurrent_flat_set() = default;
0198
0199 concurrent_flat_set& operator=(concurrent_flat_set const& rhs)
0200 {
0201 table_ = rhs.table_;
0202 return *this;
0203 }
0204
0205 concurrent_flat_set& operator=(concurrent_flat_set&& rhs)
0206 noexcept(boost::allocator_is_always_equal<Allocator>::type::value ||
0207 boost::allocator_propagate_on_container_move_assignment<
0208 Allocator>::type::value)
0209 {
0210 table_ = std::move(rhs.table_);
0211 return *this;
0212 }
0213
0214 concurrent_flat_set& operator=(std::initializer_list<value_type> ilist)
0215 {
0216 table_ = ilist;
0217 return *this;
0218 }
0219
0220
0221
0222
0223 size_type size() const noexcept { return table_.size(); }
0224 size_type max_size() const noexcept { return table_.max_size(); }
0225
0226 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0227 {
0228 return size() == 0;
0229 }
0230
0231 template <class F>
0232 BOOST_FORCEINLINE size_type visit(key_type const& k, F f)
0233 {
0234 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0235 return table_.visit(k, f);
0236 }
0237
0238 template <class F>
0239 BOOST_FORCEINLINE size_type visit(key_type const& k, F f) const
0240 {
0241 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0242 return table_.visit(k, f);
0243 }
0244
0245 template <class F>
0246 BOOST_FORCEINLINE size_type cvisit(key_type const& k, F f) const
0247 {
0248 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0249 return table_.visit(k, f);
0250 }
0251
0252 template <class K, class F>
0253 BOOST_FORCEINLINE typename std::enable_if<
0254 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0255 visit(K&& k, F f)
0256 {
0257 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0258 return table_.visit(std::forward<K>(k), f);
0259 }
0260
0261 template <class K, class F>
0262 BOOST_FORCEINLINE typename std::enable_if<
0263 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0264 visit(K&& k, F f) const
0265 {
0266 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0267 return table_.visit(std::forward<K>(k), f);
0268 }
0269
0270 template <class K, class F>
0271 BOOST_FORCEINLINE typename std::enable_if<
0272 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0273 cvisit(K&& k, F f) const
0274 {
0275 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0276 return table_.visit(std::forward<K>(k), f);
0277 }
0278
0279 template<class FwdIterator, class F>
0280 BOOST_FORCEINLINE
0281 size_t visit(FwdIterator first, FwdIterator last, F f)
0282 {
0283 BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
0284 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0285 return table_.visit(first, last, f);
0286 }
0287
0288 template<class FwdIterator, class F>
0289 BOOST_FORCEINLINE
0290 size_t visit(FwdIterator first, FwdIterator last, F f) const
0291 {
0292 BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
0293 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0294 return table_.visit(first, last, f);
0295 }
0296
0297 template<class FwdIterator, class F>
0298 BOOST_FORCEINLINE
0299 size_t cvisit(FwdIterator first, FwdIterator last, F f) const
0300 {
0301 BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
0302 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0303 return table_.visit(first, last, f);
0304 }
0305
0306 template <class F> size_type visit_all(F f)
0307 {
0308 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0309 return table_.visit_all(f);
0310 }
0311
0312 template <class F> size_type visit_all(F f) const
0313 {
0314 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0315 return table_.visit_all(f);
0316 }
0317
0318 template <class F> size_type cvisit_all(F f) const
0319 {
0320 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0321 return table_.cvisit_all(f);
0322 }
0323
0324 #if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
0325 template <class ExecPolicy, class F>
0326 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0327 void>::type
0328 visit_all(ExecPolicy&& p, F f)
0329 {
0330 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0331 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0332 table_.visit_all(p, f);
0333 }
0334
0335 template <class ExecPolicy, class F>
0336 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0337 void>::type
0338 visit_all(ExecPolicy&& p, F f) const
0339 {
0340 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0341 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0342 table_.visit_all(p, f);
0343 }
0344
0345 template <class ExecPolicy, class F>
0346 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0347 void>::type
0348 cvisit_all(ExecPolicy&& p, F f) const
0349 {
0350 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0351 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0352 table_.cvisit_all(p, f);
0353 }
0354 #endif
0355
0356 template <class F> bool visit_while(F f)
0357 {
0358 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0359 return table_.visit_while(f);
0360 }
0361
0362 template <class F> bool visit_while(F f) const
0363 {
0364 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0365 return table_.visit_while(f);
0366 }
0367
0368 template <class F> bool cvisit_while(F f) const
0369 {
0370 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0371 return table_.cvisit_while(f);
0372 }
0373
0374 #if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
0375 template <class ExecPolicy, class F>
0376 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0377 bool>::type
0378 visit_while(ExecPolicy&& p, F f)
0379 {
0380 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0381 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0382 return table_.visit_while(p, f);
0383 }
0384
0385 template <class ExecPolicy, class F>
0386 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0387 bool>::type
0388 visit_while(ExecPolicy&& p, F f) const
0389 {
0390 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0391 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0392 return table_.visit_while(p, f);
0393 }
0394
0395 template <class ExecPolicy, class F>
0396 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0397 bool>::type
0398 cvisit_while(ExecPolicy&& p, F f) const
0399 {
0400 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0401 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0402 return table_.cvisit_while(p, f);
0403 }
0404 #endif
0405
0406
0407
0408
0409 BOOST_FORCEINLINE bool insert(value_type const& obj)
0410 {
0411 return table_.insert(obj);
0412 }
0413
0414 BOOST_FORCEINLINE bool insert(value_type&& obj)
0415 {
0416 return table_.insert(std::move(obj));
0417 }
0418
0419 template <class K>
0420 BOOST_FORCEINLINE typename std::enable_if<
0421 detail::are_transparent<K, hasher, key_equal>::value,
0422 bool >::type
0423 insert(K&& k)
0424 {
0425 return table_.try_emplace(std::forward<K>(k));
0426 }
0427
0428 template <class InputIterator>
0429 size_type insert(InputIterator begin, InputIterator end)
0430 {
0431 size_type count_elements = 0;
0432 for (auto pos = begin; pos != end; ++pos, ++count_elements) {
0433 table_.emplace(*pos);
0434 }
0435 return count_elements;
0436 }
0437
0438 size_type insert(std::initializer_list<value_type> ilist)
0439 {
0440 return this->insert(ilist.begin(), ilist.end());
0441 }
0442
0443 template <class F>
0444 BOOST_FORCEINLINE bool insert_or_visit(value_type const& obj, F f)
0445 {
0446 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0447 return table_.insert_or_visit(obj, f);
0448 }
0449
0450 template <class F>
0451 BOOST_FORCEINLINE bool insert_or_visit(value_type&& obj, F f)
0452 {
0453 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0454 return table_.insert_or_visit(std::move(obj), f);
0455 }
0456
0457 template <class K, class F>
0458 BOOST_FORCEINLINE typename std::enable_if<
0459 detail::are_transparent<K, hasher, key_equal>::value,
0460 bool >::type
0461 insert_or_visit(K&& k, F f)
0462 {
0463 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0464 return table_.try_emplace_or_visit(std::forward<K>(k), f);
0465 }
0466
0467 template <class InputIterator, class F>
0468 size_type insert_or_visit(InputIterator first, InputIterator last, F f)
0469 {
0470 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0471 size_type count_elements = 0;
0472 for (; first != last; ++first, ++count_elements) {
0473 table_.emplace_or_visit(*first, f);
0474 }
0475 return count_elements;
0476 }
0477
0478 template <class F>
0479 size_type insert_or_visit(std::initializer_list<value_type> ilist, F f)
0480 {
0481 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0482 return this->insert_or_visit(ilist.begin(), ilist.end(), std::ref(f));
0483 }
0484
0485 template <class F>
0486 BOOST_FORCEINLINE bool insert_or_cvisit(value_type const& obj, F f)
0487 {
0488 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0489 return table_.insert_or_cvisit(obj, f);
0490 }
0491
0492 template <class F>
0493 BOOST_FORCEINLINE bool insert_or_cvisit(value_type&& obj, F f)
0494 {
0495 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0496 return table_.insert_or_cvisit(std::move(obj), f);
0497 }
0498
0499 template <class K, class F>
0500 BOOST_FORCEINLINE typename std::enable_if<
0501 detail::are_transparent<K, hasher, key_equal>::value,
0502 bool >::type
0503 insert_or_cvisit(K&& k, F f)
0504 {
0505 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0506 return table_.try_emplace_or_cvisit(std::forward<K>(k), f);
0507 }
0508
0509 template <class InputIterator, class F>
0510 size_type insert_or_cvisit(InputIterator first, InputIterator last, F f)
0511 {
0512 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0513 size_type count_elements = 0;
0514 for (; first != last; ++first, ++count_elements) {
0515 table_.emplace_or_cvisit(*first, f);
0516 }
0517 return count_elements;
0518 }
0519
0520 template <class F>
0521 size_type insert_or_cvisit(std::initializer_list<value_type> ilist, F f)
0522 {
0523 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0524 return this->insert_or_cvisit(ilist.begin(), ilist.end(), std::ref(f));
0525 }
0526
0527 template <class F1, class F2>
0528 BOOST_FORCEINLINE bool insert_and_visit(
0529 value_type const& obj, F1 f1, F2 f2)
0530 {
0531 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0532 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0533 return table_.insert_and_visit(obj, f1, f2);
0534 }
0535
0536 template <class F1, class F2>
0537 BOOST_FORCEINLINE bool insert_and_visit(value_type&& obj, F1 f1, F2 f2)
0538 {
0539 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0540 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0541 return table_.insert_and_visit(std::move(obj), f1, f2);
0542 }
0543
0544 template <class K, class F1, class F2>
0545 BOOST_FORCEINLINE typename std::enable_if<
0546 detail::are_transparent<K, hasher, key_equal>::value,
0547 bool >::type
0548 insert_and_visit(K&& k, F1 f1, F2 f2)
0549 {
0550 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0551 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0552 return table_.try_emplace_and_visit(std::forward<K>(k), f1, f2);
0553 }
0554
0555 template <class InputIterator, class F1, class F2>
0556 size_type insert_and_visit(
0557 InputIterator first, InputIterator last, F1 f1, F2 f2)
0558 {
0559 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0560 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0561 size_type count_elements = 0;
0562 for (; first != last; ++first, ++count_elements) {
0563 table_.emplace_and_visit(*first, f1, f2);
0564 }
0565 return count_elements;
0566 }
0567
0568 template <class F1, class F2>
0569 size_type insert_and_visit(std::initializer_list<value_type> ilist, F1 f1, F2 f2)
0570 {
0571 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0572 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0573 return this->insert_and_visit(
0574 ilist.begin(), ilist.end(), std::ref(f1), std::ref(f2));
0575 }
0576
0577 template <class F1, class F2>
0578 BOOST_FORCEINLINE bool insert_and_cvisit(
0579 value_type const& obj, F1 f1, F2 f2)
0580 {
0581 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0582 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0583 return table_.insert_and_cvisit(obj, f1, f2);
0584 }
0585
0586 template <class F1, class F2>
0587 BOOST_FORCEINLINE bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2)
0588 {
0589 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0590 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0591 return table_.insert_and_cvisit(std::move(obj), f1, f2);
0592 }
0593
0594 template <class K, class F1, class F2>
0595 BOOST_FORCEINLINE typename std::enable_if<
0596 detail::are_transparent<K, hasher, key_equal>::value,
0597 bool >::type
0598 insert_and_cvisit(K&& k, F1 f1, F2 f2)
0599 {
0600 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0601 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0602 return table_.try_emplace_and_cvisit(std::forward<K>(k), f1, f2);
0603 }
0604
0605 template <class InputIterator, class F1, class F2>
0606 size_type insert_and_cvisit(
0607 InputIterator first, InputIterator last, F1 f1, F2 f2)
0608 {
0609 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0610 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0611 size_type count_elements = 0;
0612 for (; first != last; ++first, ++count_elements) {
0613 table_.emplace_and_cvisit(*first, f1, f2);
0614 }
0615 return count_elements;
0616 }
0617
0618 template <class F1, class F2>
0619 size_type insert_and_cvisit(
0620 std::initializer_list<value_type> ilist, F1 f1, F2 f2)
0621 {
0622 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F1)
0623 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F2)
0624 return this->insert_and_cvisit(
0625 ilist.begin(), ilist.end(), std::ref(f1), std::ref(f2));
0626 }
0627
0628 template <class... Args> BOOST_FORCEINLINE bool emplace(Args&&... args)
0629 {
0630 return table_.emplace(std::forward<Args>(args)...);
0631 }
0632
0633 template <class Arg, class... Args>
0634 BOOST_FORCEINLINE bool emplace_or_visit(Arg&& arg, Args&&... args)
0635 {
0636 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0637 return table_.emplace_or_visit(
0638 std::forward<Arg>(arg), std::forward<Args>(args)...);
0639 }
0640
0641 template <class Arg, class... Args>
0642 BOOST_FORCEINLINE bool emplace_or_cvisit(Arg&& arg, Args&&... args)
0643 {
0644 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0645 return table_.emplace_or_cvisit(
0646 std::forward<Arg>(arg), std::forward<Args>(args)...);
0647 }
0648
0649 template <class Arg1, class Arg2, class... Args>
0650 BOOST_FORCEINLINE bool emplace_and_visit(
0651 Arg1&& arg1, Arg2&& arg2, Args&&... args)
0652 {
0653 BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_CONST_INVOCABLE(
0654 Arg1, Arg2, Args...)
0655 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
0656 return table_.emplace_and_visit(
0657 std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
0658 std::forward<Args>(args)...);
0659 }
0660
0661 template <class Arg1, class Arg2, class... Args>
0662 BOOST_FORCEINLINE bool emplace_and_cvisit(
0663 Arg1&& arg1, Arg2&& arg2, Args&&... args)
0664 {
0665 BOOST_UNORDERED_STATIC_ASSERT_PENULTIMATE_ARG_CONST_INVOCABLE(
0666 Arg1, Arg2, Args...)
0667 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg2, Args...)
0668 return table_.emplace_and_cvisit(
0669 std::forward<Arg1>(arg1), std::forward<Arg2>(arg2),
0670 std::forward<Args>(args)...);
0671 }
0672
0673 BOOST_FORCEINLINE size_type erase(key_type const& k)
0674 {
0675 return table_.erase(k);
0676 }
0677
0678 template <class K>
0679 BOOST_FORCEINLINE typename std::enable_if<
0680 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0681 erase(K&& k)
0682 {
0683 return table_.erase(std::forward<K>(k));
0684 }
0685
0686 template <class F>
0687 BOOST_FORCEINLINE size_type erase_if(key_type const& k, F f)
0688 {
0689 return table_.erase_if(k, f);
0690 }
0691
0692 template <class K, class F>
0693 BOOST_FORCEINLINE typename std::enable_if<
0694 detail::are_transparent<K, hasher, key_equal>::value &&
0695 !detail::is_execution_policy<K>::value,
0696 size_type>::type
0697 erase_if(K&& k, F f)
0698 {
0699 return table_.erase_if(std::forward<K>(k), f);
0700 }
0701
0702 #if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
0703 template <class ExecPolicy, class F>
0704 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0705 void>::type
0706 erase_if(ExecPolicy&& p, F f)
0707 {
0708 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0709 table_.erase_if(p, f);
0710 }
0711 #endif
0712
0713 template <class F> size_type erase_if(F f) { return table_.erase_if(f); }
0714
0715 void swap(concurrent_flat_set& other) noexcept(
0716 boost::allocator_is_always_equal<Allocator>::type::value ||
0717 boost::allocator_propagate_on_container_swap<Allocator>::type::value)
0718 {
0719 return table_.swap(other.table_);
0720 }
0721
0722 void clear() noexcept { table_.clear(); }
0723
0724 template <typename H2, typename P2>
0725 size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>& x)
0726 {
0727 BOOST_ASSERT(get_allocator() == x.get_allocator());
0728 return table_.merge(x.table_);
0729 }
0730
0731 template <typename H2, typename P2>
0732 size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>&& x)
0733 {
0734 return merge(x);
0735 }
0736
0737 BOOST_FORCEINLINE size_type count(key_type const& k) const
0738 {
0739 return table_.count(k);
0740 }
0741
0742 template <class K>
0743 BOOST_FORCEINLINE typename std::enable_if<
0744 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0745 count(K const& k)
0746 {
0747 return table_.count(k);
0748 }
0749
0750 BOOST_FORCEINLINE bool contains(key_type const& k) const
0751 {
0752 return table_.contains(k);
0753 }
0754
0755 template <class K>
0756 BOOST_FORCEINLINE typename std::enable_if<
0757 detail::are_transparent<K, hasher, key_equal>::value, bool>::type
0758 contains(K const& k) const
0759 {
0760 return table_.contains(k);
0761 }
0762
0763
0764
0765 size_type bucket_count() const noexcept { return table_.capacity(); }
0766
0767 float load_factor() const noexcept { return table_.load_factor(); }
0768 float max_load_factor() const noexcept
0769 {
0770 return table_.max_load_factor();
0771 }
0772 void max_load_factor(float) {}
0773 size_type max_load() const noexcept { return table_.max_load(); }
0774
0775 void rehash(size_type n) { table_.rehash(n); }
0776 void reserve(size_type n) { table_.reserve(n); }
0777
0778 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0779
0780
0781 stats get_stats() const { return table_.get_stats(); }
0782
0783 void reset_stats() noexcept { table_.reset_stats(); }
0784 #endif
0785
0786
0787
0788 allocator_type get_allocator() const noexcept
0789 {
0790 return table_.get_allocator();
0791 }
0792
0793 hasher hash_function() const { return table_.hash_function(); }
0794 key_equal key_eq() const { return table_.key_eq(); }
0795 };
0796
0797 template <class Key, class Hash, class KeyEqual, class Allocator>
0798 bool operator==(
0799 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
0800 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
0801 {
0802 return lhs.table_ == rhs.table_;
0803 }
0804
0805 template <class Key, class Hash, class KeyEqual, class Allocator>
0806 bool operator!=(
0807 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
0808 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
0809 {
0810 return !(lhs == rhs);
0811 }
0812
0813 template <class Key, class Hash, class Pred, class Alloc>
0814 void swap(concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
0815 concurrent_flat_set<Key, Hash, Pred, Alloc>& y)
0816 noexcept(noexcept(x.swap(y)))
0817 {
0818 x.swap(y);
0819 }
0820
0821 template <class K, class H, class P, class A, class Predicate>
0822 typename concurrent_flat_set<K, H, P, A>::size_type erase_if(
0823 concurrent_flat_set<K, H, P, A>& c, Predicate pred)
0824 {
0825 return c.table_.erase_if(pred);
0826 }
0827
0828 template<class Archive, class K, class H, class KE, class A>
0829 void serialize(
0830 Archive& ar, concurrent_flat_set<K, H, KE, A>& c, unsigned int)
0831 {
0832 ar & core::make_nvp("table",c.table_);
0833 }
0834
0835 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0836
0837 template <class InputIterator,
0838 class Hash =
0839 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0840 class Pred =
0841 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0842 class Allocator = std::allocator<
0843 typename std::iterator_traits<InputIterator>::value_type>,
0844 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0845 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0846 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0847 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0848 concurrent_flat_set(InputIterator, InputIterator,
0849 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0850 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0851 -> concurrent_flat_set<
0852 typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
0853 Allocator>;
0854
0855 template <class T, class Hash = boost::hash<T>,
0856 class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
0857 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0858 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0859 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0860 concurrent_flat_set(std::initializer_list<T>,
0861 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0862 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0863 -> concurrent_flat_set< T, Hash, Pred, Allocator>;
0864
0865 template <class InputIterator, class Allocator,
0866 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0867 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0868 concurrent_flat_set(InputIterator, InputIterator, std::size_t, Allocator)
0869 -> concurrent_flat_set<
0870 typename std::iterator_traits<InputIterator>::value_type,
0871 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0872 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0873 Allocator>;
0874
0875 template <class InputIterator, class Allocator,
0876 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0877 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0878 concurrent_flat_set(InputIterator, InputIterator, Allocator)
0879 -> concurrent_flat_set<
0880 typename std::iterator_traits<InputIterator>::value_type,
0881 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0882 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0883 Allocator>;
0884
0885 template <class InputIterator, class Hash, class Allocator,
0886 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0887 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0888 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0889 concurrent_flat_set(
0890 InputIterator, InputIterator, std::size_t, Hash, Allocator)
0891 -> concurrent_flat_set<
0892 typename std::iterator_traits<InputIterator>::value_type, Hash,
0893 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0894 Allocator>;
0895
0896 template <class T, class Allocator,
0897 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0898 concurrent_flat_set(std::initializer_list<T>, std::size_t, Allocator)
0899 -> concurrent_flat_set<T, boost::hash<T>,std::equal_to<T>, Allocator>;
0900
0901 template <class T, class Allocator,
0902 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0903 concurrent_flat_set(std::initializer_list<T >, Allocator)
0904 -> concurrent_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0905
0906 template <class T, class Hash, class Allocator,
0907 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0908 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0909 concurrent_flat_set(std::initializer_list<T >, std::size_t,Hash, Allocator)
0910 -> concurrent_flat_set<T, Hash, std::equal_to<T>, Allocator>;
0911
0912 #endif
0913
0914 }
0915 }
0916
0917 #endif