File indexing completed on 2025-01-30 10:02:00
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
0010 #define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
0011
0012 #include <boost/config.hpp>
0013 #if defined(BOOST_HAS_PRAGMA_ONCE)
0014 #pragma once
0015 #endif
0016
0017 #include <boost/unordered/detail/serialize_fca_container.hpp>
0018 #include <boost/unordered/detail/set.hpp>
0019 #include <boost/unordered/detail/type_traits.hpp>
0020
0021 #include <boost/container_hash/hash.hpp>
0022
0023 #include <initializer_list>
0024
0025 #if defined(BOOST_MSVC)
0026 #pragma warning(push)
0027
0028 #pragma warning(disable : 4127)
0029 #if BOOST_MSVC >= 1400
0030
0031
0032 #pragma warning(disable : 4396)
0033 #endif
0034 #endif
0035
0036 namespace boost {
0037 namespace unordered {
0038 template <class T, class H, class P, class A> class unordered_set
0039 {
0040 template <typename, typename, typename, typename>
0041 friend class unordered_multiset;
0042
0043 public:
0044 typedef T key_type;
0045 typedef T value_type;
0046 typedef H hasher;
0047 typedef P key_equal;
0048 typedef A allocator_type;
0049
0050 private:
0051 typedef boost::unordered::detail::set<A, T, H, P> types;
0052 typedef typename types::value_allocator_traits value_allocator_traits;
0053 typedef typename types::table table;
0054
0055 public:
0056 typedef typename value_allocator_traits::pointer pointer;
0057 typedef typename value_allocator_traits::const_pointer const_pointer;
0058
0059 typedef value_type& reference;
0060 typedef value_type const& const_reference;
0061
0062 typedef std::size_t size_type;
0063 typedef std::ptrdiff_t difference_type;
0064
0065 typedef typename table::c_iterator iterator;
0066 typedef typename table::c_iterator const_iterator;
0067 typedef typename table::cl_iterator local_iterator;
0068 typedef typename table::cl_iterator const_local_iterator;
0069 typedef typename types::node_type node_type;
0070 typedef typename types::insert_return_type insert_return_type;
0071
0072 private:
0073 table table_;
0074
0075 public:
0076
0077
0078 unordered_set();
0079
0080 explicit unordered_set(size_type, const hasher& = hasher(),
0081 const key_equal& = key_equal(),
0082 const allocator_type& = allocator_type());
0083
0084 template <class InputIt>
0085 unordered_set(InputIt, InputIt,
0086 size_type = boost::unordered::detail::default_bucket_count,
0087 const hasher& = hasher(), const key_equal& = key_equal(),
0088 const allocator_type& = allocator_type());
0089
0090 unordered_set(unordered_set const&);
0091
0092 unordered_set(unordered_set&& other)
0093 noexcept(table::nothrow_move_constructible)
0094 : table_(other.table_, boost::unordered::detail::move_tag())
0095 {
0096
0097 }
0098
0099 explicit unordered_set(allocator_type const&);
0100
0101 unordered_set(unordered_set const&, allocator_type const&);
0102
0103 unordered_set(unordered_set&&, allocator_type const&);
0104
0105 unordered_set(std::initializer_list<value_type>,
0106 size_type = boost::unordered::detail::default_bucket_count,
0107 const hasher& = hasher(), const key_equal& l = key_equal(),
0108 const allocator_type& = allocator_type());
0109
0110 explicit unordered_set(size_type, const allocator_type&);
0111
0112 explicit unordered_set(size_type, const hasher&, const allocator_type&);
0113
0114 template <class InputIterator>
0115 unordered_set(InputIterator, InputIterator, const allocator_type&);
0116
0117 template <class InputIt>
0118 unordered_set(InputIt, InputIt, size_type, const allocator_type&);
0119
0120 template <class InputIt>
0121 unordered_set(
0122 InputIt, InputIt, size_type, const hasher&, const allocator_type&);
0123
0124 unordered_set(std::initializer_list<value_type>, const allocator_type&);
0125
0126 unordered_set(
0127 std::initializer_list<value_type>, size_type, const allocator_type&);
0128
0129 unordered_set(std::initializer_list<value_type>, size_type, const hasher&,
0130 const allocator_type&);
0131
0132
0133
0134 ~unordered_set() noexcept;
0135
0136
0137
0138 unordered_set& operator=(unordered_set const& x)
0139 {
0140 table_.assign(x.table_, std::true_type());
0141 return *this;
0142 }
0143
0144 unordered_set& operator=(unordered_set&& x)
0145 noexcept(value_allocator_traits::is_always_equal::value&&
0146 std::is_nothrow_move_assignable<H>::value&&
0147 std::is_nothrow_move_assignable<P>::value)
0148 {
0149 table_.move_assign(x.table_, std::true_type());
0150 return *this;
0151 }
0152
0153 unordered_set& operator=(std::initializer_list<value_type>);
0154
0155 allocator_type get_allocator() const noexcept
0156 {
0157 return table_.node_alloc();
0158 }
0159
0160
0161
0162 iterator begin() noexcept { return iterator(table_.begin()); }
0163
0164 const_iterator begin() const noexcept
0165 {
0166 return const_iterator(table_.begin());
0167 }
0168
0169 iterator end() noexcept { return iterator(); }
0170
0171 const_iterator end() const noexcept { return const_iterator(); }
0172
0173 const_iterator cbegin() const noexcept
0174 {
0175 return const_iterator(table_.begin());
0176 }
0177
0178 const_iterator cend() const noexcept { return const_iterator(); }
0179
0180
0181
0182 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0183 {
0184 return table_.size_ == 0;
0185 }
0186
0187 size_type size() const noexcept { return table_.size_; }
0188
0189 size_type max_size() const noexcept;
0190
0191
0192
0193 template <class... Args> std::pair<iterator, bool> emplace(Args&&... args)
0194 {
0195 return table_.emplace_unique(
0196 table::extractor::extract(std::forward<Args>(args)...),
0197 std::forward<Args>(args)...);
0198 }
0199
0200 template <class... Args>
0201 iterator emplace_hint(const_iterator hint, Args&&... args)
0202 {
0203 return table_.emplace_hint_unique(hint,
0204 table::extractor::extract(std::forward<Args>(args)...),
0205 std::forward<Args>(args)...);
0206 }
0207
0208 std::pair<iterator, bool> insert(value_type const& x)
0209 {
0210 return this->emplace(x);
0211 }
0212
0213 std::pair<iterator, bool> insert(value_type&& x)
0214 {
0215 return this->emplace(std::move(x));
0216 }
0217
0218 template <class Key>
0219 typename boost::enable_if_c<
0220 detail::transparent_non_iterable<Key, unordered_set>::value,
0221 std::pair<iterator, bool> >::type
0222 insert(Key&& k)
0223 {
0224 return table_.try_emplace_unique(std::forward<Key>(k));
0225 }
0226
0227 iterator insert(const_iterator hint, value_type const& x)
0228 {
0229 return this->emplace_hint(hint, x);
0230 }
0231
0232 iterator insert(const_iterator hint, value_type&& x)
0233 {
0234 return this->emplace_hint(hint, std::move(x));
0235 }
0236
0237 template <class Key>
0238 typename boost::enable_if_c<
0239 detail::transparent_non_iterable<Key, unordered_set>::value,
0240 iterator>::type
0241 insert(const_iterator hint, Key&& k)
0242 {
0243 return table_.try_emplace_hint_unique(hint, std::forward<Key>(k));
0244 }
0245
0246 template <class InputIt> void insert(InputIt, InputIt);
0247
0248 void insert(std::initializer_list<value_type>);
0249
0250
0251
0252 node_type extract(const_iterator position)
0253 {
0254 return node_type(
0255 table_.extract_by_iterator_unique(position), table_.node_alloc());
0256 }
0257
0258 node_type extract(const key_type& k)
0259 {
0260 return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0261 }
0262
0263 template <class Key>
0264 typename boost::enable_if_c<
0265 detail::transparent_non_iterable<Key, unordered_set>::value,
0266 node_type>::type
0267 extract(const Key& k)
0268 {
0269 return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0270 }
0271
0272 insert_return_type insert(node_type&& np)
0273 {
0274 insert_return_type result;
0275 table_.move_insert_node_type_unique(np, result);
0276 return result;
0277 }
0278
0279 iterator insert(const_iterator hint, node_type&& np)
0280 {
0281 return table_.move_insert_node_type_with_hint_unique(hint, np);
0282 }
0283
0284 iterator erase(const_iterator);
0285 size_type erase(const key_type&);
0286 iterator erase(const_iterator, const_iterator);
0287
0288 template <class Key>
0289 typename boost::enable_if_c<
0290 detail::transparent_non_iterable<Key, unordered_set>::value,
0291 size_type>::type
0292 erase(Key&& k)
0293 {
0294 return table_.erase_key_unique_impl(std::forward<Key>(k));
0295 }
0296
0297 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0298 void quick_erase(const_iterator it) { erase(it); }
0299 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0300 void erase_return_void(const_iterator it) { erase(it); }
0301
0302 void swap(unordered_set&)
0303 noexcept(value_allocator_traits::is_always_equal::value&&
0304 boost::unordered::detail::is_nothrow_swappable<H>::value&&
0305 boost::unordered::detail::is_nothrow_swappable<P>::value);
0306 void clear() noexcept { table_.clear_impl(); }
0307
0308 template <typename H2, typename P2>
0309 void merge(boost::unordered_set<T, H2, P2, A>& source);
0310
0311 template <typename H2, typename P2>
0312 void merge(boost::unordered_set<T, H2, P2, A>&& source);
0313
0314 template <typename H2, typename P2>
0315 void merge(boost::unordered_multiset<T, H2, P2, A>& source);
0316
0317 template <typename H2, typename P2>
0318 void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
0319
0320
0321
0322 hasher hash_function() const;
0323 key_equal key_eq() const;
0324
0325
0326
0327 const_iterator find(const key_type&) const;
0328
0329 template <class Key>
0330 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0331 const_iterator>::type
0332 find(const Key& k) const
0333 {
0334 return const_iterator(table_.find(k));
0335 }
0336
0337 template <class CompatibleKey, class CompatibleHash,
0338 class CompatiblePredicate>
0339 const_iterator find(CompatibleKey const&, CompatibleHash const&,
0340 CompatiblePredicate const&) const;
0341
0342 bool contains(key_type const& k) const
0343 {
0344 return table_.find(k) != this->end();
0345 }
0346
0347 template <class Key>
0348 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0349 bool>::type
0350 contains(const Key& k) const
0351 {
0352 return table_.find(k) != this->end();
0353 }
0354
0355 size_type count(const key_type&) const;
0356
0357 template <class Key>
0358 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0359 size_type>::type
0360 count(const Key& k) const
0361 {
0362 return table_.find(k) != this->end() ? 1 : 0;
0363 }
0364
0365 std::pair<const_iterator, const_iterator> equal_range(
0366 const key_type&) const;
0367
0368 template <class Key>
0369 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0370 std::pair<const_iterator, const_iterator> >::type
0371 equal_range(Key const& k) const
0372 {
0373 iterator n = table_.find(k);
0374 iterator m = n;
0375 if (m != this->end()) {
0376 ++m;
0377 }
0378
0379 return std::make_pair(const_iterator(n), const_iterator(m));
0380 }
0381
0382
0383
0384 size_type bucket_count() const noexcept { return table_.bucket_count(); }
0385
0386 size_type max_bucket_count() const noexcept
0387 {
0388 return table_.max_bucket_count();
0389 }
0390
0391 size_type bucket_size(size_type) const;
0392
0393 size_type bucket(const key_type& k) const
0394 {
0395 return table_.hash_to_bucket(table_.hash(k));
0396 }
0397
0398 template <class Key>
0399 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0400 size_type>::type
0401 bucket(Key&& k) const
0402 {
0403 return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
0404 }
0405
0406 local_iterator begin(size_type n)
0407 {
0408 return local_iterator(table_.begin(n));
0409 }
0410
0411 const_local_iterator begin(size_type n) const
0412 {
0413 return const_local_iterator(table_.begin(n));
0414 }
0415
0416 local_iterator end(size_type) { return local_iterator(); }
0417
0418 const_local_iterator end(size_type) const
0419 {
0420 return const_local_iterator();
0421 }
0422
0423 const_local_iterator cbegin(size_type n) const
0424 {
0425 return const_local_iterator(table_.begin(n));
0426 }
0427
0428 const_local_iterator cend(size_type) const
0429 {
0430 return const_local_iterator();
0431 }
0432
0433
0434
0435 float load_factor() const noexcept;
0436 float max_load_factor() const noexcept { return table_.mlf_; }
0437 void max_load_factor(float) noexcept;
0438 void rehash(size_type);
0439 void reserve(size_type);
0440
0441 #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
0442 friend bool operator==
0443 <T, H, P, A>(unordered_set const&, unordered_set const&);
0444 friend bool operator!=
0445 <T, H, P, A>(unordered_set const&, unordered_set const&);
0446 #endif
0447 };
0448
0449 template <class Archive, class K, class H, class P, class A>
0450 void serialize(
0451 Archive& ar, unordered_set<K, H, P, A>& c, unsigned int version)
0452 {
0453 detail::serialize_fca_container(ar, c, version);
0454 }
0455
0456 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0457
0458 template <class InputIterator,
0459 class Hash =
0460 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0461 class Pred =
0462 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0463 class Allocator = std::allocator<
0464 typename std::iterator_traits<InputIterator>::value_type>,
0465 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0466 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0467 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0468 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0469 unordered_set(InputIterator, InputIterator,
0470 std::size_t = boost::unordered::detail::default_bucket_count,
0471 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0472 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0473 Hash, Pred, Allocator>;
0474
0475 template <class T, class Hash = boost::hash<T>,
0476 class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
0477 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0478 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0479 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0480 unordered_set(std::initializer_list<T>,
0481 std::size_t = boost::unordered::detail::default_bucket_count,
0482 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0483 -> unordered_set<T, Hash, Pred, Allocator>;
0484
0485 template <class InputIterator, class Allocator,
0486 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0487 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0488 unordered_set(InputIterator, InputIterator, std::size_t, Allocator)
0489 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0490 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0491 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0492 Allocator>;
0493
0494 template <class InputIterator, class Hash, class Allocator,
0495 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0496 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0497 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0498 unordered_set(InputIterator, InputIterator, std::size_t, Hash, Allocator)
0499 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0500 Hash,
0501 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0502 Allocator>;
0503
0504 template <class T, class Allocator,
0505 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0506 unordered_set(std::initializer_list<T>, std::size_t, Allocator)
0507 -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0508
0509 template <class T, class Hash, class Allocator,
0510 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0511 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0512 unordered_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
0513 -> unordered_set<T, Hash, std::equal_to<T>, Allocator>;
0514
0515 template <class InputIterator, class Allocator,
0516 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0517 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0518 unordered_set(InputIterator, InputIterator, Allocator)
0519 -> unordered_set<typename std::iterator_traits<InputIterator>::value_type,
0520 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0521 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0522 Allocator>;
0523
0524 template <class T, class Allocator,
0525 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0526 unordered_set(std::initializer_list<T>, Allocator)
0527 -> unordered_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0528
0529 #endif
0530
0531 template <class T, class H, class P, class A> class unordered_multiset
0532 {
0533 template <typename, typename, typename, typename>
0534 friend class unordered_set;
0535
0536 public:
0537 typedef T key_type;
0538 typedef T value_type;
0539 typedef H hasher;
0540 typedef P key_equal;
0541 typedef A allocator_type;
0542
0543 private:
0544 typedef boost::unordered::detail::set<A, T, H, P> types;
0545 typedef typename types::value_allocator_traits value_allocator_traits;
0546 typedef typename types::table table;
0547
0548 public:
0549 typedef typename value_allocator_traits::pointer pointer;
0550 typedef typename value_allocator_traits::const_pointer const_pointer;
0551
0552 typedef value_type& reference;
0553 typedef value_type const& const_reference;
0554
0555 typedef std::size_t size_type;
0556 typedef std::ptrdiff_t difference_type;
0557
0558 typedef typename table::c_iterator iterator;
0559 typedef typename table::c_iterator const_iterator;
0560 typedef typename table::cl_iterator local_iterator;
0561 typedef typename table::cl_iterator const_local_iterator;
0562 typedef typename types::node_type node_type;
0563
0564 private:
0565 table table_;
0566
0567 public:
0568
0569
0570 unordered_multiset();
0571
0572 explicit unordered_multiset(size_type, const hasher& = hasher(),
0573 const key_equal& = key_equal(),
0574 const allocator_type& = allocator_type());
0575
0576 template <class InputIt>
0577 unordered_multiset(InputIt, InputIt,
0578 size_type = boost::unordered::detail::default_bucket_count,
0579 const hasher& = hasher(), const key_equal& = key_equal(),
0580 const allocator_type& = allocator_type());
0581
0582 unordered_multiset(unordered_multiset const&);
0583
0584 unordered_multiset(unordered_multiset&& other)
0585 noexcept(table::nothrow_move_constructible)
0586 : table_(other.table_, boost::unordered::detail::move_tag())
0587 {
0588
0589 }
0590
0591 explicit unordered_multiset(allocator_type const&);
0592
0593 unordered_multiset(unordered_multiset const&, allocator_type const&);
0594
0595 unordered_multiset(unordered_multiset&&, allocator_type const&);
0596
0597 unordered_multiset(std::initializer_list<value_type>,
0598 size_type = boost::unordered::detail::default_bucket_count,
0599 const hasher& = hasher(), const key_equal& l = key_equal(),
0600 const allocator_type& = allocator_type());
0601
0602 explicit unordered_multiset(size_type, const allocator_type&);
0603
0604 explicit unordered_multiset(
0605 size_type, const hasher&, const allocator_type&);
0606
0607 template <class InputIterator>
0608 unordered_multiset(InputIterator, InputIterator, const allocator_type&);
0609
0610 template <class InputIt>
0611 unordered_multiset(InputIt, InputIt, size_type, const allocator_type&);
0612
0613 template <class InputIt>
0614 unordered_multiset(
0615 InputIt, InputIt, size_type, const hasher&, const allocator_type&);
0616
0617 unordered_multiset(
0618 std::initializer_list<value_type>, const allocator_type&);
0619
0620 unordered_multiset(
0621 std::initializer_list<value_type>, size_type, const allocator_type&);
0622
0623 unordered_multiset(std::initializer_list<value_type>, size_type,
0624 const hasher&, const allocator_type&);
0625
0626
0627
0628 ~unordered_multiset() noexcept;
0629
0630
0631 unordered_multiset& operator=(unordered_multiset const& x)
0632 {
0633 table_.assign(x.table_, std::false_type());
0634 return *this;
0635 }
0636
0637 unordered_multiset& operator=(unordered_multiset&& x)
0638 noexcept(value_allocator_traits::is_always_equal::value&&
0639 std::is_nothrow_move_assignable<H>::value&&
0640 std::is_nothrow_move_assignable<P>::value)
0641 {
0642 table_.move_assign(x.table_, std::false_type());
0643 return *this;
0644 }
0645
0646 unordered_multiset& operator=(std::initializer_list<value_type>);
0647
0648 allocator_type get_allocator() const noexcept
0649 {
0650 return table_.node_alloc();
0651 }
0652
0653
0654
0655 iterator begin() noexcept { return iterator(table_.begin()); }
0656
0657 const_iterator begin() const noexcept
0658 {
0659 return const_iterator(table_.begin());
0660 }
0661
0662 iterator end() noexcept { return iterator(); }
0663
0664 const_iterator end() const noexcept { return const_iterator(); }
0665
0666 const_iterator cbegin() const noexcept
0667 {
0668 return const_iterator(table_.begin());
0669 }
0670
0671 const_iterator cend() const noexcept { return const_iterator(); }
0672
0673
0674
0675 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
0676 {
0677 return table_.size_ == 0;
0678 }
0679
0680 size_type size() const noexcept { return table_.size_; }
0681
0682 size_type max_size() const noexcept;
0683
0684
0685
0686 template <class... Args> iterator emplace(Args&&... args)
0687 {
0688 return iterator(table_.emplace_equiv(
0689 boost::unordered::detail::func::construct_node_from_args(
0690 table_.node_alloc(), std::forward<Args>(args)...)));
0691 }
0692
0693 template <class... Args>
0694 iterator emplace_hint(const_iterator hint, Args&&... args)
0695 {
0696 return iterator(table_.emplace_hint_equiv(
0697 hint, boost::unordered::detail::func::construct_node_from_args(
0698 table_.node_alloc(), std::forward<Args>(args)...)));
0699 }
0700
0701 iterator insert(value_type const& x) { return this->emplace(x); }
0702
0703 iterator insert(value_type&& x) { return this->emplace(std::move(x)); }
0704
0705 iterator insert(const_iterator hint, value_type const& x)
0706 {
0707 return this->emplace_hint(hint, x);
0708 }
0709
0710 iterator insert(const_iterator hint, value_type&& x)
0711 {
0712 return this->emplace_hint(hint, std::move(x));
0713 }
0714
0715 template <class InputIt> void insert(InputIt, InputIt);
0716
0717 void insert(std::initializer_list<value_type>);
0718
0719
0720
0721 node_type extract(const_iterator position)
0722 {
0723 return node_type(
0724 table_.extract_by_iterator_equiv(position), table_.node_alloc());
0725 }
0726
0727 node_type extract(const key_type& k)
0728 {
0729 return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0730 }
0731
0732 template <class Key>
0733 typename boost::enable_if_c<
0734 detail::transparent_non_iterable<Key, unordered_multiset>::value,
0735 node_type>::type
0736 extract(const Key& k)
0737 {
0738 return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
0739 }
0740
0741 iterator insert(node_type&& np)
0742 {
0743 return table_.move_insert_node_type_equiv(np);
0744 }
0745
0746 iterator insert(const_iterator hint, node_type&& np)
0747 {
0748 return table_.move_insert_node_type_with_hint_equiv(hint, np);
0749 }
0750
0751 iterator erase(const_iterator);
0752 size_type erase(const key_type&);
0753
0754 template <class Key>
0755 typename boost::enable_if_c<
0756 detail::transparent_non_iterable<Key, unordered_multiset>::value,
0757 size_type>::type
0758 erase(const Key& k)
0759 {
0760 return table_.erase_key_equiv_impl(k);
0761 }
0762
0763 iterator erase(const_iterator, const_iterator);
0764 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0765 void quick_erase(const_iterator it) { erase(it); }
0766 BOOST_UNORDERED_DEPRECATED("Use erase instead")
0767 void erase_return_void(const_iterator it) { erase(it); }
0768
0769 void swap(unordered_multiset&)
0770 noexcept(value_allocator_traits::is_always_equal::value&&
0771 boost::unordered::detail::is_nothrow_swappable<H>::value&&
0772 boost::unordered::detail::is_nothrow_swappable<P>::value);
0773 void clear() noexcept { table_.clear_impl(); }
0774
0775 template <typename H2, typename P2>
0776 void merge(boost::unordered_multiset<T, H2, P2, A>& source);
0777
0778 template <typename H2, typename P2>
0779 void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
0780
0781 template <typename H2, typename P2>
0782 void merge(boost::unordered_set<T, H2, P2, A>& source);
0783
0784 template <typename H2, typename P2>
0785 void merge(boost::unordered_set<T, H2, P2, A>&& source);
0786
0787
0788
0789 hasher hash_function() const;
0790 key_equal key_eq() const;
0791
0792
0793
0794 const_iterator find(const key_type&) const;
0795
0796 template <class Key>
0797 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0798 const_iterator>::type
0799 find(const Key& k) const
0800 {
0801 return table_.find(k);
0802 }
0803
0804 template <class CompatibleKey, class CompatibleHash,
0805 class CompatiblePredicate>
0806 const_iterator find(CompatibleKey const&, CompatibleHash const&,
0807 CompatiblePredicate const&) const;
0808
0809 bool contains(const key_type& k) const
0810 {
0811 return table_.find(k) != this->end();
0812 }
0813
0814 template <class Key>
0815 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0816 bool>::type
0817 contains(const Key& k) const
0818 {
0819 return table_.find(k) != this->end();
0820 }
0821
0822 size_type count(const key_type&) const;
0823
0824 template <class Key>
0825 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0826 size_type>::type
0827 count(const Key& k) const
0828 {
0829 return table_.group_count(k);
0830 }
0831
0832 std::pair<const_iterator, const_iterator> equal_range(
0833 const key_type&) const;
0834
0835 template <class Key>
0836 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0837 std::pair<const_iterator, const_iterator> >::type
0838 equal_range(const Key& k) const
0839 {
0840 iterator first = table_.find(k);
0841 iterator last = table_.next_group(k, first);
0842 return std::make_pair(const_iterator(first), const_iterator(last));
0843 }
0844
0845
0846
0847 size_type bucket_count() const noexcept { return table_.bucket_count(); }
0848
0849 size_type max_bucket_count() const noexcept
0850 {
0851 return table_.max_bucket_count();
0852 }
0853
0854 size_type bucket_size(size_type) const;
0855
0856 size_type bucket(const key_type& k) const
0857 {
0858 return table_.hash_to_bucket(table_.hash(k));
0859 }
0860
0861 template <class Key>
0862 typename boost::enable_if_c<detail::are_transparent<Key, H, P>::value,
0863 size_type>::type
0864 bucket(Key&& k) const
0865 {
0866 return table_.hash_to_bucket(table_.hash(std::forward<Key>(k)));
0867 }
0868
0869 local_iterator begin(size_type n)
0870 {
0871 return local_iterator(table_.begin(n));
0872 }
0873
0874 const_local_iterator begin(size_type n) const
0875 {
0876 return const_local_iterator(table_.begin(n));
0877 }
0878
0879 local_iterator end(size_type) { return local_iterator(); }
0880
0881 const_local_iterator end(size_type) const
0882 {
0883 return const_local_iterator();
0884 }
0885
0886 const_local_iterator cbegin(size_type n) const
0887 {
0888 return const_local_iterator(table_.begin(n));
0889 }
0890
0891 const_local_iterator cend(size_type) const
0892 {
0893 return const_local_iterator();
0894 }
0895
0896
0897
0898 float load_factor() const noexcept;
0899 float max_load_factor() const noexcept { return table_.mlf_; }
0900 void max_load_factor(float) noexcept;
0901 void rehash(size_type);
0902 void reserve(size_type);
0903
0904 #if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0582)
0905 friend bool operator==
0906 <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
0907 friend bool operator!=
0908 <T, H, P, A>(unordered_multiset const&, unordered_multiset const&);
0909 #endif
0910 };
0911
0912 template <class Archive, class K, class H, class P, class A>
0913 void serialize(
0914 Archive& ar, unordered_multiset<K, H, P, A>& c, unsigned int version)
0915 {
0916 detail::serialize_fca_container(ar, c, version);
0917 }
0918
0919 #if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
0920
0921 template <class InputIterator,
0922 class Hash =
0923 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0924 class Pred =
0925 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0926 class Allocator = std::allocator<
0927 typename std::iterator_traits<InputIterator>::value_type>,
0928 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0929 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0930 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0931 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0932 unordered_multiset(InputIterator, InputIterator,
0933 std::size_t = boost::unordered::detail::default_bucket_count,
0934 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0935 -> unordered_multiset<
0936 typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
0937 Allocator>;
0938
0939 template <class T, class Hash = boost::hash<T>,
0940 class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
0941 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0942 class = std::enable_if_t<detail::is_pred_v<Pred> >,
0943 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0944 unordered_multiset(std::initializer_list<T>,
0945 std::size_t = boost::unordered::detail::default_bucket_count,
0946 Hash = Hash(), Pred = Pred(), Allocator = Allocator())
0947 -> unordered_multiset<T, Hash, Pred, Allocator>;
0948
0949 template <class InputIterator, class Allocator,
0950 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0951 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0952 unordered_multiset(InputIterator, InputIterator, std::size_t, Allocator)
0953 -> unordered_multiset<
0954 typename std::iterator_traits<InputIterator>::value_type,
0955 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0956 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0957 Allocator>;
0958
0959 template <class InputIterator, class Hash, class Allocator,
0960 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0961 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0962 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0963 unordered_multiset(
0964 InputIterator, InputIterator, std::size_t, Hash, Allocator)
0965 -> unordered_multiset<
0966 typename std::iterator_traits<InputIterator>::value_type, Hash,
0967 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0968 Allocator>;
0969
0970 template <class T, class Allocator,
0971 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0972 unordered_multiset(std::initializer_list<T>, std::size_t, Allocator)
0973 -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0974
0975 template <class T, class Hash, class Allocator,
0976 class = std::enable_if_t<detail::is_hash_v<Hash> >,
0977 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0978 unordered_multiset(std::initializer_list<T>, std::size_t, Hash, Allocator)
0979 -> unordered_multiset<T, Hash, std::equal_to<T>, Allocator>;
0980
0981 template <class InputIterator, class Allocator,
0982 class = std::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
0983 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0984 unordered_multiset(InputIterator, InputIterator, Allocator)
0985 -> unordered_multiset<
0986 typename std::iterator_traits<InputIterator>::value_type,
0987 boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
0988 std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
0989 Allocator>;
0990
0991 template <class T, class Allocator,
0992 class = std::enable_if_t<detail::is_allocator_v<Allocator> > >
0993 unordered_multiset(std::initializer_list<T>, Allocator)
0994 -> unordered_multiset<T, boost::hash<T>, std::equal_to<T>, Allocator>;
0995
0996 #endif
0997
0998
0999 template <class T, class H, class P, class A>
1000 unordered_set<T, H, P, A>::unordered_set()
1001 {
1002 }
1003
1004 template <class T, class H, class P, class A>
1005 unordered_set<T, H, P, A>::unordered_set(size_type n, const hasher& hf,
1006 const key_equal& eql, const allocator_type& a)
1007 : table_(n, hf, eql, a)
1008 {
1009 }
1010
1011 template <class T, class H, class P, class A>
1012 template <class InputIt>
1013 unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
1014 const hasher& hf, const key_equal& eql, const allocator_type& a)
1015 : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1016 {
1017 this->insert(f, l);
1018 }
1019
1020 template <class T, class H, class P, class A>
1021 unordered_set<T, H, P, A>::unordered_set(unordered_set const& other)
1022 : table_(other.table_,
1023 unordered_set::value_allocator_traits::
1024 select_on_container_copy_construction(other.get_allocator()))
1025 {
1026 if (other.size()) {
1027 table_.copy_buckets(other.table_, std::true_type());
1028 }
1029 }
1030
1031 template <class T, class H, class P, class A>
1032 unordered_set<T, H, P, A>::unordered_set(allocator_type const& a)
1033 : table_(boost::unordered::detail::default_bucket_count, hasher(),
1034 key_equal(), a)
1035 {
1036 }
1037
1038 template <class T, class H, class P, class A>
1039 unordered_set<T, H, P, A>::unordered_set(
1040 unordered_set const& other, allocator_type const& a)
1041 : table_(other.table_, a)
1042 {
1043 if (other.table_.size_) {
1044 table_.copy_buckets(other.table_, std::true_type());
1045 }
1046 }
1047
1048 template <class T, class H, class P, class A>
1049 unordered_set<T, H, P, A>::unordered_set(
1050 unordered_set&& other, allocator_type const& a)
1051 : table_(other.table_, a, boost::unordered::detail::move_tag())
1052 {
1053 table_.move_construct_buckets(other.table_);
1054 }
1055
1056 template <class T, class H, class P, class A>
1057 unordered_set<T, H, P, A>::unordered_set(
1058 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1059 const key_equal& eql, const allocator_type& a)
1060 : table_(
1061 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1062 hf, eql, a)
1063 {
1064 this->insert(list.begin(), list.end());
1065 }
1066
1067 template <class T, class H, class P, class A>
1068 unordered_set<T, H, P, A>::unordered_set(
1069 size_type n, const allocator_type& a)
1070 : table_(n, hasher(), key_equal(), a)
1071 {
1072 }
1073
1074 template <class T, class H, class P, class A>
1075 unordered_set<T, H, P, A>::unordered_set(
1076 size_type n, const hasher& hf, const allocator_type& a)
1077 : table_(n, hf, key_equal(), a)
1078 {
1079 }
1080
1081 template <class T, class H, class P, class A>
1082 template <class InputIterator>
1083 unordered_set<T, H, P, A>::unordered_set(
1084 InputIterator f, InputIterator l, const allocator_type& a)
1085 : table_(boost::unordered::detail::initial_size(
1086 f, l, detail::default_bucket_count),
1087 hasher(), key_equal(), a)
1088 {
1089 this->insert(f, l);
1090 }
1091
1092 template <class T, class H, class P, class A>
1093 template <class InputIt>
1094 unordered_set<T, H, P, A>::unordered_set(
1095 InputIt f, InputIt l, size_type n, const allocator_type& a)
1096 : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1097 key_equal(), a)
1098 {
1099 this->insert(f, l);
1100 }
1101
1102 template <class T, class H, class P, class A>
1103 template <class InputIt>
1104 unordered_set<T, H, P, A>::unordered_set(InputIt f, InputIt l, size_type n,
1105 const hasher& hf, const allocator_type& a)
1106 : table_(
1107 boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1108 {
1109 this->insert(f, l);
1110 }
1111
1112 template <class T, class H, class P, class A>
1113 unordered_set<T, H, P, A>::unordered_set(
1114 std::initializer_list<value_type> list, const allocator_type& a)
1115 : table_(boost::unordered::detail::initial_size(
1116 list.begin(), list.end(), detail::default_bucket_count),
1117 hasher(), key_equal(), a)
1118 {
1119 this->insert(list.begin(), list.end());
1120 }
1121
1122 template <class T, class H, class P, class A>
1123 unordered_set<T, H, P, A>::unordered_set(
1124 std::initializer_list<value_type> list, size_type n,
1125 const allocator_type& a)
1126 : table_(
1127 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1128 hasher(), key_equal(), a)
1129 {
1130 this->insert(list.begin(), list.end());
1131 }
1132
1133 template <class T, class H, class P, class A>
1134 unordered_set<T, H, P, A>::unordered_set(
1135 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1136 const allocator_type& a)
1137 : table_(
1138 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1139 hf, key_equal(), a)
1140 {
1141 this->insert(list.begin(), list.end());
1142 }
1143
1144 template <class T, class H, class P, class A>
1145 unordered_set<T, H, P, A>::~unordered_set() noexcept
1146 {
1147 }
1148
1149 template <class T, class H, class P, class A>
1150 unordered_set<T, H, P, A>& unordered_set<T, H, P, A>::operator=(
1151 std::initializer_list<value_type> list)
1152 {
1153 this->clear();
1154 this->insert(list.begin(), list.end());
1155 return *this;
1156 }
1157
1158
1159
1160 template <class T, class H, class P, class A>
1161 std::size_t unordered_set<T, H, P, A>::max_size() const noexcept
1162 {
1163 using namespace std;
1164
1165
1166 return boost::unordered::detail::double_to_size(
1167 ceil(static_cast<double>(table_.mlf_) *
1168 static_cast<double>(table_.max_bucket_count()))) -
1169 1;
1170 }
1171
1172
1173
1174 template <class T, class H, class P, class A>
1175 template <class InputIt>
1176 void unordered_set<T, H, P, A>::insert(InputIt first, InputIt last)
1177 {
1178 if (first != last) {
1179 table_.insert_range_unique(
1180 table::extractor::extract(*first), first, last);
1181 }
1182 }
1183
1184 template <class T, class H, class P, class A>
1185 void unordered_set<T, H, P, A>::insert(
1186 std::initializer_list<value_type> list)
1187 {
1188 this->insert(list.begin(), list.end());
1189 }
1190
1191 template <class T, class H, class P, class A>
1192 typename unordered_set<T, H, P, A>::iterator
1193 unordered_set<T, H, P, A>::erase(const_iterator position)
1194 {
1195 return table_.erase_node(position);
1196 }
1197
1198 template <class T, class H, class P, class A>
1199 typename unordered_set<T, H, P, A>::size_type
1200 unordered_set<T, H, P, A>::erase(const key_type& k)
1201 {
1202 return table_.erase_key_unique_impl(k);
1203 }
1204
1205 template <class T, class H, class P, class A>
1206 typename unordered_set<T, H, P, A>::iterator
1207 unordered_set<T, H, P, A>::erase(const_iterator first, const_iterator last)
1208 {
1209 return table_.erase_nodes_range(first, last);
1210 }
1211
1212 template <class T, class H, class P, class A>
1213 void unordered_set<T, H, P, A>::swap(unordered_set& other)
1214 noexcept(value_allocator_traits::is_always_equal::value&&
1215 boost::unordered::detail::is_nothrow_swappable<H>::value&&
1216 boost::unordered::detail::is_nothrow_swappable<P>::value)
1217 {
1218 table_.swap(other.table_);
1219 }
1220
1221
1222
1223 template <class T, class H, class P, class A>
1224 typename unordered_set<T, H, P, A>::hasher
1225 unordered_set<T, H, P, A>::hash_function() const
1226 {
1227 return table_.hash_function();
1228 }
1229
1230 template <class T, class H, class P, class A>
1231 typename unordered_set<T, H, P, A>::key_equal
1232 unordered_set<T, H, P, A>::key_eq() const
1233 {
1234 return table_.key_eq();
1235 }
1236
1237 template <class T, class H, class P, class A>
1238 template <typename H2, typename P2>
1239 void unordered_set<T, H, P, A>::merge(
1240 boost::unordered_set<T, H2, P2, A>& source)
1241 {
1242 table_.merge_unique(source.table_);
1243 }
1244
1245 template <class T, class H, class P, class A>
1246 template <typename H2, typename P2>
1247 void unordered_set<T, H, P, A>::merge(
1248 boost::unordered_set<T, H2, P2, A>&& source)
1249 {
1250 table_.merge_unique(source.table_);
1251 }
1252
1253 template <class T, class H, class P, class A>
1254 template <typename H2, typename P2>
1255 void unordered_set<T, H, P, A>::merge(
1256 boost::unordered_multiset<T, H2, P2, A>& source)
1257 {
1258 table_.merge_unique(source.table_);
1259 }
1260
1261 template <class T, class H, class P, class A>
1262 template <typename H2, typename P2>
1263 void unordered_set<T, H, P, A>::merge(
1264 boost::unordered_multiset<T, H2, P2, A>&& source)
1265 {
1266 table_.merge_unique(source.table_);
1267 }
1268
1269
1270
1271 template <class T, class H, class P, class A>
1272 typename unordered_set<T, H, P, A>::const_iterator
1273 unordered_set<T, H, P, A>::find(const key_type& k) const
1274 {
1275 return const_iterator(table_.find(k));
1276 }
1277
1278 template <class T, class H, class P, class A>
1279 template <class CompatibleKey, class CompatibleHash,
1280 class CompatiblePredicate>
1281 typename unordered_set<T, H, P, A>::const_iterator
1282 unordered_set<T, H, P, A>::find(CompatibleKey const& k,
1283 CompatibleHash const& hash, CompatiblePredicate const& eq) const
1284 {
1285 return table_.transparent_find(k, hash, eq);
1286 }
1287
1288 template <class T, class H, class P, class A>
1289 typename unordered_set<T, H, P, A>::size_type
1290 unordered_set<T, H, P, A>::count(const key_type& k) const
1291 {
1292 return table_.find_node(k) ? 1 : 0;
1293 }
1294
1295 template <class T, class H, class P, class A>
1296 std::pair<typename unordered_set<T, H, P, A>::const_iterator,
1297 typename unordered_set<T, H, P, A>::const_iterator>
1298 unordered_set<T, H, P, A>::equal_range(const key_type& k) const
1299 {
1300 iterator first = table_.find(k);
1301 iterator second = first;
1302 if (second != this->end()) {
1303 ++second;
1304 }
1305 return std::make_pair(first, second);
1306 }
1307
1308 template <class T, class H, class P, class A>
1309 typename unordered_set<T, H, P, A>::size_type
1310 unordered_set<T, H, P, A>::bucket_size(size_type n) const
1311 {
1312 return table_.bucket_size(n);
1313 }
1314
1315
1316
1317 template <class T, class H, class P, class A>
1318 float unordered_set<T, H, P, A>::load_factor() const noexcept
1319 {
1320 if (table_.size_ == 0) {
1321 return 0.0f;
1322 }
1323
1324 BOOST_ASSERT(table_.bucket_count() != 0);
1325 return static_cast<float>(table_.size_) /
1326 static_cast<float>(table_.bucket_count());
1327 }
1328
1329 template <class T, class H, class P, class A>
1330 void unordered_set<T, H, P, A>::max_load_factor(float m) noexcept
1331 {
1332 table_.max_load_factor(m);
1333 }
1334
1335 template <class T, class H, class P, class A>
1336 void unordered_set<T, H, P, A>::rehash(size_type n)
1337 {
1338 table_.rehash(n);
1339 }
1340
1341 template <class T, class H, class P, class A>
1342 void unordered_set<T, H, P, A>::reserve(size_type n)
1343 {
1344 table_.reserve(n);
1345 }
1346
1347 template <class T, class H, class P, class A>
1348 inline bool operator==(
1349 unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
1350 {
1351 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1352 struct dummy
1353 {
1354 unordered_set<T, H, P, A> x;
1355 };
1356 #endif
1357 return m1.table_.equals_unique(m2.table_);
1358 }
1359
1360 template <class T, class H, class P, class A>
1361 inline bool operator!=(
1362 unordered_set<T, H, P, A> const& m1, unordered_set<T, H, P, A> const& m2)
1363 {
1364 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1365 struct dummy
1366 {
1367 unordered_set<T, H, P, A> x;
1368 };
1369 #endif
1370 return !m1.table_.equals_unique(m2.table_);
1371 }
1372
1373 template <class T, class H, class P, class A>
1374 inline void swap(unordered_set<T, H, P, A>& m1,
1375 unordered_set<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
1376 {
1377 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1378 struct dummy
1379 {
1380 unordered_set<T, H, P, A> x;
1381 };
1382 #endif
1383 m1.swap(m2);
1384 }
1385
1386 template <class K, class H, class P, class A, class Predicate>
1387 typename unordered_set<K, H, P, A>::size_type erase_if(
1388 unordered_set<K, H, P, A>& c, Predicate pred)
1389 {
1390 return detail::erase_if(c, pred);
1391 }
1392
1393
1394
1395 template <class T, class H, class P, class A>
1396 unordered_multiset<T, H, P, A>::unordered_multiset()
1397 {
1398 }
1399
1400 template <class T, class H, class P, class A>
1401 unordered_multiset<T, H, P, A>::unordered_multiset(size_type n,
1402 const hasher& hf, const key_equal& eql, const allocator_type& a)
1403 : table_(n, hf, eql, a)
1404 {
1405 }
1406
1407 template <class T, class H, class P, class A>
1408 template <class InputIt>
1409 unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
1410 size_type n, const hasher& hf, const key_equal& eql,
1411 const allocator_type& a)
1412 : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a)
1413 {
1414 this->insert(f, l);
1415 }
1416
1417 template <class T, class H, class P, class A>
1418 unordered_multiset<T, H, P, A>::unordered_multiset(
1419 unordered_multiset const& other)
1420 : table_(other.table_,
1421 unordered_multiset::value_allocator_traits::
1422 select_on_container_copy_construction(other.get_allocator()))
1423 {
1424 if (other.table_.size_) {
1425 table_.copy_buckets(other.table_, std::false_type());
1426 }
1427 }
1428
1429 template <class T, class H, class P, class A>
1430 unordered_multiset<T, H, P, A>::unordered_multiset(allocator_type const& a)
1431 : table_(boost::unordered::detail::default_bucket_count, hasher(),
1432 key_equal(), a)
1433 {
1434 }
1435
1436 template <class T, class H, class P, class A>
1437 unordered_multiset<T, H, P, A>::unordered_multiset(
1438 unordered_multiset const& other, allocator_type const& a)
1439 : table_(other.table_, a)
1440 {
1441 if (other.table_.size_) {
1442 table_.copy_buckets(other.table_, std::false_type());
1443 }
1444 }
1445
1446 template <class T, class H, class P, class A>
1447 unordered_multiset<T, H, P, A>::unordered_multiset(
1448 unordered_multiset&& other, allocator_type const& a)
1449 : table_(other.table_, a, boost::unordered::detail::move_tag())
1450 {
1451 table_.move_construct_buckets(other.table_);
1452 }
1453
1454 template <class T, class H, class P, class A>
1455 unordered_multiset<T, H, P, A>::unordered_multiset(
1456 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1457 const key_equal& eql, const allocator_type& a)
1458 : table_(
1459 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1460 hf, eql, a)
1461 {
1462 this->insert(list.begin(), list.end());
1463 }
1464
1465 template <class T, class H, class P, class A>
1466 unordered_multiset<T, H, P, A>::unordered_multiset(
1467 size_type n, const allocator_type& a)
1468 : table_(n, hasher(), key_equal(), a)
1469 {
1470 }
1471
1472 template <class T, class H, class P, class A>
1473 unordered_multiset<T, H, P, A>::unordered_multiset(
1474 size_type n, const hasher& hf, const allocator_type& a)
1475 : table_(n, hf, key_equal(), a)
1476 {
1477 }
1478
1479 template <class T, class H, class P, class A>
1480 template <class InputIterator>
1481 unordered_multiset<T, H, P, A>::unordered_multiset(
1482 InputIterator f, InputIterator l, const allocator_type& a)
1483 : table_(boost::unordered::detail::initial_size(
1484 f, l, detail::default_bucket_count),
1485 hasher(), key_equal(), a)
1486 {
1487 this->insert(f, l);
1488 }
1489
1490 template <class T, class H, class P, class A>
1491 template <class InputIt>
1492 unordered_multiset<T, H, P, A>::unordered_multiset(
1493 InputIt f, InputIt l, size_type n, const allocator_type& a)
1494 : table_(boost::unordered::detail::initial_size(f, l, n), hasher(),
1495 key_equal(), a)
1496 {
1497 this->insert(f, l);
1498 }
1499
1500 template <class T, class H, class P, class A>
1501 template <class InputIt>
1502 unordered_multiset<T, H, P, A>::unordered_multiset(InputIt f, InputIt l,
1503 size_type n, const hasher& hf, const allocator_type& a)
1504 : table_(
1505 boost::unordered::detail::initial_size(f, l, n), hf, key_equal(), a)
1506 {
1507 this->insert(f, l);
1508 }
1509
1510 template <class T, class H, class P, class A>
1511 unordered_multiset<T, H, P, A>::unordered_multiset(
1512 std::initializer_list<value_type> list, const allocator_type& a)
1513 : table_(boost::unordered::detail::initial_size(
1514 list.begin(), list.end(), detail::default_bucket_count),
1515 hasher(), key_equal(), a)
1516 {
1517 this->insert(list.begin(), list.end());
1518 }
1519
1520 template <class T, class H, class P, class A>
1521 unordered_multiset<T, H, P, A>::unordered_multiset(
1522 std::initializer_list<value_type> list, size_type n,
1523 const allocator_type& a)
1524 : table_(
1525 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1526 hasher(), key_equal(), a)
1527 {
1528 this->insert(list.begin(), list.end());
1529 }
1530
1531 template <class T, class H, class P, class A>
1532 unordered_multiset<T, H, P, A>::unordered_multiset(
1533 std::initializer_list<value_type> list, size_type n, const hasher& hf,
1534 const allocator_type& a)
1535 : table_(
1536 boost::unordered::detail::initial_size(list.begin(), list.end(), n),
1537 hf, key_equal(), a)
1538 {
1539 this->insert(list.begin(), list.end());
1540 }
1541
1542 template <class T, class H, class P, class A>
1543 unordered_multiset<T, H, P, A>::~unordered_multiset() noexcept
1544 {
1545 }
1546
1547 template <class T, class H, class P, class A>
1548 unordered_multiset<T, H, P, A>& unordered_multiset<T, H, P, A>::operator=(
1549 std::initializer_list<value_type> list)
1550 {
1551 this->clear();
1552 this->insert(list.begin(), list.end());
1553 return *this;
1554 }
1555
1556
1557
1558 template <class T, class H, class P, class A>
1559 std::size_t unordered_multiset<T, H, P, A>::max_size() const noexcept
1560 {
1561 using namespace std;
1562
1563
1564 return boost::unordered::detail::double_to_size(
1565 ceil(static_cast<double>(table_.mlf_) *
1566 static_cast<double>(table_.max_bucket_count()))) -
1567 1;
1568 }
1569
1570
1571
1572 template <class T, class H, class P, class A>
1573 template <class InputIt>
1574 void unordered_multiset<T, H, P, A>::insert(InputIt first, InputIt last)
1575 {
1576 table_.insert_range_equiv(first, last);
1577 }
1578
1579 template <class T, class H, class P, class A>
1580 void unordered_multiset<T, H, P, A>::insert(
1581 std::initializer_list<value_type> list)
1582 {
1583 this->insert(list.begin(), list.end());
1584 }
1585
1586 template <class T, class H, class P, class A>
1587 typename unordered_multiset<T, H, P, A>::iterator
1588 unordered_multiset<T, H, P, A>::erase(const_iterator position)
1589 {
1590 BOOST_ASSERT(position != this->end());
1591 return table_.erase_node(position);
1592 }
1593
1594 template <class T, class H, class P, class A>
1595 typename unordered_multiset<T, H, P, A>::size_type
1596 unordered_multiset<T, H, P, A>::erase(const key_type& k)
1597 {
1598 return table_.erase_key_equiv(k);
1599 }
1600
1601 template <class T, class H, class P, class A>
1602 typename unordered_multiset<T, H, P, A>::iterator
1603 unordered_multiset<T, H, P, A>::erase(
1604 const_iterator first, const_iterator last)
1605 {
1606 return table_.erase_nodes_range(first, last);
1607 }
1608
1609 template <class T, class H, class P, class A>
1610 void unordered_multiset<T, H, P, A>::swap(unordered_multiset& other)
1611 noexcept(value_allocator_traits::is_always_equal::value&&
1612 boost::unordered::detail::is_nothrow_swappable<H>::value&&
1613 boost::unordered::detail::is_nothrow_swappable<P>::value)
1614 {
1615 table_.swap(other.table_);
1616 }
1617
1618
1619
1620 template <class T, class H, class P, class A>
1621 typename unordered_multiset<T, H, P, A>::hasher
1622 unordered_multiset<T, H, P, A>::hash_function() const
1623 {
1624 return table_.hash_function();
1625 }
1626
1627 template <class T, class H, class P, class A>
1628 typename unordered_multiset<T, H, P, A>::key_equal
1629 unordered_multiset<T, H, P, A>::key_eq() const
1630 {
1631 return table_.key_eq();
1632 }
1633
1634 template <class T, class H, class P, class A>
1635 template <typename H2, typename P2>
1636 void unordered_multiset<T, H, P, A>::merge(
1637 boost::unordered_multiset<T, H2, P2, A>& source)
1638 {
1639 while (!source.empty()) {
1640 insert(source.extract(source.begin()));
1641 }
1642 }
1643
1644 template <class T, class H, class P, class A>
1645 template <typename H2, typename P2>
1646 void unordered_multiset<T, H, P, A>::merge(
1647 boost::unordered_multiset<T, H2, P2, A>&& source)
1648 {
1649 while (!source.empty()) {
1650 insert(source.extract(source.begin()));
1651 }
1652 }
1653
1654 template <class T, class H, class P, class A>
1655 template <typename H2, typename P2>
1656 void unordered_multiset<T, H, P, A>::merge(
1657 boost::unordered_set<T, H2, P2, A>& source)
1658 {
1659 while (!source.empty()) {
1660 insert(source.extract(source.begin()));
1661 }
1662 }
1663
1664 template <class T, class H, class P, class A>
1665 template <typename H2, typename P2>
1666 void unordered_multiset<T, H, P, A>::merge(
1667 boost::unordered_set<T, H2, P2, A>&& source)
1668 {
1669 while (!source.empty()) {
1670 insert(source.extract(source.begin()));
1671 }
1672 }
1673
1674
1675
1676 template <class T, class H, class P, class A>
1677 typename unordered_multiset<T, H, P, A>::const_iterator
1678 unordered_multiset<T, H, P, A>::find(const key_type& k) const
1679 {
1680 return const_iterator(table_.find(k));
1681 }
1682
1683 template <class T, class H, class P, class A>
1684 template <class CompatibleKey, class CompatibleHash,
1685 class CompatiblePredicate>
1686 typename unordered_multiset<T, H, P, A>::const_iterator
1687 unordered_multiset<T, H, P, A>::find(CompatibleKey const& k,
1688 CompatibleHash const& hash, CompatiblePredicate const& eq) const
1689 {
1690 return table_.transparent_find(k, hash, eq);
1691 }
1692
1693 template <class T, class H, class P, class A>
1694 typename unordered_multiset<T, H, P, A>::size_type
1695 unordered_multiset<T, H, P, A>::count(const key_type& k) const
1696 {
1697 return table_.group_count(k);
1698 }
1699
1700 template <class T, class H, class P, class A>
1701 std::pair<typename unordered_multiset<T, H, P, A>::const_iterator,
1702 typename unordered_multiset<T, H, P, A>::const_iterator>
1703 unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
1704 {
1705 iterator n = table_.find(k);
1706 return std::make_pair(const_iterator(n),
1707 const_iterator(n == end() ? n : table_.next_group(k, n)));
1708 }
1709
1710 template <class T, class H, class P, class A>
1711 typename unordered_multiset<T, H, P, A>::size_type
1712 unordered_multiset<T, H, P, A>::bucket_size(size_type n) const
1713 {
1714 return table_.bucket_size(n);
1715 }
1716
1717
1718
1719 template <class T, class H, class P, class A>
1720 float unordered_multiset<T, H, P, A>::load_factor() const noexcept
1721 {
1722 if (table_.size_ == 0) {
1723 return 0.0f;
1724 }
1725
1726 BOOST_ASSERT(table_.bucket_count() != 0);
1727 return static_cast<float>(table_.size_) /
1728 static_cast<float>(table_.bucket_count());
1729 }
1730
1731 template <class T, class H, class P, class A>
1732 void unordered_multiset<T, H, P, A>::max_load_factor(float m) noexcept
1733 {
1734 table_.max_load_factor(m);
1735 }
1736
1737 template <class T, class H, class P, class A>
1738 void unordered_multiset<T, H, P, A>::rehash(size_type n)
1739 {
1740 table_.rehash(n);
1741 }
1742
1743 template <class T, class H, class P, class A>
1744 void unordered_multiset<T, H, P, A>::reserve(size_type n)
1745 {
1746 table_.reserve(n);
1747 }
1748
1749 template <class T, class H, class P, class A>
1750 inline bool operator==(unordered_multiset<T, H, P, A> const& m1,
1751 unordered_multiset<T, H, P, A> const& m2)
1752 {
1753 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1754 struct dummy
1755 {
1756 unordered_multiset<T, H, P, A> x;
1757 };
1758 #endif
1759 return m1.table_.equals_equiv(m2.table_);
1760 }
1761
1762 template <class T, class H, class P, class A>
1763 inline bool operator!=(unordered_multiset<T, H, P, A> const& m1,
1764 unordered_multiset<T, H, P, A> const& m2)
1765 {
1766 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1767 struct dummy
1768 {
1769 unordered_multiset<T, H, P, A> x;
1770 };
1771 #endif
1772 return !m1.table_.equals_equiv(m2.table_);
1773 }
1774
1775 template <class T, class H, class P, class A>
1776 inline void swap(unordered_multiset<T, H, P, A>& m1,
1777 unordered_multiset<T, H, P, A>& m2) noexcept(noexcept(m1.swap(m2)))
1778 {
1779 #if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
1780 struct dummy
1781 {
1782 unordered_multiset<T, H, P, A> x;
1783 };
1784 #endif
1785 m1.swap(m2);
1786 }
1787
1788 template <class K, class H, class P, class A, class Predicate>
1789 typename unordered_multiset<K, H, P, A>::size_type erase_if(
1790 unordered_multiset<K, H, P, A>& c, Predicate pred)
1791 {
1792 return detail::erase_if(c, pred);
1793 }
1794
1795 template <typename N, typename T, typename A> class node_handle_set
1796 {
1797 template <typename Types> friend struct ::boost::unordered::detail::table;
1798 template <class T2, class H2, class P2, class A2>
1799 friend class unordered_set;
1800 template <class T2, class H2, class P2, class A2>
1801 friend class unordered_multiset;
1802
1803 typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
1804 value_allocator;
1805 typedef boost::unordered::detail::allocator_traits<value_allocator>
1806 value_allocator_traits;
1807 typedef N node;
1808 typedef typename boost::unordered::detail::rebind_wrap<A, node>::type
1809 node_allocator;
1810 typedef boost::unordered::detail::allocator_traits<node_allocator>
1811 node_allocator_traits;
1812 typedef typename node_allocator_traits::pointer node_pointer;
1813
1814 public:
1815 typedef T value_type;
1816 typedef A allocator_type;
1817
1818 private:
1819 node_pointer ptr_;
1820 bool has_alloc_;
1821 boost::unordered::detail::optional<value_allocator> alloc_;
1822
1823 node_handle_set(node_pointer ptr, allocator_type const& a)
1824 : ptr_(ptr), alloc_(a)
1825 {
1826 }
1827
1828 public:
1829 constexpr node_handle_set() noexcept : ptr_(), has_alloc_(false) {}
1830 node_handle_set(node_handle_set const&) = delete;
1831 node_handle_set& operator=(node_handle_set const&) = delete;
1832
1833 ~node_handle_set()
1834 {
1835 if (ptr_) {
1836 node_allocator node_alloc(*alloc_);
1837 boost::unordered::detail::node_tmp<node_allocator> tmp(
1838 ptr_, node_alloc);
1839 }
1840 }
1841
1842 node_handle_set(node_handle_set&& n) noexcept
1843 : ptr_(n.ptr_),
1844 alloc_(std::move(n.alloc_))
1845 {
1846 n.ptr_ = node_pointer();
1847 }
1848
1849 node_handle_set& operator=(node_handle_set&& n)
1850 {
1851 BOOST_ASSERT(!alloc_.has_value() ||
1852 value_allocator_traits::
1853 propagate_on_container_move_assignment::value ||
1854 (n.alloc_.has_value() && alloc_ == n.alloc_));
1855
1856 if (ptr_) {
1857 node_allocator node_alloc(*alloc_);
1858 boost::unordered::detail::node_tmp<node_allocator> tmp(
1859 ptr_, node_alloc);
1860 ptr_ = node_pointer();
1861 }
1862
1863 if (!alloc_.has_value() ||
1864 value_allocator_traits::propagate_on_container_move_assignment::
1865 value) {
1866 alloc_ = std::move(n.alloc_);
1867 }
1868 ptr_ = n.ptr_;
1869 n.ptr_ = node_pointer();
1870
1871 return *this;
1872 }
1873
1874 value_type& value() const { return ptr_->value(); }
1875
1876 allocator_type get_allocator() const { return *alloc_; }
1877
1878 explicit operator bool() const noexcept
1879 {
1880 return !this->operator!();
1881 }
1882
1883 bool operator!() const noexcept { return ptr_ ? 0 : 1; }
1884
1885 BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
1886 {
1887 return ptr_ ? 0 : 1;
1888 }
1889
1890 void swap(node_handle_set& n)
1891 noexcept(value_allocator_traits::propagate_on_container_swap::value ||
1892 value_allocator_traits::is_always_equal::value)
1893 {
1894 BOOST_ASSERT(
1895 !alloc_.has_value() || !n.alloc_.has_value() ||
1896 value_allocator_traits::propagate_on_container_swap::value ||
1897 alloc_ == n.alloc_);
1898 if (value_allocator_traits::propagate_on_container_swap::value ||
1899 !alloc_.has_value() || !n.alloc_.has_value()) {
1900 boost::core::invoke_swap(alloc_, n.alloc_);
1901 }
1902 boost::core::invoke_swap(ptr_, n.ptr_);
1903 }
1904 };
1905
1906 template <typename N, typename T, typename A>
1907 void swap(node_handle_set<N, T, A>& x, node_handle_set<N, T, A>& y)
1908 noexcept(noexcept(x.swap(y)))
1909 {
1910 x.swap(y);
1911 }
1912
1913 template <class Iter, class NodeType> struct insert_return_type_set
1914 {
1915 public:
1916 Iter position;
1917 bool inserted;
1918 NodeType node;
1919
1920 insert_return_type_set() : position(), inserted(false), node() {}
1921 insert_return_type_set(insert_return_type_set const&) = delete;
1922 insert_return_type_set& operator=(insert_return_type_set const&) = delete;
1923
1924 insert_return_type_set(insert_return_type_set&& x) noexcept
1925 : position(x.position),
1926 inserted(x.inserted),
1927 node(std::move(x.node))
1928 {
1929 }
1930
1931 insert_return_type_set& operator=(insert_return_type_set&& x)
1932 {
1933 inserted = x.inserted;
1934 position = x.position;
1935 node = std::move(x.node);
1936 return *this;
1937 }
1938 };
1939
1940 template <class Iter, class NodeType>
1941 void swap(insert_return_type_set<Iter, NodeType>& x,
1942 insert_return_type_set<Iter, NodeType>& y)
1943 {
1944 boost::core::invoke_swap(x.node, y.node);
1945 boost::core::invoke_swap(x.inserted, y.inserted);
1946 boost::core::invoke_swap(x.position, y.position);
1947 }
1948 }
1949
1950 namespace serialization {
1951 template <class K, class H, class P, class A>
1952 struct version<boost::unordered_set<K, H, P, A> >
1953 {
1954 BOOST_STATIC_CONSTANT(int, value = 1);
1955 };
1956
1957 template <class K, class H, class P, class A>
1958 struct version<boost::unordered_multiset<K, H, P, A> >
1959 {
1960 BOOST_STATIC_CONSTANT(int, value = 1);
1961 };
1962 }
1963
1964 }
1965
1966 #if defined(BOOST_MSVC)
1967 #pragma warning(pop)
1968 #endif
1969
1970 #endif