File indexing completed on 2025-01-18 09:27:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
0016 #define ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
0017
0018 #include <algorithm>
0019 #include <initializer_list>
0020 #include <iterator>
0021 #include <utility>
0022
0023 #include "absl/base/attributes.h"
0024 #include "absl/base/internal/throw_delegate.h"
0025 #include "absl/container/internal/btree.h" // IWYU pragma: export
0026 #include "absl/container/internal/common.h"
0027 #include "absl/memory/memory.h"
0028 #include "absl/meta/type_traits.h"
0029
0030 namespace absl {
0031 ABSL_NAMESPACE_BEGIN
0032 namespace container_internal {
0033
0034
0035
0036 template <typename Tree>
0037 class btree_container {
0038 using params_type = typename Tree::params_type;
0039
0040 protected:
0041
0042
0043
0044
0045 template <class K>
0046 using key_arg =
0047 typename KeyArg<params_type::kIsKeyCompareTransparent>::template type<
0048 K, typename Tree::key_type>;
0049
0050 public:
0051 using key_type = typename Tree::key_type;
0052 using value_type = typename Tree::value_type;
0053 using size_type = typename Tree::size_type;
0054 using difference_type = typename Tree::difference_type;
0055 using key_compare = typename Tree::original_key_compare;
0056 using value_compare = typename Tree::value_compare;
0057 using allocator_type = typename Tree::allocator_type;
0058 using reference = typename Tree::reference;
0059 using const_reference = typename Tree::const_reference;
0060 using pointer = typename Tree::pointer;
0061 using const_pointer = typename Tree::const_pointer;
0062 using iterator = typename Tree::iterator;
0063 using const_iterator = typename Tree::const_iterator;
0064 using reverse_iterator = typename Tree::reverse_iterator;
0065 using const_reverse_iterator = typename Tree::const_reverse_iterator;
0066 using node_type = typename Tree::node_handle_type;
0067
0068 struct extract_and_get_next_return_type {
0069 node_type node;
0070 iterator next;
0071 };
0072
0073
0074 btree_container() : tree_(key_compare(), allocator_type()) {}
0075 explicit btree_container(const key_compare &comp,
0076 const allocator_type &alloc = allocator_type())
0077 : tree_(comp, alloc) {}
0078 explicit btree_container(const allocator_type &alloc)
0079 : tree_(key_compare(), alloc) {}
0080
0081 btree_container(const btree_container &other)
0082 : btree_container(other, absl::allocator_traits<allocator_type>::
0083 select_on_container_copy_construction(
0084 other.get_allocator())) {}
0085 btree_container(const btree_container &other, const allocator_type &alloc)
0086 : tree_(other.tree_, alloc) {}
0087
0088 btree_container(btree_container &&other) noexcept(
0089 std::is_nothrow_move_constructible<Tree>::value) = default;
0090 btree_container(btree_container &&other, const allocator_type &alloc)
0091 : tree_(std::move(other.tree_), alloc) {}
0092
0093 btree_container &operator=(const btree_container &other) = default;
0094 btree_container &operator=(btree_container &&other) noexcept(
0095 std::is_nothrow_move_assignable<Tree>::value) = default;
0096
0097
0098 iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.begin(); }
0099 const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0100 return tree_.begin();
0101 }
0102 const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0103 return tree_.begin();
0104 }
0105 iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.end(); }
0106 const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0107 return tree_.end();
0108 }
0109 const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0110 return tree_.end();
0111 }
0112 reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
0113 return tree_.rbegin();
0114 }
0115 const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0116 return tree_.rbegin();
0117 }
0118 const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0119 return tree_.rbegin();
0120 }
0121 reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.rend(); }
0122 const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0123 return tree_.rend();
0124 }
0125 const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0126 return tree_.rend();
0127 }
0128
0129
0130 template <typename K = key_type>
0131 size_type count(const key_arg<K> &key) const {
0132 auto equal_range = this->equal_range(key);
0133 return equal_range.second - equal_range.first;
0134 }
0135 template <typename K = key_type>
0136 iterator find(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0137 return tree_.find(key);
0138 }
0139 template <typename K = key_type>
0140 const_iterator find(const key_arg<K> &key) const
0141 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0142 return tree_.find(key);
0143 }
0144 template <typename K = key_type>
0145 bool contains(const key_arg<K> &key) const {
0146 return find(key) != end();
0147 }
0148 template <typename K = key_type>
0149 iterator lower_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0150 return tree_.lower_bound(key);
0151 }
0152 template <typename K = key_type>
0153 const_iterator lower_bound(const key_arg<K> &key) const
0154 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0155 return tree_.lower_bound(key);
0156 }
0157 template <typename K = key_type>
0158 iterator upper_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0159 return tree_.upper_bound(key);
0160 }
0161 template <typename K = key_type>
0162 const_iterator upper_bound(const key_arg<K> &key) const
0163 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0164 return tree_.upper_bound(key);
0165 }
0166 template <typename K = key_type>
0167 std::pair<iterator, iterator> equal_range(const key_arg<K> &key)
0168 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0169 return tree_.equal_range(key);
0170 }
0171 template <typename K = key_type>
0172 std::pair<const_iterator, const_iterator> equal_range(
0173 const key_arg<K> &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
0174 return tree_.equal_range(key);
0175 }
0176
0177
0178
0179
0180
0181
0182
0183 iterator erase(const_iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0184 return tree_.erase(iterator(iter));
0185 }
0186 iterator erase(iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0187 return tree_.erase(iter);
0188 }
0189 iterator erase(const_iterator first,
0190 const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0191 return tree_.erase_range(iterator(first), iterator(last)).second;
0192 }
0193 template <typename K = key_type>
0194 size_type erase(const key_arg<K> &key) {
0195 auto equal_range = this->equal_range(key);
0196 return tree_.erase_range(equal_range.first, equal_range.second).first;
0197 }
0198
0199
0200 extract_and_get_next_return_type extract_and_get_next(const_iterator position)
0201 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0202
0203
0204
0205 return {CommonAccess::Construct<node_type>(get_allocator(),
0206 iterator(position).slot()),
0207 erase(position)};
0208 }
0209 node_type extract(iterator position) {
0210
0211
0212 auto node =
0213 CommonAccess::Construct<node_type>(get_allocator(), position.slot());
0214 erase(position);
0215 return node;
0216 }
0217 node_type extract(const_iterator position) {
0218 return extract(iterator(position));
0219 }
0220
0221
0222 ABSL_ATTRIBUTE_REINITIALIZES void clear() { tree_.clear(); }
0223 void swap(btree_container &other) { tree_.swap(other.tree_); }
0224 void verify() const { tree_.verify(); }
0225
0226
0227 size_type size() const { return tree_.size(); }
0228 size_type max_size() const { return tree_.max_size(); }
0229 bool empty() const { return tree_.empty(); }
0230
0231 friend bool operator==(const btree_container &x, const btree_container &y) {
0232 if (x.size() != y.size()) return false;
0233 return std::equal(x.begin(), x.end(), y.begin());
0234 }
0235
0236 friend bool operator!=(const btree_container &x, const btree_container &y) {
0237 return !(x == y);
0238 }
0239
0240 friend bool operator<(const btree_container &x, const btree_container &y) {
0241 return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
0242 }
0243
0244 friend bool operator>(const btree_container &x, const btree_container &y) {
0245 return y < x;
0246 }
0247
0248 friend bool operator<=(const btree_container &x, const btree_container &y) {
0249 return !(y < x);
0250 }
0251
0252 friend bool operator>=(const btree_container &x, const btree_container &y) {
0253 return !(x < y);
0254 }
0255
0256
0257 allocator_type get_allocator() const { return tree_.get_allocator(); }
0258
0259
0260 key_compare key_comp() const { return key_compare(tree_.key_comp()); }
0261 value_compare value_comp() const { return tree_.value_comp(); }
0262
0263
0264 template <typename State>
0265 friend State AbslHashValue(State h, const btree_container &b) {
0266 for (const auto &v : b) {
0267 h = State::combine(std::move(h), v);
0268 }
0269 return State::combine(std::move(h), b.size());
0270 }
0271
0272 protected:
0273 friend struct btree_access;
0274 Tree tree_;
0275 };
0276
0277
0278 template <typename Tree>
0279 class btree_set_container : public btree_container<Tree> {
0280 using super_type = btree_container<Tree>;
0281 using params_type = typename Tree::params_type;
0282 using init_type = typename params_type::init_type;
0283 using is_key_compare_to = typename params_type::is_key_compare_to;
0284 friend class BtreeNodePeer;
0285
0286 protected:
0287 template <class K>
0288 using key_arg = typename super_type::template key_arg<K>;
0289
0290 public:
0291 using key_type = typename Tree::key_type;
0292 using value_type = typename Tree::value_type;
0293 using size_type = typename Tree::size_type;
0294 using key_compare = typename Tree::original_key_compare;
0295 using allocator_type = typename Tree::allocator_type;
0296 using iterator = typename Tree::iterator;
0297 using const_iterator = typename Tree::const_iterator;
0298 using node_type = typename super_type::node_type;
0299 using insert_return_type = InsertReturnType<iterator, node_type>;
0300
0301
0302 using super_type::super_type;
0303 btree_set_container() {}
0304
0305
0306 template <class InputIterator>
0307 btree_set_container(InputIterator b, InputIterator e,
0308 const key_compare &comp = key_compare(),
0309 const allocator_type &alloc = allocator_type())
0310 : super_type(comp, alloc) {
0311 insert(b, e);
0312 }
0313 template <class InputIterator>
0314 btree_set_container(InputIterator b, InputIterator e,
0315 const allocator_type &alloc)
0316 : btree_set_container(b, e, key_compare(), alloc) {}
0317
0318
0319 btree_set_container(std::initializer_list<init_type> init,
0320 const key_compare &comp = key_compare(),
0321 const allocator_type &alloc = allocator_type())
0322 : btree_set_container(init.begin(), init.end(), comp, alloc) {}
0323 btree_set_container(std::initializer_list<init_type> init,
0324 const allocator_type &alloc)
0325 : btree_set_container(init.begin(), init.end(), alloc) {}
0326
0327
0328 std::pair<iterator, bool> insert(const value_type &v)
0329 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0330 return this->tree_.insert_unique(params_type::key(v), v);
0331 }
0332 std::pair<iterator, bool> insert(value_type &&v)
0333 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0334 return this->tree_.insert_unique(params_type::key(v), std::move(v));
0335 }
0336 template <typename... Args>
0337 std::pair<iterator, bool> emplace(Args &&...args)
0338 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0339
0340 auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
0341 std::forward<Args>(args)...);
0342 auto *slot = CommonAccess::GetSlot(node);
0343 return this->tree_.insert_unique(params_type::key(slot), slot);
0344 }
0345 iterator insert(const_iterator hint,
0346 const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0347 return this->tree_
0348 .insert_hint_unique(iterator(hint), params_type::key(v), v)
0349 .first;
0350 }
0351 iterator insert(const_iterator hint,
0352 value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0353 return this->tree_
0354 .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
0355 .first;
0356 }
0357 template <typename... Args>
0358 iterator emplace_hint(const_iterator hint,
0359 Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0360
0361 auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
0362 std::forward<Args>(args)...);
0363 auto *slot = CommonAccess::GetSlot(node);
0364 return this->tree_
0365 .insert_hint_unique(iterator(hint), params_type::key(slot), slot)
0366 .first;
0367 }
0368 template <typename InputIterator>
0369 void insert(InputIterator b, InputIterator e) {
0370 this->tree_.insert_iterator_unique(b, e, 0);
0371 }
0372 void insert(std::initializer_list<init_type> init) {
0373 this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);
0374 }
0375 insert_return_type insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0376 if (!node) return {this->end(), false, node_type()};
0377 std::pair<iterator, bool> res =
0378 this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
0379 CommonAccess::GetSlot(node));
0380 if (res.second) {
0381 CommonAccess::Destroy(&node);
0382 return {res.first, true, node_type()};
0383 } else {
0384 return {res.first, false, std::move(node)};
0385 }
0386 }
0387 iterator insert(const_iterator hint,
0388 node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0389 if (!node) return this->end();
0390 std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
0391 iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
0392 CommonAccess::GetSlot(node));
0393 if (res.second) CommonAccess::Destroy(&node);
0394 return res.first;
0395 }
0396
0397
0398 template <typename K = key_type>
0399 node_type extract(const key_arg<K> &key) {
0400 const std::pair<iterator, bool> lower_and_equal =
0401 this->tree_.lower_bound_equal(key);
0402 return lower_and_equal.second ? extract(lower_and_equal.first)
0403 : node_type();
0404 }
0405 using super_type::extract;
0406
0407
0408
0409
0410 template <
0411 typename T,
0412 typename absl::enable_if_t<
0413 absl::conjunction<
0414 std::is_same<value_type, typename T::value_type>,
0415 std::is_same<allocator_type, typename T::allocator_type>,
0416 std::is_same<typename params_type::is_map_container,
0417 typename T::params_type::is_map_container>>::value,
0418 int> = 0>
0419 void merge(btree_container<T> &src) {
0420 for (auto src_it = src.begin(); src_it != src.end();) {
0421 if (insert(std::move(params_type::element(src_it.slot()))).second) {
0422 src_it = src.erase(src_it);
0423 } else {
0424 ++src_it;
0425 }
0426 }
0427 }
0428
0429 template <
0430 typename T,
0431 typename absl::enable_if_t<
0432 absl::conjunction<
0433 std::is_same<value_type, typename T::value_type>,
0434 std::is_same<allocator_type, typename T::allocator_type>,
0435 std::is_same<typename params_type::is_map_container,
0436 typename T::params_type::is_map_container>>::value,
0437 int> = 0>
0438 void merge(btree_container<T> &&src) {
0439 merge(src);
0440 }
0441 };
0442
0443
0444 template <typename Tree>
0445 class btree_map_container : public btree_set_container<Tree> {
0446 using super_type = btree_set_container<Tree>;
0447 using params_type = typename Tree::params_type;
0448 friend class BtreeNodePeer;
0449
0450 private:
0451 template <class K>
0452 using key_arg = typename super_type::template key_arg<K>;
0453
0454 public:
0455 using key_type = typename Tree::key_type;
0456 using mapped_type = typename params_type::mapped_type;
0457 using value_type = typename Tree::value_type;
0458 using key_compare = typename Tree::original_key_compare;
0459 using allocator_type = typename Tree::allocator_type;
0460 using iterator = typename Tree::iterator;
0461 using const_iterator = typename Tree::const_iterator;
0462
0463
0464 using super_type::super_type;
0465 btree_map_container() {}
0466
0467
0468
0469
0470 template <typename K = key_type, class M>
0471 std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, const M &obj)
0472 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0473 return insert_or_assign_impl(k, obj);
0474 }
0475 template <typename K = key_type, class M, K * = nullptr>
0476 std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj)
0477 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0478 return insert_or_assign_impl(std::forward<K>(k), obj);
0479 }
0480 template <typename K = key_type, class M, M * = nullptr>
0481 std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj)
0482 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0483 return insert_or_assign_impl(k, std::forward<M>(obj));
0484 }
0485 template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
0486 std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj)
0487 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0488 return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj));
0489 }
0490 template <typename K = key_type, class M>
0491 iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
0492 const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0493 return insert_or_assign_hint_impl(hint, k, obj);
0494 }
0495 template <typename K = key_type, class M, K * = nullptr>
0496 iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
0497 const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0498 return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj);
0499 }
0500 template <typename K = key_type, class M, M * = nullptr>
0501 iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
0502 M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0503 return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj));
0504 }
0505 template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
0506 iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
0507 M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0508 return insert_or_assign_hint_impl(hint, std::forward<K>(k),
0509 std::forward<M>(obj));
0510 }
0511
0512 template <typename K = key_type, typename... Args,
0513 typename absl::enable_if_t<
0514 !std::is_convertible<K, const_iterator>::value, int> = 0>
0515 std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&...args)
0516 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0517 return try_emplace_impl(k, std::forward<Args>(args)...);
0518 }
0519 template <typename K = key_type, typename... Args,
0520 typename absl::enable_if_t<
0521 !std::is_convertible<K, const_iterator>::value, int> = 0>
0522 std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&...args)
0523 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0524 return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
0525 }
0526 template <typename K = key_type, typename... Args>
0527 iterator try_emplace(const_iterator hint, const key_arg<K> &k,
0528 Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0529 return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
0530 }
0531 template <typename K = key_type, typename... Args>
0532 iterator try_emplace(const_iterator hint, key_arg<K> &&k,
0533 Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0534 return try_emplace_hint_impl(hint, std::forward<K>(k),
0535 std::forward<Args>(args)...);
0536 }
0537
0538 template <typename K = key_type>
0539 mapped_type &operator[](const key_arg<K> &k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0540 return try_emplace(k).first->second;
0541 }
0542 template <typename K = key_type>
0543 mapped_type &operator[](key_arg<K> &&k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0544 return try_emplace(std::forward<K>(k)).first->second;
0545 }
0546
0547 template <typename K = key_type>
0548 mapped_type &at(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0549 auto it = this->find(key);
0550 if (it == this->end())
0551 base_internal::ThrowStdOutOfRange("absl::btree_map::at");
0552 return it->second;
0553 }
0554 template <typename K = key_type>
0555 const mapped_type &at(const key_arg<K> &key) const
0556 ABSL_ATTRIBUTE_LIFETIME_BOUND {
0557 auto it = this->find(key);
0558 if (it == this->end())
0559 base_internal::ThrowStdOutOfRange("absl::btree_map::at");
0560 return it->second;
0561 }
0562
0563 private:
0564
0565
0566
0567 template <class K, class M>
0568 std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) {
0569 const std::pair<iterator, bool> ret =
0570 this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj));
0571 if (!ret.second) ret.first->second = std::forward<M>(obj);
0572 return ret;
0573 }
0574 template <class K, class M>
0575 iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) {
0576 const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
0577 iterator(hint), k, std::forward<K>(k), std::forward<M>(obj));
0578 if (!ret.second) ret.first->second = std::forward<M>(obj);
0579 return ret.first;
0580 }
0581
0582 template <class K, class... Args>
0583 std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) {
0584 return this->tree_.insert_unique(
0585 k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)),
0586 std::forward_as_tuple(std::forward<Args>(args)...));
0587 }
0588 template <class K, class... Args>
0589 iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) {
0590 return this->tree_
0591 .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
0592 std::forward_as_tuple(std::forward<K>(k)),
0593 std::forward_as_tuple(std::forward<Args>(args)...))
0594 .first;
0595 }
0596 };
0597
0598
0599 template <typename Tree>
0600 class btree_multiset_container : public btree_container<Tree> {
0601 using super_type = btree_container<Tree>;
0602 using params_type = typename Tree::params_type;
0603 using init_type = typename params_type::init_type;
0604 using is_key_compare_to = typename params_type::is_key_compare_to;
0605 friend class BtreeNodePeer;
0606
0607 template <class K>
0608 using key_arg = typename super_type::template key_arg<K>;
0609
0610 public:
0611 using key_type = typename Tree::key_type;
0612 using value_type = typename Tree::value_type;
0613 using size_type = typename Tree::size_type;
0614 using key_compare = typename Tree::original_key_compare;
0615 using allocator_type = typename Tree::allocator_type;
0616 using iterator = typename Tree::iterator;
0617 using const_iterator = typename Tree::const_iterator;
0618 using node_type = typename super_type::node_type;
0619
0620
0621 using super_type::super_type;
0622 btree_multiset_container() {}
0623
0624
0625 template <class InputIterator>
0626 btree_multiset_container(InputIterator b, InputIterator e,
0627 const key_compare &comp = key_compare(),
0628 const allocator_type &alloc = allocator_type())
0629 : super_type(comp, alloc) {
0630 insert(b, e);
0631 }
0632 template <class InputIterator>
0633 btree_multiset_container(InputIterator b, InputIterator e,
0634 const allocator_type &alloc)
0635 : btree_multiset_container(b, e, key_compare(), alloc) {}
0636
0637
0638 btree_multiset_container(std::initializer_list<init_type> init,
0639 const key_compare &comp = key_compare(),
0640 const allocator_type &alloc = allocator_type())
0641 : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
0642 btree_multiset_container(std::initializer_list<init_type> init,
0643 const allocator_type &alloc)
0644 : btree_multiset_container(init.begin(), init.end(), alloc) {}
0645
0646
0647 iterator insert(const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0648 return this->tree_.insert_multi(v);
0649 }
0650 iterator insert(value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0651 return this->tree_.insert_multi(std::move(v));
0652 }
0653 iterator insert(const_iterator hint,
0654 const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0655 return this->tree_.insert_hint_multi(iterator(hint), v);
0656 }
0657 iterator insert(const_iterator hint,
0658 value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0659 return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
0660 }
0661 template <typename InputIterator>
0662 void insert(InputIterator b, InputIterator e) {
0663 this->tree_.insert_iterator_multi(b, e);
0664 }
0665 void insert(std::initializer_list<init_type> init) {
0666 this->tree_.insert_iterator_multi(init.begin(), init.end());
0667 }
0668 template <typename... Args>
0669 iterator emplace(Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0670
0671 auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
0672 std::forward<Args>(args)...);
0673 return this->tree_.insert_multi(CommonAccess::GetSlot(node));
0674 }
0675 template <typename... Args>
0676 iterator emplace_hint(const_iterator hint,
0677 Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0678
0679 auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
0680 std::forward<Args>(args)...);
0681 return this->tree_.insert_hint_multi(iterator(hint),
0682 CommonAccess::GetSlot(node));
0683 }
0684 iterator insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0685 if (!node) return this->end();
0686 iterator res =
0687 this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
0688 CommonAccess::GetSlot(node));
0689 CommonAccess::Destroy(&node);
0690 return res;
0691 }
0692 iterator insert(const_iterator hint,
0693 node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
0694 if (!node) return this->end();
0695 iterator res = this->tree_.insert_hint_multi(
0696 iterator(hint),
0697 std::move(params_type::element(CommonAccess::GetSlot(node))));
0698 CommonAccess::Destroy(&node);
0699 return res;
0700 }
0701
0702
0703 template <typename K = key_type>
0704 node_type extract(const key_arg<K> &key) {
0705 const std::pair<iterator, bool> lower_and_equal =
0706 this->tree_.lower_bound_equal(key);
0707 return lower_and_equal.second ? extract(lower_and_equal.first)
0708 : node_type();
0709 }
0710 using super_type::extract;
0711
0712
0713
0714 template <
0715 typename T,
0716 typename absl::enable_if_t<
0717 absl::conjunction<
0718 std::is_same<value_type, typename T::value_type>,
0719 std::is_same<allocator_type, typename T::allocator_type>,
0720 std::is_same<typename params_type::is_map_container,
0721 typename T::params_type::is_map_container>>::value,
0722 int> = 0>
0723 void merge(btree_container<T> &src) {
0724 for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
0725 insert(std::move(params_type::element(src_it.slot())));
0726 }
0727 src.clear();
0728 }
0729
0730 template <
0731 typename T,
0732 typename absl::enable_if_t<
0733 absl::conjunction<
0734 std::is_same<value_type, typename T::value_type>,
0735 std::is_same<allocator_type, typename T::allocator_type>,
0736 std::is_same<typename params_type::is_map_container,
0737 typename T::params_type::is_map_container>>::value,
0738 int> = 0>
0739 void merge(btree_container<T> &&src) {
0740 merge(src);
0741 }
0742 };
0743
0744
0745 template <typename Tree>
0746 class btree_multimap_container : public btree_multiset_container<Tree> {
0747 using super_type = btree_multiset_container<Tree>;
0748 using params_type = typename Tree::params_type;
0749 friend class BtreeNodePeer;
0750
0751 public:
0752 using mapped_type = typename params_type::mapped_type;
0753
0754
0755 using super_type::super_type;
0756 btree_multimap_container() {}
0757 };
0758
0759 }
0760 ABSL_NAMESPACE_END
0761 }
0762
0763 #endif