blob: 03be708e4fd177173ad47806a13682c99499c907 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// Copyright 2018 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
16#define ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
17
18#include <algorithm>
19#include <initializer_list>
20#include <iterator>
21#include <utility>
22
23#include "absl/base/internal/throw_delegate.h"
24#include "absl/container/internal/btree.h" // IWYU pragma: export
25#include "absl/container/internal/common.h"
Austin Schuhb4691e92020-12-31 12:37:18 -080026#include "absl/memory/memory.h"
Austin Schuh36244a12019-09-21 17:52:38 -070027#include "absl/meta/type_traits.h"
28
29namespace absl {
Austin Schuhb4691e92020-12-31 12:37:18 -080030ABSL_NAMESPACE_BEGIN
Austin Schuh36244a12019-09-21 17:52:38 -070031namespace container_internal {
32
33// A common base class for btree_set, btree_map, btree_multiset, and
34// btree_multimap.
35template <typename Tree>
36class btree_container {
37 using params_type = typename Tree::params_type;
38
39 protected:
40 // Alias used for heterogeneous lookup functions.
41 // `key_arg<K>` evaluates to `K` when the functors are transparent and to
42 // `key_type` otherwise. It permits template argument deduction on `K` for the
43 // transparent case.
44 template <class K>
45 using key_arg =
46 typename KeyArg<IsTransparent<typename Tree::key_compare>::value>::
47 template type<K, typename Tree::key_type>;
48
49 public:
50 using key_type = typename Tree::key_type;
51 using value_type = typename Tree::value_type;
52 using size_type = typename Tree::size_type;
53 using difference_type = typename Tree::difference_type;
54 using key_compare = typename Tree::key_compare;
55 using value_compare = typename Tree::value_compare;
56 using allocator_type = typename Tree::allocator_type;
57 using reference = typename Tree::reference;
58 using const_reference = typename Tree::const_reference;
59 using pointer = typename Tree::pointer;
60 using const_pointer = typename Tree::const_pointer;
61 using iterator = typename Tree::iterator;
62 using const_iterator = typename Tree::const_iterator;
63 using reverse_iterator = typename Tree::reverse_iterator;
64 using const_reverse_iterator = typename Tree::const_reverse_iterator;
65 using node_type = typename Tree::node_handle_type;
66
67 // Constructors/assignments.
68 btree_container() : tree_(key_compare(), allocator_type()) {}
69 explicit btree_container(const key_compare &comp,
70 const allocator_type &alloc = allocator_type())
71 : tree_(comp, alloc) {}
Austin Schuhb4691e92020-12-31 12:37:18 -080072 explicit btree_container(const allocator_type &alloc)
73 : tree_(key_compare(), alloc) {}
74
75 btree_container(const btree_container &other)
76 : btree_container(other, absl::allocator_traits<allocator_type>::
77 select_on_container_copy_construction(
78 other.get_allocator())) {}
79 btree_container(const btree_container &other, const allocator_type &alloc)
80 : tree_(other.tree_, alloc) {}
81
82 btree_container(btree_container &&other) noexcept(
83 std::is_nothrow_move_constructible<Tree>::value) = default;
84 btree_container(btree_container &&other, const allocator_type &alloc)
85 : tree_(std::move(other.tree_), alloc) {}
86
87 btree_container &operator=(const btree_container &other) = default;
88 btree_container &operator=(btree_container &&other) noexcept(
Austin Schuh36244a12019-09-21 17:52:38 -070089 std::is_nothrow_move_assignable<Tree>::value) = default;
90
91 // Iterator routines.
92 iterator begin() { return tree_.begin(); }
93 const_iterator begin() const { return tree_.begin(); }
94 const_iterator cbegin() const { return tree_.begin(); }
95 iterator end() { return tree_.end(); }
96 const_iterator end() const { return tree_.end(); }
97 const_iterator cend() const { return tree_.end(); }
98 reverse_iterator rbegin() { return tree_.rbegin(); }
99 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
100 const_reverse_iterator crbegin() const { return tree_.rbegin(); }
101 reverse_iterator rend() { return tree_.rend(); }
102 const_reverse_iterator rend() const { return tree_.rend(); }
103 const_reverse_iterator crend() const { return tree_.rend(); }
104
105 // Lookup routines.
106 template <typename K = key_type>
Austin Schuhb4691e92020-12-31 12:37:18 -0800107 size_type count(const key_arg<K> &key) const {
108 auto equal_range = this->equal_range(key);
109 return std::distance(equal_range.first, equal_range.second);
110 }
111 template <typename K = key_type>
Austin Schuh36244a12019-09-21 17:52:38 -0700112 iterator find(const key_arg<K> &key) {
113 return tree_.find(key);
114 }
115 template <typename K = key_type>
116 const_iterator find(const key_arg<K> &key) const {
117 return tree_.find(key);
118 }
119 template <typename K = key_type>
120 bool contains(const key_arg<K> &key) const {
121 return find(key) != end();
122 }
123 template <typename K = key_type>
124 iterator lower_bound(const key_arg<K> &key) {
125 return tree_.lower_bound(key);
126 }
127 template <typename K = key_type>
128 const_iterator lower_bound(const key_arg<K> &key) const {
129 return tree_.lower_bound(key);
130 }
131 template <typename K = key_type>
132 iterator upper_bound(const key_arg<K> &key) {
133 return tree_.upper_bound(key);
134 }
135 template <typename K = key_type>
136 const_iterator upper_bound(const key_arg<K> &key) const {
137 return tree_.upper_bound(key);
138 }
139 template <typename K = key_type>
140 std::pair<iterator, iterator> equal_range(const key_arg<K> &key) {
141 return tree_.equal_range(key);
142 }
143 template <typename K = key_type>
144 std::pair<const_iterator, const_iterator> equal_range(
145 const key_arg<K> &key) const {
146 return tree_.equal_range(key);
147 }
148
149 // Deletion routines. Note that there is also a deletion routine that is
150 // specific to btree_set_container/btree_multiset_container.
151
152 // Erase the specified iterator from the btree. The iterator must be valid
153 // (i.e. not equal to end()). Return an iterator pointing to the node after
154 // the one that was erased (or end() if none exists).
155 iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); }
156 iterator erase(iterator iter) { return tree_.erase(iter); }
157 iterator erase(const_iterator first, const_iterator last) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800158 return tree_.erase_range(iterator(first), iterator(last)).second;
159 }
160 template <typename K = key_type>
161 size_type erase(const key_arg<K> &key) {
162 auto equal_range = this->equal_range(key);
163 return tree_.erase_range(equal_range.first, equal_range.second).first;
Austin Schuh36244a12019-09-21 17:52:38 -0700164 }
165
166 // Extract routines.
167 node_type extract(iterator position) {
168 // Use Move instead of Transfer, because the rebalancing code expects to
169 // have a valid object to scribble metadata bits on top of.
170 auto node = CommonAccess::Move<node_type>(get_allocator(), position.slot());
171 erase(position);
172 return node;
173 }
174 node_type extract(const_iterator position) {
175 return extract(iterator(position));
176 }
177
Austin Schuh36244a12019-09-21 17:52:38 -0700178 // Utility routines.
179 void clear() { tree_.clear(); }
Austin Schuhb4691e92020-12-31 12:37:18 -0800180 void swap(btree_container &other) { tree_.swap(other.tree_); }
Austin Schuh36244a12019-09-21 17:52:38 -0700181 void verify() const { tree_.verify(); }
182
183 // Size routines.
184 size_type size() const { return tree_.size(); }
185 size_type max_size() const { return tree_.max_size(); }
186 bool empty() const { return tree_.empty(); }
187
188 friend bool operator==(const btree_container &x, const btree_container &y) {
189 if (x.size() != y.size()) return false;
190 return std::equal(x.begin(), x.end(), y.begin());
191 }
192
193 friend bool operator!=(const btree_container &x, const btree_container &y) {
194 return !(x == y);
195 }
196
197 friend bool operator<(const btree_container &x, const btree_container &y) {
198 return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
199 }
200
201 friend bool operator>(const btree_container &x, const btree_container &y) {
202 return y < x;
203 }
204
205 friend bool operator<=(const btree_container &x, const btree_container &y) {
206 return !(y < x);
207 }
208
209 friend bool operator>=(const btree_container &x, const btree_container &y) {
210 return !(x < y);
211 }
212
213 // The allocator used by the btree.
214 allocator_type get_allocator() const { return tree_.get_allocator(); }
215
216 // The key comparator used by the btree.
217 key_compare key_comp() const { return tree_.key_comp(); }
218 value_compare value_comp() const { return tree_.value_comp(); }
219
220 // Support absl::Hash.
221 template <typename State>
222 friend State AbslHashValue(State h, const btree_container &b) {
223 for (const auto &v : b) {
224 h = State::combine(std::move(h), v);
225 }
226 return State::combine(std::move(h), b.size());
227 }
228
229 protected:
230 Tree tree_;
231};
232
233// A common base class for btree_set and btree_map.
234template <typename Tree>
235class btree_set_container : public btree_container<Tree> {
236 using super_type = btree_container<Tree>;
237 using params_type = typename Tree::params_type;
238 using init_type = typename params_type::init_type;
239 using is_key_compare_to = typename params_type::is_key_compare_to;
240 friend class BtreeNodePeer;
241
242 protected:
243 template <class K>
244 using key_arg = typename super_type::template key_arg<K>;
245
246 public:
247 using key_type = typename Tree::key_type;
248 using value_type = typename Tree::value_type;
249 using size_type = typename Tree::size_type;
250 using key_compare = typename Tree::key_compare;
251 using allocator_type = typename Tree::allocator_type;
252 using iterator = typename Tree::iterator;
253 using const_iterator = typename Tree::const_iterator;
254 using node_type = typename super_type::node_type;
255 using insert_return_type = InsertReturnType<iterator, node_type>;
256
257 // Inherit constructors.
258 using super_type::super_type;
259 btree_set_container() {}
260
Austin Schuhb4691e92020-12-31 12:37:18 -0800261 // Range constructors.
Austin Schuh36244a12019-09-21 17:52:38 -0700262 template <class InputIterator>
263 btree_set_container(InputIterator b, InputIterator e,
264 const key_compare &comp = key_compare(),
265 const allocator_type &alloc = allocator_type())
266 : super_type(comp, alloc) {
267 insert(b, e);
268 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800269 template <class InputIterator>
270 btree_set_container(InputIterator b, InputIterator e,
271 const allocator_type &alloc)
272 : btree_set_container(b, e, key_compare(), alloc) {}
Austin Schuh36244a12019-09-21 17:52:38 -0700273
Austin Schuhb4691e92020-12-31 12:37:18 -0800274 // Initializer list constructors.
Austin Schuh36244a12019-09-21 17:52:38 -0700275 btree_set_container(std::initializer_list<init_type> init,
276 const key_compare &comp = key_compare(),
277 const allocator_type &alloc = allocator_type())
278 : btree_set_container(init.begin(), init.end(), comp, alloc) {}
Austin Schuhb4691e92020-12-31 12:37:18 -0800279 btree_set_container(std::initializer_list<init_type> init,
280 const allocator_type &alloc)
281 : btree_set_container(init.begin(), init.end(), alloc) {}
Austin Schuh36244a12019-09-21 17:52:38 -0700282
283 // Insertion routines.
Austin Schuhb4691e92020-12-31 12:37:18 -0800284 std::pair<iterator, bool> insert(const value_type &v) {
285 return this->tree_.insert_unique(params_type::key(v), v);
Austin Schuh36244a12019-09-21 17:52:38 -0700286 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800287 std::pair<iterator, bool> insert(value_type &&v) {
288 return this->tree_.insert_unique(params_type::key(v), std::move(v));
Austin Schuh36244a12019-09-21 17:52:38 -0700289 }
290 template <typename... Args>
291 std::pair<iterator, bool> emplace(Args &&... args) {
292 init_type v(std::forward<Args>(args)...);
293 return this->tree_.insert_unique(params_type::key(v), std::move(v));
294 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800295 iterator insert(const_iterator hint, const value_type &v) {
Austin Schuh36244a12019-09-21 17:52:38 -0700296 return this->tree_
Austin Schuhb4691e92020-12-31 12:37:18 -0800297 .insert_hint_unique(iterator(hint), params_type::key(v), v)
Austin Schuh36244a12019-09-21 17:52:38 -0700298 .first;
299 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800300 iterator insert(const_iterator hint, value_type &&v) {
Austin Schuh36244a12019-09-21 17:52:38 -0700301 return this->tree_
Austin Schuhb4691e92020-12-31 12:37:18 -0800302 .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
Austin Schuh36244a12019-09-21 17:52:38 -0700303 .first;
304 }
305 template <typename... Args>
Austin Schuhb4691e92020-12-31 12:37:18 -0800306 iterator emplace_hint(const_iterator hint, Args &&... args) {
Austin Schuh36244a12019-09-21 17:52:38 -0700307 init_type v(std::forward<Args>(args)...);
308 return this->tree_
Austin Schuhb4691e92020-12-31 12:37:18 -0800309 .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
Austin Schuh36244a12019-09-21 17:52:38 -0700310 .first;
311 }
312 template <typename InputIterator>
313 void insert(InputIterator b, InputIterator e) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800314 this->tree_.insert_iterator_unique(b, e, 0);
Austin Schuh36244a12019-09-21 17:52:38 -0700315 }
316 void insert(std::initializer_list<init_type> init) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800317 this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);
Austin Schuh36244a12019-09-21 17:52:38 -0700318 }
319 insert_return_type insert(node_type &&node) {
320 if (!node) return {this->end(), false, node_type()};
321 std::pair<iterator, bool> res =
Austin Schuhb4691e92020-12-31 12:37:18 -0800322 this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
323 CommonAccess::GetSlot(node));
Austin Schuh36244a12019-09-21 17:52:38 -0700324 if (res.second) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800325 CommonAccess::Destroy(&node);
Austin Schuh36244a12019-09-21 17:52:38 -0700326 return {res.first, true, node_type()};
327 } else {
328 return {res.first, false, std::move(node)};
329 }
330 }
331 iterator insert(const_iterator hint, node_type &&node) {
332 if (!node) return this->end();
333 std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
334 iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
Austin Schuhb4691e92020-12-31 12:37:18 -0800335 CommonAccess::GetSlot(node));
336 if (res.second) CommonAccess::Destroy(&node);
Austin Schuh36244a12019-09-21 17:52:38 -0700337 return res.first;
338 }
339
Austin Schuh36244a12019-09-21 17:52:38 -0700340 // Node extraction routines.
341 template <typename K = key_type>
342 node_type extract(const key_arg<K> &key) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800343 const std::pair<iterator, bool> lower_and_equal =
344 this->tree_.lower_bound_equal(key);
345 return lower_and_equal.second ? extract(lower_and_equal.first)
346 : node_type();
Austin Schuh36244a12019-09-21 17:52:38 -0700347 }
348 using super_type::extract;
349
350 // Merge routines.
351 // Moves elements from `src` into `this`. If the element already exists in
352 // `this`, it is left unmodified in `src`.
353 template <
354 typename T,
355 typename absl::enable_if_t<
356 absl::conjunction<
357 std::is_same<value_type, typename T::value_type>,
358 std::is_same<allocator_type, typename T::allocator_type>,
359 std::is_same<typename params_type::is_map_container,
360 typename T::params_type::is_map_container>>::value,
361 int> = 0>
362 void merge(btree_container<T> &src) { // NOLINT
363 for (auto src_it = src.begin(); src_it != src.end();) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800364 if (insert(std::move(params_type::element(src_it.slot()))).second) {
Austin Schuh36244a12019-09-21 17:52:38 -0700365 src_it = src.erase(src_it);
366 } else {
367 ++src_it;
368 }
369 }
370 }
371
372 template <
373 typename T,
374 typename absl::enable_if_t<
375 absl::conjunction<
376 std::is_same<value_type, typename T::value_type>,
377 std::is_same<allocator_type, typename T::allocator_type>,
378 std::is_same<typename params_type::is_map_container,
379 typename T::params_type::is_map_container>>::value,
380 int> = 0>
381 void merge(btree_container<T> &&src) {
382 merge(src);
383 }
384};
385
386// Base class for btree_map.
387template <typename Tree>
388class btree_map_container : public btree_set_container<Tree> {
389 using super_type = btree_set_container<Tree>;
390 using params_type = typename Tree::params_type;
Austin Schuhb4691e92020-12-31 12:37:18 -0800391 friend class BtreeNodePeer;
Austin Schuh36244a12019-09-21 17:52:38 -0700392
Austin Schuhb4691e92020-12-31 12:37:18 -0800393 private:
Austin Schuh36244a12019-09-21 17:52:38 -0700394 template <class K>
395 using key_arg = typename super_type::template key_arg<K>;
396
397 public:
398 using key_type = typename Tree::key_type;
399 using mapped_type = typename params_type::mapped_type;
400 using value_type = typename Tree::value_type;
401 using key_compare = typename Tree::key_compare;
402 using allocator_type = typename Tree::allocator_type;
403 using iterator = typename Tree::iterator;
404 using const_iterator = typename Tree::const_iterator;
405
406 // Inherit constructors.
407 using super_type::super_type;
408 btree_map_container() {}
409
410 // Insertion routines.
Austin Schuhb4691e92020-12-31 12:37:18 -0800411 // Note: the nullptr template arguments and extra `const M&` overloads allow
412 // for supporting bitfield arguments.
413 template <typename K = key_type, class M>
414 std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k,
415 const M &obj) {
416 return insert_or_assign_impl(k, obj);
Austin Schuh36244a12019-09-21 17:52:38 -0700417 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800418 template <typename K = key_type, class M, K * = nullptr>
419 std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj) {
420 return insert_or_assign_impl(std::forward<K>(k), obj);
Austin Schuh36244a12019-09-21 17:52:38 -0700421 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800422 template <typename K = key_type, class M, M * = nullptr>
423 std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj) {
424 return insert_or_assign_impl(k, std::forward<M>(obj));
425 }
426 template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
427 std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj) {
428 return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj));
429 }
430 template <typename K = key_type, class M>
431 iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
432 const M &obj) {
433 return insert_or_assign_hint_impl(hint, k, obj);
434 }
435 template <typename K = key_type, class M, K * = nullptr>
436 iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, const M &obj) {
437 return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj);
438 }
439 template <typename K = key_type, class M, M * = nullptr>
440 iterator insert_or_assign(const_iterator hint, const key_arg<K> &k, M &&obj) {
441 return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj));
442 }
443 template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
444 iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, M &&obj) {
445 return insert_or_assign_hint_impl(hint, std::forward<K>(k),
446 std::forward<M>(obj));
447 }
448
449 template <typename K = key_type, typename... Args,
450 typename absl::enable_if_t<
451 !std::is_convertible<K, const_iterator>::value, int> = 0>
452 std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&... args) {
453 return try_emplace_impl(k, std::forward<Args>(args)...);
454 }
455 template <typename K = key_type, typename... Args,
456 typename absl::enable_if_t<
457 !std::is_convertible<K, const_iterator>::value, int> = 0>
458 std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&... args) {
459 return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
460 }
461 template <typename K = key_type, typename... Args>
462 iterator try_emplace(const_iterator hint, const key_arg<K> &k,
Austin Schuh36244a12019-09-21 17:52:38 -0700463 Args &&... args) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800464 return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
Austin Schuh36244a12019-09-21 17:52:38 -0700465 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800466 template <typename K = key_type, typename... Args>
467 iterator try_emplace(const_iterator hint, key_arg<K> &&k, Args &&... args) {
468 return try_emplace_hint_impl(hint, std::forward<K>(k),
469 std::forward<Args>(args)...);
Austin Schuh36244a12019-09-21 17:52:38 -0700470 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800471
472 template <typename K = key_type>
473 mapped_type &operator[](const key_arg<K> &k) {
Austin Schuh36244a12019-09-21 17:52:38 -0700474 return try_emplace(k).first->second;
475 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800476 template <typename K = key_type>
477 mapped_type &operator[](key_arg<K> &&k) {
478 return try_emplace(std::forward<K>(k)).first->second;
Austin Schuh36244a12019-09-21 17:52:38 -0700479 }
480
481 template <typename K = key_type>
482 mapped_type &at(const key_arg<K> &key) {
483 auto it = this->find(key);
484 if (it == this->end())
485 base_internal::ThrowStdOutOfRange("absl::btree_map::at");
486 return it->second;
487 }
488 template <typename K = key_type>
489 const mapped_type &at(const key_arg<K> &key) const {
490 auto it = this->find(key);
491 if (it == this->end())
492 base_internal::ThrowStdOutOfRange("absl::btree_map::at");
493 return it->second;
494 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800495
496 private:
497 // Note: when we call `std::forward<M>(obj)` twice, it's safe because
498 // insert_unique/insert_hint_unique are guaranteed to not consume `obj` when
499 // `ret.second` is false.
500 template <class K, class M>
501 std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) {
502 const std::pair<iterator, bool> ret =
503 this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj));
504 if (!ret.second) ret.first->second = std::forward<M>(obj);
505 return ret;
506 }
507 template <class K, class M>
508 iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) {
509 const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
510 iterator(hint), k, std::forward<K>(k), std::forward<M>(obj));
511 if (!ret.second) ret.first->second = std::forward<M>(obj);
512 return ret.first;
513 }
514
515 template <class K, class... Args>
516 std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) {
517 return this->tree_.insert_unique(
518 k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)),
519 std::forward_as_tuple(std::forward<Args>(args)...));
520 }
521 template <class K, class... Args>
522 iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) {
523 return this->tree_
524 .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
525 std::forward_as_tuple(std::forward<K>(k)),
526 std::forward_as_tuple(std::forward<Args>(args)...))
527 .first;
528 }
Austin Schuh36244a12019-09-21 17:52:38 -0700529};
530
531// A common base class for btree_multiset and btree_multimap.
532template <typename Tree>
533class btree_multiset_container : public btree_container<Tree> {
534 using super_type = btree_container<Tree>;
535 using params_type = typename Tree::params_type;
536 using init_type = typename params_type::init_type;
537 using is_key_compare_to = typename params_type::is_key_compare_to;
538
539 template <class K>
540 using key_arg = typename super_type::template key_arg<K>;
541
542 public:
543 using key_type = typename Tree::key_type;
544 using value_type = typename Tree::value_type;
545 using size_type = typename Tree::size_type;
546 using key_compare = typename Tree::key_compare;
547 using allocator_type = typename Tree::allocator_type;
548 using iterator = typename Tree::iterator;
549 using const_iterator = typename Tree::const_iterator;
550 using node_type = typename super_type::node_type;
551
552 // Inherit constructors.
553 using super_type::super_type;
554 btree_multiset_container() {}
555
Austin Schuhb4691e92020-12-31 12:37:18 -0800556 // Range constructors.
Austin Schuh36244a12019-09-21 17:52:38 -0700557 template <class InputIterator>
558 btree_multiset_container(InputIterator b, InputIterator e,
559 const key_compare &comp = key_compare(),
560 const allocator_type &alloc = allocator_type())
561 : super_type(comp, alloc) {
562 insert(b, e);
563 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800564 template <class InputIterator>
565 btree_multiset_container(InputIterator b, InputIterator e,
566 const allocator_type &alloc)
567 : btree_multiset_container(b, e, key_compare(), alloc) {}
Austin Schuh36244a12019-09-21 17:52:38 -0700568
Austin Schuhb4691e92020-12-31 12:37:18 -0800569 // Initializer list constructors.
Austin Schuh36244a12019-09-21 17:52:38 -0700570 btree_multiset_container(std::initializer_list<init_type> init,
571 const key_compare &comp = key_compare(),
572 const allocator_type &alloc = allocator_type())
573 : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
Austin Schuhb4691e92020-12-31 12:37:18 -0800574 btree_multiset_container(std::initializer_list<init_type> init,
575 const allocator_type &alloc)
576 : btree_multiset_container(init.begin(), init.end(), alloc) {}
Austin Schuh36244a12019-09-21 17:52:38 -0700577
578 // Insertion routines.
Austin Schuhb4691e92020-12-31 12:37:18 -0800579 iterator insert(const value_type &v) { return this->tree_.insert_multi(v); }
580 iterator insert(value_type &&v) {
581 return this->tree_.insert_multi(std::move(v));
Austin Schuh36244a12019-09-21 17:52:38 -0700582 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800583 iterator insert(const_iterator hint, const value_type &v) {
584 return this->tree_.insert_hint_multi(iterator(hint), v);
Austin Schuh36244a12019-09-21 17:52:38 -0700585 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800586 iterator insert(const_iterator hint, value_type &&v) {
587 return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
Austin Schuh36244a12019-09-21 17:52:38 -0700588 }
589 template <typename InputIterator>
590 void insert(InputIterator b, InputIterator e) {
591 this->tree_.insert_iterator_multi(b, e);
592 }
593 void insert(std::initializer_list<init_type> init) {
594 this->tree_.insert_iterator_multi(init.begin(), init.end());
595 }
596 template <typename... Args>
597 iterator emplace(Args &&... args) {
598 return this->tree_.insert_multi(init_type(std::forward<Args>(args)...));
599 }
600 template <typename... Args>
Austin Schuhb4691e92020-12-31 12:37:18 -0800601 iterator emplace_hint(const_iterator hint, Args &&... args) {
Austin Schuh36244a12019-09-21 17:52:38 -0700602 return this->tree_.insert_hint_multi(
Austin Schuhb4691e92020-12-31 12:37:18 -0800603 iterator(hint), init_type(std::forward<Args>(args)...));
Austin Schuh36244a12019-09-21 17:52:38 -0700604 }
Austin Schuhb4691e92020-12-31 12:37:18 -0800605 iterator insert(node_type &&node) {
Austin Schuh36244a12019-09-21 17:52:38 -0700606 if (!node) return this->end();
607 iterator res =
Austin Schuhb4691e92020-12-31 12:37:18 -0800608 this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
609 CommonAccess::GetSlot(node));
610 CommonAccess::Destroy(&node);
Austin Schuh36244a12019-09-21 17:52:38 -0700611 return res;
612 }
Austin Schuh36244a12019-09-21 17:52:38 -0700613 iterator insert(const_iterator hint, node_type &&node) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800614 if (!node) return this->end();
615 iterator res = this->tree_.insert_hint_multi(
616 iterator(hint),
617 std::move(params_type::element(CommonAccess::GetSlot(node))));
618 CommonAccess::Destroy(&node);
619 return res;
Austin Schuh36244a12019-09-21 17:52:38 -0700620 }
621
Austin Schuh36244a12019-09-21 17:52:38 -0700622 // Node extraction routines.
623 template <typename K = key_type>
624 node_type extract(const key_arg<K> &key) {
Austin Schuhb4691e92020-12-31 12:37:18 -0800625 const std::pair<iterator, bool> lower_and_equal =
626 this->tree_.lower_bound_equal(key);
627 return lower_and_equal.second ? extract(lower_and_equal.first)
628 : node_type();
Austin Schuh36244a12019-09-21 17:52:38 -0700629 }
630 using super_type::extract;
631
632 // Merge routines.
633 // Moves all elements from `src` into `this`.
634 template <
635 typename T,
636 typename absl::enable_if_t<
637 absl::conjunction<
638 std::is_same<value_type, typename T::value_type>,
639 std::is_same<allocator_type, typename T::allocator_type>,
640 std::is_same<typename params_type::is_map_container,
641 typename T::params_type::is_map_container>>::value,
642 int> = 0>
643 void merge(btree_container<T> &src) { // NOLINT
Austin Schuhb4691e92020-12-31 12:37:18 -0800644 for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
645 insert(std::move(params_type::element(src_it.slot())));
646 }
Austin Schuh36244a12019-09-21 17:52:38 -0700647 src.clear();
648 }
649
650 template <
651 typename T,
652 typename absl::enable_if_t<
653 absl::conjunction<
654 std::is_same<value_type, typename T::value_type>,
655 std::is_same<allocator_type, typename T::allocator_type>,
656 std::is_same<typename params_type::is_map_container,
657 typename T::params_type::is_map_container>>::value,
658 int> = 0>
659 void merge(btree_container<T> &&src) {
660 merge(src);
661 }
662};
663
664// A base class for btree_multimap.
665template <typename Tree>
666class btree_multimap_container : public btree_multiset_container<Tree> {
667 using super_type = btree_multiset_container<Tree>;
668 using params_type = typename Tree::params_type;
669
670 public:
671 using mapped_type = typename params_type::mapped_type;
672
673 // Inherit constructors.
674 using super_type::super_type;
675 btree_multimap_container() {}
676};
677
678} // namespace container_internal
Austin Schuhb4691e92020-12-31 12:37:18 -0800679ABSL_NAMESPACE_END
Austin Schuh36244a12019-09-21 17:52:38 -0700680} // namespace absl
681
682#endif // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_