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