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