File indexing completed on 2025-07-15 08:51:09
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 concurrent_flat_set(
0191 unordered_flat_set<Key, Hash, Pred, Allocator>&& other)
0192 : table_(std::move(other.table_))
0193 {
0194 }
0195
0196 ~concurrent_flat_set() = default;
0197
0198 concurrent_flat_set& operator=(concurrent_flat_set const& rhs)
0199 {
0200 table_ = rhs.table_;
0201 return *this;
0202 }
0203
0204 concurrent_flat_set& operator=(concurrent_flat_set&& rhs)
0205 noexcept(boost::allocator_is_always_equal<Allocator>::type::value ||
0206 boost::allocator_propagate_on_container_move_assignment<
0207 Allocator>::type::value)
0208 {
0209 table_ = std::move(rhs.table_);
0210 return *this;
0211 }
0212
0213 concurrent_flat_set& operator=(std::initializer_list<value_type> ilist)
0214 {
0215 table_ = ilist;
0216 return *this;
0217 }
0218
0219
0220
0221
0222 size_type size() const noexcept { return table_.size(); }
0223 size_type max_size() const noexcept { return table_.max_size(); }
0224
0225 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0226 {
0227 return size() == 0;
0228 }
0229
0230 template <class F>
0231 BOOST_FORCEINLINE size_type visit(key_type const& k, F f) const
0232 {
0233 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0234 return table_.visit(k, f);
0235 }
0236
0237 template <class F>
0238 BOOST_FORCEINLINE size_type cvisit(key_type const& k, F f) const
0239 {
0240 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0241 return table_.visit(k, f);
0242 }
0243
0244 template <class K, class F>
0245 BOOST_FORCEINLINE typename std::enable_if<
0246 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0247 visit(K&& k, F f) const
0248 {
0249 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0250 return table_.visit(std::forward<K>(k), f);
0251 }
0252
0253 template <class K, class F>
0254 BOOST_FORCEINLINE typename std::enable_if<
0255 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0256 cvisit(K&& k, F f) const
0257 {
0258 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0259 return table_.visit(std::forward<K>(k), f);
0260 }
0261
0262 template<class FwdIterator, class F>
0263 BOOST_FORCEINLINE
0264 size_t visit(FwdIterator first, FwdIterator last, F f) const
0265 {
0266 BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
0267 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0268 return table_.visit(first, last, f);
0269 }
0270
0271 template<class FwdIterator, class F>
0272 BOOST_FORCEINLINE
0273 size_t cvisit(FwdIterator first, FwdIterator last, F f) const
0274 {
0275 BOOST_UNORDERED_STATIC_ASSERT_BULK_VISIT_ITERATOR(FwdIterator)
0276 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0277 return table_.visit(first, last, f);
0278 }
0279
0280 template <class F> size_type visit_all(F f) const
0281 {
0282 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0283 return table_.visit_all(f);
0284 }
0285
0286 template <class F> size_type cvisit_all(F f) const
0287 {
0288 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0289 return table_.cvisit_all(f);
0290 }
0291
0292 #if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
0293 template <class ExecPolicy, class F>
0294 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0295 void>::type
0296 visit_all(ExecPolicy&& p, F f) const
0297 {
0298 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0299 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0300 table_.visit_all(p, f);
0301 }
0302
0303 template <class ExecPolicy, class F>
0304 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0305 void>::type
0306 cvisit_all(ExecPolicy&& p, F f) const
0307 {
0308 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0309 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0310 table_.cvisit_all(p, f);
0311 }
0312 #endif
0313
0314 template <class F> bool visit_while(F f) const
0315 {
0316 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0317 return table_.visit_while(f);
0318 }
0319
0320 template <class F> bool cvisit_while(F f) const
0321 {
0322 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0323 return table_.cvisit_while(f);
0324 }
0325
0326 #if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
0327 template <class ExecPolicy, class F>
0328 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0329 bool>::type
0330 visit_while(ExecPolicy&& p, F f) const
0331 {
0332 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0333 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0334 return table_.visit_while(p, f);
0335 }
0336
0337 template <class ExecPolicy, class F>
0338 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0339 bool>::type
0340 cvisit_while(ExecPolicy&& p, F f) const
0341 {
0342 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0343 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0344 return table_.cvisit_while(p, f);
0345 }
0346 #endif
0347
0348
0349
0350
0351 BOOST_FORCEINLINE bool insert(value_type const& obj)
0352 {
0353 return table_.insert(obj);
0354 }
0355
0356 BOOST_FORCEINLINE bool insert(value_type&& obj)
0357 {
0358 return table_.insert(std::move(obj));
0359 }
0360
0361 template <class K>
0362 BOOST_FORCEINLINE typename std::enable_if<
0363 detail::are_transparent<K, hasher, key_equal>::value,
0364 bool >::type
0365 insert(K&& k)
0366 {
0367 return table_.try_emplace(std::forward<K>(k));
0368 }
0369
0370 template <class InputIterator>
0371 void insert(InputIterator begin, InputIterator end)
0372 {
0373 for (auto pos = begin; pos != end; ++pos) {
0374 table_.emplace(*pos);
0375 }
0376 }
0377
0378 void insert(std::initializer_list<value_type> ilist)
0379 {
0380 this->insert(ilist.begin(), ilist.end());
0381 }
0382
0383 template <class F>
0384 BOOST_FORCEINLINE bool insert_or_visit(value_type const& obj, F f)
0385 {
0386 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0387 return table_.insert_or_cvisit(obj, f);
0388 }
0389
0390 template <class F>
0391 BOOST_FORCEINLINE bool insert_or_visit(value_type&& obj, F f)
0392 {
0393 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0394 return table_.insert_or_cvisit(std::move(obj), f);
0395 }
0396
0397 template <class K, class F>
0398 BOOST_FORCEINLINE typename std::enable_if<
0399 detail::are_transparent<K, hasher, key_equal>::value,
0400 bool >::type
0401 insert_or_visit(K&& k, F f)
0402 {
0403 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0404 return table_.try_emplace_or_cvisit(std::forward<K>(k), f);
0405 }
0406
0407 template <class InputIterator, class F>
0408 void insert_or_visit(InputIterator first, InputIterator last, F f)
0409 {
0410 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0411 for (; first != last; ++first) {
0412 table_.emplace_or_cvisit(*first, f);
0413 }
0414 }
0415
0416 template <class F>
0417 void insert_or_visit(std::initializer_list<value_type> ilist, F f)
0418 {
0419 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0420 this->insert_or_cvisit(ilist.begin(), ilist.end(), f);
0421 }
0422
0423 template <class F>
0424 BOOST_FORCEINLINE bool insert_or_cvisit(value_type const& obj, F f)
0425 {
0426 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0427 return table_.insert_or_cvisit(obj, f);
0428 }
0429
0430 template <class F>
0431 BOOST_FORCEINLINE bool insert_or_cvisit(value_type&& obj, F f)
0432 {
0433 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0434 return table_.insert_or_cvisit(std::move(obj), f);
0435 }
0436
0437 template <class K, class F>
0438 BOOST_FORCEINLINE typename std::enable_if<
0439 detail::are_transparent<K, hasher, key_equal>::value,
0440 bool >::type
0441 insert_or_cvisit(K&& k, F f)
0442 {
0443 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0444 return table_.try_emplace_or_cvisit(std::forward<K>(k), f);
0445 }
0446
0447 template <class InputIterator, class F>
0448 void insert_or_cvisit(InputIterator first, InputIterator last, F f)
0449 {
0450 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0451 for (; first != last; ++first) {
0452 table_.emplace_or_cvisit(*first, f);
0453 }
0454 }
0455
0456 template <class F>
0457 void insert_or_cvisit(std::initializer_list<value_type> ilist, F f)
0458 {
0459 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0460 this->insert_or_cvisit(ilist.begin(), ilist.end(), f);
0461 }
0462
0463 template <class... Args> BOOST_FORCEINLINE bool emplace(Args&&... args)
0464 {
0465 return table_.emplace(std::forward<Args>(args)...);
0466 }
0467
0468 template <class Arg, class... Args>
0469 BOOST_FORCEINLINE bool emplace_or_visit(Arg&& arg, Args&&... args)
0470 {
0471 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0472 return table_.emplace_or_cvisit(
0473 std::forward<Arg>(arg), std::forward<Args>(args)...);
0474 }
0475
0476 template <class Arg, class... Args>
0477 BOOST_FORCEINLINE bool emplace_or_cvisit(Arg&& arg, Args&&... args)
0478 {
0479 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0480 return table_.emplace_or_cvisit(
0481 std::forward<Arg>(arg), std::forward<Args>(args)...);
0482 }
0483
0484 BOOST_FORCEINLINE size_type erase(key_type const& k)
0485 {
0486 return table_.erase(k);
0487 }
0488
0489 template <class K>
0490 BOOST_FORCEINLINE typename std::enable_if<
0491 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0492 erase(K&& k)
0493 {
0494 return table_.erase(std::forward<K>(k));
0495 }
0496
0497 template <class F>
0498 BOOST_FORCEINLINE size_type erase_if(key_type const& k, F f)
0499 {
0500 return table_.erase_if(k, f);
0501 }
0502
0503 template <class K, class F>
0504 BOOST_FORCEINLINE typename std::enable_if<
0505 detail::are_transparent<K, hasher, key_equal>::value &&
0506 !detail::is_execution_policy<K>::value,
0507 size_type>::type
0508 erase_if(K&& k, F f)
0509 {
0510 return table_.erase_if(std::forward<K>(k), f);
0511 }
0512
0513 #if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
0514 template <class ExecPolicy, class F>
0515 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0516 void>::type
0517 erase_if(ExecPolicy&& p, F f)
0518 {
0519 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0520 table_.erase_if(p, f);
0521 }
0522 #endif
0523
0524 template <class F> size_type erase_if(F f) { return table_.erase_if(f); }
0525
0526 void swap(concurrent_flat_set& other) noexcept(
0527 boost::allocator_is_always_equal<Allocator>::type::value ||
0528 boost::allocator_propagate_on_container_swap<Allocator>::type::value)
0529 {
0530 return table_.swap(other.table_);
0531 }
0532
0533 void clear() noexcept { table_.clear(); }
0534
0535 template <typename H2, typename P2>
0536 size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>& x)
0537 {
0538 BOOST_ASSERT(get_allocator() == x.get_allocator());
0539 return table_.merge(x.table_);
0540 }
0541
0542 template <typename H2, typename P2>
0543 size_type merge(concurrent_flat_set<Key, H2, P2, Allocator>&& x)
0544 {
0545 return merge(x);
0546 }
0547
0548 BOOST_FORCEINLINE size_type count(key_type const& k) const
0549 {
0550 return table_.count(k);
0551 }
0552
0553 template <class K>
0554 BOOST_FORCEINLINE typename std::enable_if<
0555 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0556 count(K const& k)
0557 {
0558 return table_.count(k);
0559 }
0560
0561 BOOST_FORCEINLINE bool contains(key_type const& k) const
0562 {
0563 return table_.contains(k);
0564 }
0565
0566 template <class K>
0567 BOOST_FORCEINLINE typename std::enable_if<
0568 detail::are_transparent<K, hasher, key_equal>::value, bool>::type
0569 contains(K const& k) const
0570 {
0571 return table_.contains(k);
0572 }
0573
0574
0575
0576 size_type bucket_count() const noexcept { return table_.capacity(); }
0577
0578 float load_factor() const noexcept { return table_.load_factor(); }
0579 float max_load_factor() const noexcept
0580 {
0581 return table_.max_load_factor();
0582 }
0583 void max_load_factor(float) {}
0584 size_type max_load() const noexcept { return table_.max_load(); }
0585
0586 void rehash(size_type n) { table_.rehash(n); }
0587 void reserve(size_type n) { table_.reserve(n); }
0588
0589 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0590
0591
0592 stats get_stats() const { return table_.get_stats(); }
0593
0594 void reset_stats() noexcept { table_.reset_stats(); }
0595 #endif
0596
0597
0598
0599 allocator_type get_allocator() const noexcept
0600 {
0601 return table_.get_allocator();
0602 }
0603
0604 hasher hash_function() const { return table_.hash_function(); }
0605 key_equal key_eq() const { return table_.key_eq(); }
0606 };
0607
0608 template <class Key, class Hash, class KeyEqual, class Allocator>
0609 bool operator==(
0610 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
0611 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
0612 {
0613 return lhs.table_ == rhs.table_;
0614 }
0615
0616 template <class Key, class Hash, class KeyEqual, class Allocator>
0617 bool operator!=(
0618 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
0619 concurrent_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
0620 {
0621 return !(lhs == rhs);
0622 }
0623
0624 template <class Key, class Hash, class Pred, class Alloc>
0625 void swap(concurrent_flat_set<Key, Hash, Pred, Alloc>& x,
0626 concurrent_flat_set<Key, Hash, Pred, Alloc>& y)
0627 noexcept(noexcept(x.swap(y)))
0628 {
0629 x.swap(y);
0630 }
0631
0632 template <class K, class H, class P, class A, class Predicate>
0633 typename concurrent_flat_set<K, H, P, A>::size_type erase_if(
0634 concurrent_flat_set<K, H, P, A>& c, Predicate pred)
0635 {
0636 return c.table_.erase_if(pred);
0637 }
0638
0639 template<class Archive, class K, class H, class KE, class A>
0640 void serialize(
0641 Archive& ar, concurrent_flat_set<K, H, KE, A>& c, unsigned int)
0642 {
0643 ar & core::make_nvp("table",c.table_);
0644 }
0645
0646 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0647
0648 template <class InputIterator,
0649 class Hash =
0650 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0651 class Pred =
0652 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0653 class Allocator = std::allocator<
0654 typename std::iterator_traits<InputIterator>::value_type>,
0655 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0656 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0657 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0658 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0659 concurrent_flat_set(InputIterator, InputIterator,
0660 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0661 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0662 -> concurrent_flat_set<
0663 typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
0664 Allocator>;
0665
0666 template <class T, class Hash = boost::hash<T>,
0667 class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
0668 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0669 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0670 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0671 concurrent_flat_set(std::initializer_list<T>,
0672 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0673 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0674 -> concurrent_flat_set< T, Hash, Pred, Allocator>;
0675
0676 template <class InputIterator, class Allocator,
0677 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0678 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0679 concurrent_flat_set(InputIterator, InputIterator, std::size_t, Allocator)
0680 -> concurrent_flat_set<
0681 typename std::iterator_traits<InputIterator>::value_type,
0682 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0683 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0684 Allocator>;
0685
0686 template <class InputIterator, class Allocator,
0687 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0688 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0689 concurrent_flat_set(InputIterator, InputIterator, Allocator)
0690 -> concurrent_flat_set<
0691 typename std::iterator_traits<InputIterator>::value_type,
0692 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0693 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0694 Allocator>;
0695
0696 template <class InputIterator, class Hash, class Allocator,
0697 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0698 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0699 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0700 concurrent_flat_set(
0701 InputIterator, InputIterator, std::size_t, Hash, Allocator)
0702 -> concurrent_flat_set<
0703 typename std::iterator_traits<InputIterator>::value_type, Hash,
0704 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0705 Allocator>;
0706
0707 template <class T, class Allocator,
0708 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0709 concurrent_flat_set(std::initializer_list<T>, std::size_t, Allocator)
0710 -> concurrent_flat_set<T, boost::hash<T>,std::equal_to<T>, Allocator>;
0711
0712 template <class T, class Allocator,
0713 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0714 concurrent_flat_set(std::initializer_list<T >, Allocator)
0715 -> concurrent_flat_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0716
0717 template <class T, class Hash, class Allocator,
0718 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0719 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0720 concurrent_flat_set(std::initializer_list<T >, std::size_t,Hash, Allocator)
0721 -> concurrent_flat_set<T, Hash, std::equal_to<T>, Allocator>;
0722
0723 #endif
0724
0725 }
0726 }
0727
0728 #endif