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