File indexing completed on 2025-06-30 08:32:10
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 concurrent_flat_map(
0194 unordered_flat_map<Key, T, Hash, Pred, Allocator>&& other)
0195 : table_(std::move(other.table_))
0196 {
0197 }
0198
0199 ~concurrent_flat_map() = default;
0200
0201 concurrent_flat_map& operator=(concurrent_flat_map const& rhs)
0202 {
0203 table_ = rhs.table_;
0204 return *this;
0205 }
0206
0207 concurrent_flat_map& operator=(concurrent_flat_map&& rhs) noexcept(
0208 noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
0209 {
0210 table_ = std::move(rhs.table_);
0211 return *this;
0212 }
0213
0214 concurrent_flat_map& 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_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_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_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_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_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_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_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 template <class Ty>
0410 BOOST_FORCEINLINE auto insert(Ty&& value)
0411 -> decltype(table_.insert(std::forward<Ty>(value)))
0412 {
0413 return table_.insert(std::forward<Ty>(value));
0414 }
0415
0416 BOOST_FORCEINLINE bool insert(init_type&& obj)
0417 {
0418 return table_.insert(std::move(obj));
0419 }
0420
0421 template <class InputIterator>
0422 void insert(InputIterator begin, InputIterator end)
0423 {
0424 for (auto pos = begin; pos != end; ++pos) {
0425 table_.emplace(*pos);
0426 }
0427 }
0428
0429 void insert(std::initializer_list<value_type> ilist)
0430 {
0431 this->insert(ilist.begin(), ilist.end());
0432 }
0433
0434 template <class M>
0435 BOOST_FORCEINLINE bool insert_or_assign(key_type const& k, M&& obj)
0436 {
0437 return table_.try_emplace_or_visit(k, std::forward<M>(obj),
0438 [&](value_type& m) { m.second = std::forward<M>(obj); });
0439 }
0440
0441 template <class M>
0442 BOOST_FORCEINLINE bool insert_or_assign(key_type&& k, M&& obj)
0443 {
0444 return table_.try_emplace_or_visit(std::move(k), std::forward<M>(obj),
0445 [&](value_type& m) { m.second = std::forward<M>(obj); });
0446 }
0447
0448 template <class K, class M>
0449 BOOST_FORCEINLINE typename std::enable_if<
0450 detail::are_transparent<K, hasher, key_equal>::value, bool>::type
0451 insert_or_assign(K&& k, M&& obj)
0452 {
0453 return table_.try_emplace_or_visit(std::forward<K>(k),
0454 std::forward<M>(obj),
0455 [&](value_type& m) { m.second = std::forward<M>(obj); });
0456 }
0457
0458 template <class Ty, class F>
0459 BOOST_FORCEINLINE auto insert_or_visit(Ty&& value, F f)
0460 -> decltype(table_.insert_or_visit(std::forward<Ty>(value), f))
0461 {
0462 BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
0463 return table_.insert_or_visit(std::forward<Ty>(value), f);
0464 }
0465
0466 template <class F>
0467 BOOST_FORCEINLINE bool insert_or_visit(init_type&& obj, F f)
0468 {
0469 BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
0470 return table_.insert_or_visit(std::move(obj), f);
0471 }
0472
0473 template <class InputIterator, class F>
0474 void insert_or_visit(InputIterator first, InputIterator last, F f)
0475 {
0476 BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
0477 for (; first != last; ++first) {
0478 table_.emplace_or_visit(*first, f);
0479 }
0480 }
0481
0482 template <class F>
0483 void insert_or_visit(std::initializer_list<value_type> ilist, F f)
0484 {
0485 BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F)
0486 this->insert_or_visit(ilist.begin(), ilist.end(), f);
0487 }
0488
0489 template <class Ty, class F>
0490 BOOST_FORCEINLINE auto insert_or_cvisit(Ty&& value, F f)
0491 -> decltype(table_.insert_or_cvisit(std::forward<Ty>(value), f))
0492 {
0493 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0494 return table_.insert_or_cvisit(std::forward<Ty>(value), f);
0495 }
0496
0497 template <class F>
0498 BOOST_FORCEINLINE bool insert_or_cvisit(init_type&& obj, F f)
0499 {
0500 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0501 return table_.insert_or_cvisit(std::move(obj), f);
0502 }
0503
0504 template <class InputIterator, class F>
0505 void insert_or_cvisit(InputIterator first, InputIterator last, F f)
0506 {
0507 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0508 for (; first != last; ++first) {
0509 table_.emplace_or_cvisit(*first, f);
0510 }
0511 }
0512
0513 template <class F>
0514 void insert_or_cvisit(std::initializer_list<value_type> ilist, F f)
0515 {
0516 BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F)
0517 this->insert_or_cvisit(ilist.begin(), ilist.end(), f);
0518 }
0519
0520 template <class... Args> BOOST_FORCEINLINE bool emplace(Args&&... args)
0521 {
0522 return table_.emplace(std::forward<Args>(args)...);
0523 }
0524
0525 template <class Arg, class... Args>
0526 BOOST_FORCEINLINE bool emplace_or_visit(Arg&& arg, Args&&... args)
0527 {
0528 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg, Args...)
0529 return table_.emplace_or_visit(
0530 std::forward<Arg>(arg), std::forward<Args>(args)...);
0531 }
0532
0533 template <class Arg, class... Args>
0534 BOOST_FORCEINLINE bool emplace_or_cvisit(Arg&& arg, Args&&... args)
0535 {
0536 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0537 return table_.emplace_or_cvisit(
0538 std::forward<Arg>(arg), std::forward<Args>(args)...);
0539 }
0540
0541 template <class... Args>
0542 BOOST_FORCEINLINE bool try_emplace(key_type const& k, Args&&... args)
0543 {
0544 return table_.try_emplace(k, std::forward<Args>(args)...);
0545 }
0546
0547 template <class... Args>
0548 BOOST_FORCEINLINE bool try_emplace(key_type&& k, Args&&... args)
0549 {
0550 return table_.try_emplace(std::move(k), std::forward<Args>(args)...);
0551 }
0552
0553 template <class K, class... Args>
0554 BOOST_FORCEINLINE typename std::enable_if<
0555 detail::are_transparent<K, hasher, key_equal>::value, bool>::type
0556 try_emplace(K&& k, Args&&... args)
0557 {
0558 return table_.try_emplace(
0559 std::forward<K>(k), std::forward<Args>(args)...);
0560 }
0561
0562 template <class Arg, class... Args>
0563 BOOST_FORCEINLINE bool try_emplace_or_visit(
0564 key_type const& k, Arg&& arg, Args&&... args)
0565 {
0566 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg, Args...)
0567 return table_.try_emplace_or_visit(
0568 k, std::forward<Arg>(arg), std::forward<Args>(args)...);
0569 }
0570
0571 template <class Arg, class... Args>
0572 BOOST_FORCEINLINE bool try_emplace_or_cvisit(
0573 key_type const& k, Arg&& arg, Args&&... args)
0574 {
0575 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0576 return table_.try_emplace_or_cvisit(
0577 k, std::forward<Arg>(arg), std::forward<Args>(args)...);
0578 }
0579
0580 template <class Arg, class... Args>
0581 BOOST_FORCEINLINE bool try_emplace_or_visit(
0582 key_type&& k, Arg&& arg, Args&&... args)
0583 {
0584 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg, Args...)
0585 return table_.try_emplace_or_visit(
0586 std::move(k), std::forward<Arg>(arg), std::forward<Args>(args)...);
0587 }
0588
0589 template <class Arg, class... Args>
0590 BOOST_FORCEINLINE bool try_emplace_or_cvisit(
0591 key_type&& k, Arg&& arg, Args&&... args)
0592 {
0593 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0594 return table_.try_emplace_or_cvisit(
0595 std::move(k), std::forward<Arg>(arg), std::forward<Args>(args)...);
0596 }
0597
0598 template <class K, class Arg, class... Args>
0599 BOOST_FORCEINLINE bool try_emplace_or_visit(
0600 K&& k, Arg&& arg, Args&&... args)
0601 {
0602 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_INVOCABLE(Arg, Args...)
0603 return table_.try_emplace_or_visit(std::forward<K>(k),
0604 std::forward<Arg>(arg), std::forward<Args>(args)...);
0605 }
0606
0607 template <class K, class Arg, class... Args>
0608 BOOST_FORCEINLINE bool try_emplace_or_cvisit(
0609 K&& k, Arg&& arg, Args&&... args)
0610 {
0611 BOOST_UNORDERED_STATIC_ASSERT_LAST_ARG_CONST_INVOCABLE(Arg, Args...)
0612 return table_.try_emplace_or_cvisit(std::forward<K>(k),
0613 std::forward<Arg>(arg), std::forward<Args>(args)...);
0614 }
0615
0616 BOOST_FORCEINLINE size_type erase(key_type const& k)
0617 {
0618 return table_.erase(k);
0619 }
0620
0621 template <class K>
0622 BOOST_FORCEINLINE typename std::enable_if<
0623 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0624 erase(K&& k)
0625 {
0626 return table_.erase(std::forward<K>(k));
0627 }
0628
0629 template <class F>
0630 BOOST_FORCEINLINE size_type erase_if(key_type const& k, F f)
0631 {
0632 return table_.erase_if(k, f);
0633 }
0634
0635 template <class K, class F>
0636 BOOST_FORCEINLINE typename std::enable_if<
0637 detail::are_transparent<K, hasher, key_equal>::value &&
0638 !detail::is_execution_policy<K>::value,
0639 size_type>::type
0640 erase_if(K&& k, F f)
0641 {
0642 return table_.erase_if(std::forward<K>(k), f);
0643 }
0644
0645 #if defined(BOOST_UNORDERED_PARALLEL_ALGORITHMS)
0646 template <class ExecPolicy, class F>
0647 typename std::enable_if<detail::is_execution_policy<ExecPolicy>::value,
0648 void>::type
0649 erase_if(ExecPolicy&& p, F f)
0650 {
0651 BOOST_UNORDERED_STATIC_ASSERT_EXEC_POLICY(ExecPolicy)
0652 table_.erase_if(p, f);
0653 }
0654 #endif
0655
0656 template <class F> size_type erase_if(F f) { return table_.erase_if(f); }
0657
0658 void swap(concurrent_flat_map& other) noexcept(
0659 boost::allocator_is_always_equal<Allocator>::type::value ||
0660 boost::allocator_propagate_on_container_swap<Allocator>::type::value)
0661 {
0662 return table_.swap(other.table_);
0663 }
0664
0665 void clear() noexcept { table_.clear(); }
0666
0667 template <typename H2, typename P2>
0668 size_type merge(concurrent_flat_map<Key, T, H2, P2, Allocator>& x)
0669 {
0670 BOOST_ASSERT(get_allocator() == x.get_allocator());
0671 return table_.merge(x.table_);
0672 }
0673
0674 template <typename H2, typename P2>
0675 size_type merge(concurrent_flat_map<Key, T, H2, P2, Allocator>&& x)
0676 {
0677 return merge(x);
0678 }
0679
0680 BOOST_FORCEINLINE size_type count(key_type const& k) const
0681 {
0682 return table_.count(k);
0683 }
0684
0685 template <class K>
0686 BOOST_FORCEINLINE typename std::enable_if<
0687 detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
0688 count(K const& k)
0689 {
0690 return table_.count(k);
0691 }
0692
0693 BOOST_FORCEINLINE bool contains(key_type const& k) const
0694 {
0695 return table_.contains(k);
0696 }
0697
0698 template <class K>
0699 BOOST_FORCEINLINE typename std::enable_if<
0700 detail::are_transparent<K, hasher, key_equal>::value, bool>::type
0701 contains(K const& k) const
0702 {
0703 return table_.contains(k);
0704 }
0705
0706
0707
0708 size_type bucket_count() const noexcept { return table_.capacity(); }
0709
0710 float load_factor() const noexcept { return table_.load_factor(); }
0711 float max_load_factor() const noexcept
0712 {
0713 return table_.max_load_factor();
0714 }
0715 void max_load_factor(float) {}
0716 size_type max_load() const noexcept { return table_.max_load(); }
0717
0718 void rehash(size_type n) { table_.rehash(n); }
0719 void reserve(size_type n) { table_.reserve(n); }
0720
0721 #if defined(BOOST_UNORDERED_ENABLE_STATS)
0722
0723
0724 stats get_stats() const { return table_.get_stats(); }
0725
0726 void reset_stats() noexcept { table_.reset_stats(); }
0727 #endif
0728
0729
0730
0731 allocator_type get_allocator() const noexcept
0732 {
0733 return table_.get_allocator();
0734 }
0735
0736 hasher hash_function() const { return table_.hash_function(); }
0737 key_equal key_eq() const { return table_.key_eq(); }
0738 };
0739
0740 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0741 bool operator==(
0742 concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
0743 concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
0744 {
0745 return lhs.table_ == rhs.table_;
0746 }
0747
0748 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0749 bool operator!=(
0750 concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
0751 concurrent_flat_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
0752 {
0753 return !(lhs == rhs);
0754 }
0755
0756 template <class Key, class T, class Hash, class Pred, class Alloc>
0757 void swap(concurrent_flat_map<Key, T, Hash, Pred, Alloc>& x,
0758 concurrent_flat_map<Key, T, Hash, Pred, Alloc>& y)
0759 noexcept(noexcept(x.swap(y)))
0760 {
0761 x.swap(y);
0762 }
0763
0764 template <class K, class T, class H, class P, class A, class Predicate>
0765 typename concurrent_flat_map<K, T, H, P, A>::size_type erase_if(
0766 concurrent_flat_map<K, T, H, P, A>& c, Predicate pred)
0767 {
0768 return c.table_.erase_if(pred);
0769 }
0770
0771 template<class Archive, class K, class V, class H, class KE, class A>
0772 void serialize(
0773 Archive& ar, concurrent_flat_map<K, V, H, KE, A>& c, unsigned int)
0774 {
0775 ar & core::make_nvp("table",c.table_);
0776 }
0777
0778 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0779
0780 template <class InputIterator,
0781 class Hash =
0782 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0783 class Pred =
0784 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0785 class Allocator = std::allocator<
0786 boost::unordered::detail::iter_to_alloc_t<InputIterator> >,
0787 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0788 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0789 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0790 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0791 concurrent_flat_map(InputIterator, InputIterator,
0792 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0793 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0794 -> concurrent_flat_map<
0795 boost::unordered::detail::iter_key_t<InputIterator>,
0796 boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
0797 Allocator>;
0798
0799 template <class Key, class T,
0800 class Hash = boost::hash<std::remove_const_t<Key> >,
0801 class Pred = std::equal_to<std::remove_const_t<Key> >,
0802 class Allocator = std::allocator<std::pair<const Key, T> >,
0803 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0804 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0805 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0806 concurrent_flat_map(std::initializer_list<std::pair<Key, T> >,
0807 std::size_t = boost::unordered::detail::foa::default_bucket_count,
0808 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0809 -> concurrent_flat_map<std::remove_const_t<Key>, T, Hash, Pred,
0810 Allocator>;
0811
0812 template <class InputIterator, class Allocator,
0813 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0814 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0815 concurrent_flat_map(InputIterator, InputIterator, std::size_t, Allocator)
0816 -> concurrent_flat_map<
0817 boost::unordered::detail::iter_key_t<InputIterator>,
0818 boost::unordered::detail::iter_val_t<InputIterator>,
0819 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0820 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0821 Allocator>;
0822
0823 template <class InputIterator, class Allocator,
0824 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0825 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0826 concurrent_flat_map(InputIterator, InputIterator, Allocator)
0827 -> concurrent_flat_map<
0828 boost::unordered::detail::iter_key_t<InputIterator>,
0829 boost::unordered::detail::iter_val_t<InputIterator>,
0830 boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
0831 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0832 Allocator>;
0833
0834 template <class InputIterator, class Hash, class Allocator,
0835 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0836 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0837 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0838 concurrent_flat_map(
0839 InputIterator, InputIterator, std::size_t, Hash, Allocator)
0840 -> concurrent_flat_map<
0841 boost::unordered::detail::iter_key_t<InputIterator>,
0842 boost::unordered::detail::iter_val_t<InputIterator>, Hash,
0843 std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
0844 Allocator>;
0845
0846 template <class Key, class T, class Allocator,
0847 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0848 concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
0849 Allocator) -> concurrent_flat_map<std::remove_const_t<Key>, T,
0850 boost::hash<std::remove_const_t<Key> >,
0851 std::equal_to<std::remove_const_t<Key> >, Allocator>;
0852
0853 template <class Key, class T, class Allocator,
0854 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0855 concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, Allocator)
0856 -> concurrent_flat_map<std::remove_const_t<Key>, T,
0857 boost::hash<std::remove_const_t<Key> >,
0858 std::equal_to<std::remove_const_t<Key> >, Allocator>;
0859
0860 template <class Key, class T, class Hash, class Allocator,
0861 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0862 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0863 concurrent_flat_map(std::initializer_list<std::pair<Key, T> >, std::size_t,
0864 Hash, Allocator) -> concurrent_flat_map<std::remove_const_t<Key>, T,
0865 Hash, std::equal_to<std::remove_const_t<Key> >, Allocator>;
0866
0867 #endif
0868
0869 }
0870 }
0871
0872 #endif