1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_
6 #define BASE_CONTAINERS_FLAT_TREE_H_
7
8 #include <algorithm>
9 #include <iterator>
10 #include <type_traits>
11 #include <vector>
12
13 #include "base/template_util.h"
14
15 namespace base {
16
17 enum FlatContainerDupes {
18 KEEP_FIRST_OF_DUPES,
19 KEEP_LAST_OF_DUPES,
20 };
21
22 namespace internal {
23
24 // This is a convenience method returning true if Iterator is at least a
25 // ForwardIterator and thus supports multiple passes over a range.
26 template <class Iterator>
is_multipass()27 constexpr bool is_multipass() {
28 return std::is_base_of<
29 std::forward_iterator_tag,
30 typename std::iterator_traits<Iterator>::iterator_category>::value;
31 }
32
33 // This algorithm is like unique() from the standard library except it
34 // selects only the last of consecutive values instead of the first.
35 template <class Iterator, class BinaryPredicate>
LastUnique(Iterator first,Iterator last,BinaryPredicate compare)36 Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) {
37 Iterator replacable = std::adjacent_find(first, last, compare);
38
39 // No duplicate elements found.
40 if (replacable == last)
41 return last;
42
43 first = std::next(replacable);
44
45 // Last element is a duplicate but all others are unique.
46 if (first == last)
47 return replacable;
48
49 // This loop is based on std::adjacent_find but std::adjacent_find doesn't
50 // quite cut it.
51 for (Iterator next = std::next(first); next != last; ++next, ++first) {
52 if (!compare(*first, *next))
53 *replacable++ = std::move(*first);
54 }
55
56 // Last element should be copied unconditionally.
57 *replacable++ = std::move(*first);
58 return replacable;
59 }
60
61 // Uses SFINAE to detect whether type has is_transparent member.
62 template <typename T, typename = void>
63 struct IsTransparentCompare : std::false_type {};
64 template <typename T>
65 struct IsTransparentCompare<T, void_t<typename T::is_transparent>>
66 : std::true_type {};
67
68 // Implementation -------------------------------------------------------------
69
70 // Implementation of a sorted vector for backing flat_set and flat_map. Do not
71 // use directly.
72 //
73 // The use of "value" in this is like std::map uses, meaning it's the thing
74 // contained (in the case of map it's a <Kay, Mapped> pair). The Key is how
75 // things are looked up. In the case of a set, Key == Value. In the case of
76 // a map, the Key is a component of a Value.
77 //
78 // The helper class GetKeyFromValue provides the means to extract a key from a
79 // value for comparison purposes. It should implement:
80 // const Key& operator()(const Value&).
81 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
82 class flat_tree {
83 private:
84 using underlying_type = std::vector<Value>;
85
86 public:
87 // --------------------------------------------------------------------------
88 // Types.
89 //
90 using key_type = Key;
91 using key_compare = KeyCompare;
92 using value_type = Value;
93
94 // Wraps the templated key comparison to compare values.
95 class value_compare : public key_compare {
96 public:
97 value_compare() = default;
98
99 template <class Cmp>
100 explicit value_compare(Cmp&& compare_arg)
101 : KeyCompare(std::forward<Cmp>(compare_arg)) {}
102
103 bool operator()(const value_type& left, const value_type& right) const {
104 GetKeyFromValue extractor;
105 return key_compare::operator()(extractor(left), extractor(right));
106 }
107 };
108
109 using pointer = typename underlying_type::pointer;
110 using const_pointer = typename underlying_type::const_pointer;
111 using reference = typename underlying_type::reference;
112 using const_reference = typename underlying_type::const_reference;
113 using size_type = typename underlying_type::size_type;
114 using difference_type = typename underlying_type::difference_type;
115 using iterator = typename underlying_type::iterator;
116 using const_iterator = typename underlying_type::const_iterator;
117 using reverse_iterator = typename underlying_type::reverse_iterator;
118 using const_reverse_iterator =
119 typename underlying_type::const_reverse_iterator;
120
121 // --------------------------------------------------------------------------
122 // Lifetime.
123 //
124 // Constructors that take range guarantee O(N * log^2(N)) + O(N) complexity
125 // and take O(N * log(N)) + O(N) if extra memory is available (N is a range
126 // length).
127 //
128 // Assume that move constructors invalidate iterators and references.
129 //
130 // The constructors that take ranges, lists, and vectors do not require that
131 // the input be sorted.
132
133 flat_tree();
134 explicit flat_tree(const key_compare& comp);
135
136 template <class InputIterator>
137 flat_tree(InputIterator first,
138 InputIterator last,
139 FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES,
140 const key_compare& comp = key_compare());
141
142 flat_tree(const flat_tree&);
143 flat_tree(flat_tree&&) noexcept = default;
144
145 flat_tree(std::vector<value_type> items,
146 FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES,
147 const key_compare& comp = key_compare());
148
149 flat_tree(std::initializer_list<value_type> ilist,
150 FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES,
151 const key_compare& comp = key_compare());
152
153 ~flat_tree();
154
155 // --------------------------------------------------------------------------
156 // Assignments.
157 //
158 // Assume that move assignment invalidates iterators and references.
159
160 flat_tree& operator=(const flat_tree&);
161 flat_tree& operator=(flat_tree&&);
162 // Takes the first if there are duplicates in the initializer list.
163 flat_tree& operator=(std::initializer_list<value_type> ilist);
164
165 // --------------------------------------------------------------------------
166 // Memory management.
167 //
168 // Beware that shrink_to_fit() simply forwards the request to the
169 // underlying_type and its implementation is free to optimize otherwise and
170 // leave capacity() to be greater that its size.
171 //
172 // reserve() and shrink_to_fit() invalidate iterators and references.
173
174 void reserve(size_type new_capacity);
175 size_type capacity() const;
176 void shrink_to_fit();
177
178 // --------------------------------------------------------------------------
179 // Size management.
180 //
181 // clear() leaves the capacity() of the flat_tree unchanged.
182
183 void clear();
184
185 size_type size() const;
186 size_type max_size() const;
187 bool empty() const;
188
189 // --------------------------------------------------------------------------
190 // Iterators.
191
192 iterator begin();
193 const_iterator begin() const;
194 const_iterator cbegin() const;
195
196 iterator end();
197 const_iterator end() const;
198 const_iterator cend() const;
199
200 reverse_iterator rbegin();
201 const_reverse_iterator rbegin() const;
202 const_reverse_iterator crbegin() const;
203
204 reverse_iterator rend();
205 const_reverse_iterator rend() const;
206 const_reverse_iterator crend() const;
207
208 // --------------------------------------------------------------------------
209 // Insert operations.
210 //
211 // Assume that every operation invalidates iterators and references.
212 // Insertion of one element can take O(size). Capacity of flat_tree grows in
213 // an implementation-defined manner.
214 //
215 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar)
216 // instead of calling insert() repeatedly.
217
218 std::pair<iterator, bool> insert(const value_type& val);
219 std::pair<iterator, bool> insert(value_type&& val);
220
221 iterator insert(const_iterator position_hint, const value_type& x);
222 iterator insert(const_iterator position_hint, value_type&& x);
223
224 // This method inserts the values from the range [first, last) into the
225 // current tree. In case of KEEP_LAST_OF_DUPES newly added elements can
226 // overwrite existing values.
227 template <class InputIterator>
228 void insert(InputIterator first,
229 InputIterator last,
230 FlatContainerDupes dupes = KEEP_FIRST_OF_DUPES);
231
232 template <class... Args>
233 std::pair<iterator, bool> emplace(Args&&... args);
234
235 template <class... Args>
236 iterator emplace_hint(const_iterator position_hint, Args&&... args);
237
238 // --------------------------------------------------------------------------
239 // Erase operations.
240 //
241 // Assume that every operation invalidates iterators and references.
242 //
243 // erase(position), erase(first, last) can take O(size).
244 // erase(key) may take O(size) + O(log(size)).
245 //
246 // Prefer base::EraseIf() or some other variation on erase(remove(), end())
247 // idiom when deleting multiple non-consecutive elements.
248
249 iterator erase(iterator position);
250 iterator erase(const_iterator position);
251 iterator erase(const_iterator first, const_iterator last);
252 template <typename K>
253 size_type erase(const K& key);
254
255 // --------------------------------------------------------------------------
256 // Comparators.
257
258 key_compare key_comp() const;
259 value_compare value_comp() const;
260
261 // --------------------------------------------------------------------------
262 // Search operations.
263 //
264 // Search operations have O(log(size)) complexity.
265
266 template <typename K>
267 size_type count(const K& key) const;
268
269 template <typename K>
270 iterator find(const K& key);
271
272 template <typename K>
273 const_iterator find(const K& key) const;
274
275 template <typename K>
276 std::pair<iterator, iterator> equal_range(const K& key);
277
278 template <typename K>
279 std::pair<const_iterator, const_iterator> equal_range(const K& key) const;
280
281 template <typename K>
282 iterator lower_bound(const K& key);
283
284 template <typename K>
285 const_iterator lower_bound(const K& key) const;
286
287 template <typename K>
288 iterator upper_bound(const K& key);
289
290 template <typename K>
291 const_iterator upper_bound(const K& key) const;
292
293 // --------------------------------------------------------------------------
294 // General operations.
295 //
296 // Assume that swap invalidates iterators and references.
297 //
298 // Implementation note: currently we use operator==() and operator<() on
299 // std::vector, because they have the same contract we need, so we use them
300 // directly for brevity and in case it is more optimal than calling equal()
301 // and lexicograhpical_compare(). If the underlying container type is changed,
302 // this code may need to be modified.
303
304 void swap(flat_tree& other) noexcept;
305
306 friend bool operator==(const flat_tree& lhs, const flat_tree& rhs) {
307 return lhs.impl_.body_ == rhs.impl_.body_;
308 }
309
310 friend bool operator!=(const flat_tree& lhs, const flat_tree& rhs) {
311 return !(lhs == rhs);
312 }
313
314 friend bool operator<(const flat_tree& lhs, const flat_tree& rhs) {
315 return lhs.impl_.body_ < rhs.impl_.body_;
316 }
317
318 friend bool operator>(const flat_tree& lhs, const flat_tree& rhs) {
319 return rhs < lhs;
320 }
321
322 friend bool operator>=(const flat_tree& lhs, const flat_tree& rhs) {
323 return !(lhs < rhs);
324 }
325
326 friend bool operator<=(const flat_tree& lhs, const flat_tree& rhs) {
327 return !(lhs > rhs);
328 }
329
330 friend void swap(flat_tree& lhs, flat_tree& rhs) noexcept { lhs.swap(rhs); }
331
332 protected:
333 // Emplaces a new item into the tree that is known not to be in it. This
334 // is for implementing map operator[].
335 template <class... Args>
336 iterator unsafe_emplace(const_iterator position, Args&&... args);
337
338 // Attempts to emplace a new element with key |key|. Only if |key| is not yet
339 // present, construct value_type from |args| and insert it. Returns an
340 // iterator to the element with key |key| and a bool indicating whether an
341 // insertion happened.
342 template <class K, class... Args>
343 std::pair<iterator, bool> emplace_key_args(const K& key, Args&&... args);
344
345 // Similar to |emplace_key_args|, but checks |hint| first as a possible
346 // insertion position.
347 template <class K, class... Args>
348 std::pair<iterator, bool> emplace_hint_key_args(const_iterator hint,
349 const K& key,
350 Args&&... args);
351
352 private:
353 // Helper class for e.g. lower_bound that can compare a value on the left
354 // to a key on the right.
355 struct KeyValueCompare {
356 // The key comparison object must outlive this class.
357 explicit KeyValueCompare(const key_compare& key_comp)
358 : key_comp_(key_comp) {}
359
360 template <typename T, typename U>
361 bool operator()(const T& lhs, const U& rhs) const {
362 return key_comp_(extract_if_value_type(lhs), extract_if_value_type(rhs));
363 }
364
365 private:
366 const key_type& extract_if_value_type(const value_type& v) const {
367 GetKeyFromValue extractor;
368 return extractor(v);
369 }
370
371 template <typename K>
372 const K& extract_if_value_type(const K& k) const {
373 return k;
374 }
375
376 const key_compare& key_comp_;
377 };
378
379 const flat_tree& as_const() { return *this; }
380
381 iterator const_cast_it(const_iterator c_it) {
382 auto distance = std::distance(cbegin(), c_it);
383 return std::next(begin(), distance);
384 }
385
386 // This method is inspired by both std::map::insert(P&&) and
387 // std::map::insert_or_assign(const K&, V&&). It inserts val if an equivalent
388 // element is not present yet, otherwise it overwrites. It returns an iterator
389 // to the modified element and a flag indicating whether insertion or
390 // assignment happened.
391 template <class V>
392 std::pair<iterator, bool> insert_or_assign(V&& val) {
393 auto position = lower_bound(GetKeyFromValue()(val));
394
395 if (position == end() || value_comp()(val, *position))
396 return {impl_.body_.emplace(position, std::forward<V>(val)), true};
397
398 *position = std::forward<V>(val);
399 return {position, false};
400 }
401
402 // This method is similar to insert_or_assign, with the following differences:
403 // - Instead of searching [begin(), end()) it only searches [first, last).
404 // - In case no equivalent element is found, val is appended to the end of the
405 // underlying body and an iterator to the next bigger element in [first,
406 // last) is returned.
407 template <class V>
408 std::pair<iterator, bool> append_or_assign(iterator first,
409 iterator last,
410 V&& val) {
411 auto position = std::lower_bound(first, last, val, value_comp());
412
413 if (position == last || value_comp()(val, *position)) {
414 // emplace_back might invalidate position, which is why distance needs to
415 // be cached.
416 const difference_type distance = std::distance(begin(), position);
417 impl_.body_.emplace_back(std::forward<V>(val));
418 return {std::next(begin(), distance), true};
419 }
420
421 *position = std::forward<V>(val);
422 return {position, false};
423 }
424
425 // This method is similar to insert, with the following differences:
426 // - Instead of searching [begin(), end()) it only searches [first, last).
427 // - In case no equivalent element is found, val is appended to the end of the
428 // underlying body and an iterator to the next bigger element in [first,
429 // last) is returned.
430 template <class V>
431 std::pair<iterator, bool> append_unique(iterator first,
432 iterator last,
433 V&& val) {
434 auto position = std::lower_bound(first, last, val, value_comp());
435
436 if (position == last || value_comp()(val, *position)) {
437 // emplace_back might invalidate position, which is why distance needs to
438 // be cached.
439 const difference_type distance = std::distance(begin(), position);
440 impl_.body_.emplace_back(std::forward<V>(val));
441 return {std::next(begin(), distance), true};
442 }
443
444 return {position, false};
445 }
446
447 void sort_and_unique(iterator first,
448 iterator last,
449 FlatContainerDupes dupes) {
450 // Preserve stability for the unique code below.
451 std::stable_sort(first, last, impl_.get_value_comp());
452
453 auto comparator = [this](const value_type& lhs, const value_type& rhs) {
454 // lhs is already <= rhs due to sort, therefore
455 // !(lhs < rhs) <=> lhs == rhs.
456 return !impl_.get_value_comp()(lhs, rhs);
457 };
458
459 iterator erase_after;
460 switch (dupes) {
461 case KEEP_FIRST_OF_DUPES:
462 erase_after = std::unique(first, last, comparator);
463 break;
464 case KEEP_LAST_OF_DUPES:
465 erase_after = LastUnique(first, last, comparator);
466 break;
467 }
468 erase(erase_after, last);
469 }
470
471 // To support comparators that may not be possible to default-construct, we
472 // have to store an instance of Compare. Using this to store all internal
473 // state of flat_tree and using private inheritance to store compare lets us
474 // take advantage of an empty base class optimization to avoid extra space in
475 // the common case when Compare has no state.
476 struct Impl : private value_compare {
477 Impl() = default;
478
479 template <class Cmp, class... Body>
480 explicit Impl(Cmp&& compare_arg, Body&&... underlying_type_args)
481 : value_compare(std::forward<Cmp>(compare_arg)),
482 body_(std::forward<Body>(underlying_type_args)...) {}
483
484 const value_compare& get_value_comp() const { return *this; }
485 const key_compare& get_key_comp() const { return *this; }
486
487 underlying_type body_;
488 } impl_;
489
490 // If the compare is not transparent we want to construct key_type once.
491 template <typename K>
492 using KeyTypeOrK = typename std::
493 conditional<IsTransparentCompare<key_compare>::value, K, key_type>::type;
494 };
495
496 // ----------------------------------------------------------------------------
497 // Lifetime.
498
499 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
500 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree() = default;
501
502 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
503 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
504 const KeyCompare& comp)
505 : impl_(comp) {}
506
507 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
508 template <class InputIterator>
509 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
510 InputIterator first,
511 InputIterator last,
512 FlatContainerDupes dupe_handling,
513 const KeyCompare& comp)
514 : impl_(comp, first, last) {
515 sort_and_unique(begin(), end(), dupe_handling);
516 }
517
518 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
519 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
520 const flat_tree&) = default;
521
522 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
523 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
524 std::vector<value_type> items,
525 FlatContainerDupes dupe_handling,
526 const KeyCompare& comp)
527 : impl_(comp, std::move(items)) {
528 sort_and_unique(begin(), end(), dupe_handling);
529 }
530
531 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
532 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
533 std::initializer_list<value_type> ilist,
534 FlatContainerDupes dupe_handling,
535 const KeyCompare& comp)
536 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {}
537
538 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
539 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default;
540
541 // ----------------------------------------------------------------------------
542 // Assignments.
543
544 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
545 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(
546 const flat_tree&) -> flat_tree& = default;
547
548 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
549 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&)
550 -> flat_tree& = default;
551
552 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
553 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(
554 std::initializer_list<value_type> ilist) -> flat_tree& {
555 impl_.body_ = ilist;
556 sort_and_unique(begin(), end(), KEEP_FIRST_OF_DUPES);
557 return *this;
558 }
559
560 // ----------------------------------------------------------------------------
561 // Memory management.
562
563 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
564 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve(
565 size_type new_capacity) {
566 impl_.body_.reserve(new_capacity);
567 }
568
569 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
570 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::capacity() const
571 -> size_type {
572 return impl_.body_.capacity();
573 }
574
575 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
576 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::shrink_to_fit() {
577 impl_.body_.shrink_to_fit();
578 }
579
580 // ----------------------------------------------------------------------------
581 // Size management.
582
583 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
584 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::clear() {
585 impl_.body_.clear();
586 }
587
588 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
589 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::size() const
590 -> size_type {
591 return impl_.body_.size();
592 }
593
594 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
595 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::max_size() const
596 -> size_type {
597 return impl_.body_.max_size();
598 }
599
600 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
601 bool flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::empty() const {
602 return impl_.body_.empty();
603 }
604
605 // ----------------------------------------------------------------------------
606 // Iterators.
607
608 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
609 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::begin() -> iterator {
610 return impl_.body_.begin();
611 }
612
613 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::begin() const
615 -> const_iterator {
616 return impl_.body_.begin();
617 }
618
619 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
620 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::cbegin() const
621 -> const_iterator {
622 return impl_.body_.cbegin();
623 }
624
625 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
626 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::end() -> iterator {
627 return impl_.body_.end();
628 }
629
630 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
631 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::end() const
632 -> const_iterator {
633 return impl_.body_.end();
634 }
635
636 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
637 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::cend() const
638 -> const_iterator {
639 return impl_.body_.cend();
640 }
641
642 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
643 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rbegin()
644 -> reverse_iterator {
645 return impl_.body_.rbegin();
646 }
647
648 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
649 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rbegin() const
650 -> const_reverse_iterator {
651 return impl_.body_.rbegin();
652 }
653
654 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
655 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::crbegin() const
656 -> const_reverse_iterator {
657 return impl_.body_.crbegin();
658 }
659
660 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
661 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rend()
662 -> reverse_iterator {
663 return impl_.body_.rend();
664 }
665
666 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
667 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rend() const
668 -> const_reverse_iterator {
669 return impl_.body_.rend();
670 }
671
672 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
673 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::crend() const
674 -> const_reverse_iterator {
675 return impl_.body_.crend();
676 }
677
678 // ----------------------------------------------------------------------------
679 // Insert operations.
680 //
681 // Currently we use position_hint the same way as eastl or boost:
682 // https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set.h#L493
683
684 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
685 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
686 const value_type& val) -> std::pair<iterator, bool> {
687 return emplace_key_args(GetKeyFromValue()(val), val);
688 }
689
690 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
691 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
692 value_type&& val) -> std::pair<iterator, bool> {
693 return emplace_key_args(GetKeyFromValue()(val), std::move(val));
694 }
695
696 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
697 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
698 const_iterator position_hint,
699 const value_type& val) -> iterator {
700 return emplace_hint_key_args(position_hint, GetKeyFromValue()(val), val)
701 .first;
702 }
703
704 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
705 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
706 const_iterator position_hint,
707 value_type&& val) -> iterator {
708 return emplace_hint_key_args(position_hint, GetKeyFromValue()(val),
709 std::move(val))
710 .first;
711 }
712
713 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
714 template <class InputIterator>
715 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
716 InputIterator first,
717 InputIterator last,
718 FlatContainerDupes dupes) {
719 if (first == last)
720 return;
721
722 // Cache results whether existing elements should be overwritten and whether
723 // inserting new elements happens immediately or will be done in a batch.
724 const bool overwrite_existing = dupes == KEEP_LAST_OF_DUPES;
725 const bool insert_inplace =
726 is_multipass<InputIterator>() && std::next(first) == last;
727
728 if (insert_inplace) {
729 if (overwrite_existing) {
730 for (; first != last; ++first)
731 insert_or_assign(*first);
732 } else
733 std::copy(first, last, std::inserter(*this, end()));
734 return;
735 }
736
737 // Provide a convenience lambda to obtain an iterator pointing past the last
738 // old element. This needs to be dymanic due to possible re-allocations.
739 const size_type original_size = size();
740 auto middle = [this, original_size]() {
741 return std::next(begin(), original_size);
742 };
743
744 // For batch updates initialize the first insertion point.
745 difference_type pos_first_new = original_size;
746
747 // Loop over the input range while appending new values and overwriting
748 // existing ones, if applicable. Keep track of the first insertion point.
749 if (overwrite_existing) {
750 for (; first != last; ++first) {
751 std::pair<iterator, bool> result =
752 append_or_assign(begin(), middle(), *first);
753 if (result.second) {
754 pos_first_new =
755 std::min(pos_first_new, std::distance(begin(), result.first));
756 }
757 }
758 } else {
759 for (; first != last; ++first) {
760 std::pair<iterator, bool> result =
761 append_unique(begin(), middle(), *first);
762 if (result.second) {
763 pos_first_new =
764 std::min(pos_first_new, std::distance(begin(), result.first));
765 }
766 }
767 }
768
769 // The new elements might be unordered and contain duplicates, so post-process
770 // the just inserted elements and merge them with the rest, inserting them at
771 // the previously found spot.
772 sort_and_unique(middle(), end(), dupes);
773 std::inplace_merge(std::next(begin(), pos_first_new), middle(), end(),
774 value_comp());
775 }
776
777 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
778 template <class... Args>
779 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args)
780 -> std::pair<iterator, bool> {
781 return insert(value_type(std::forward<Args>(args)...));
782 }
783
784 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
785 template <class... Args>
786 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint(
787 const_iterator position_hint,
788 Args&&... args) -> iterator {
789 return insert(position_hint, value_type(std::forward<Args>(args)...));
790 }
791
792 // ----------------------------------------------------------------------------
793 // Erase operations.
794
795 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
796 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
797 iterator position) -> iterator {
798 return impl_.body_.erase(position);
799 }
800
801 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
802 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
803 const_iterator position) -> iterator {
804 return impl_.body_.erase(position);
805 }
806
807 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
808 template <typename K>
809 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(const K& val)
810 -> size_type {
811 auto eq_range = equal_range(val);
812 auto res = std::distance(eq_range.first, eq_range.second);
813 erase(eq_range.first, eq_range.second);
814 return res;
815 }
816
817 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
818 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
819 const_iterator first,
820 const_iterator last) -> iterator {
821 return impl_.body_.erase(first, last);
822 }
823
824 // ----------------------------------------------------------------------------
825 // Comparators.
826
827 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
828 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::key_comp() const
829 -> key_compare {
830 return impl_.get_key_comp();
831 }
832
833 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
834 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::value_comp() const
835 -> value_compare {
836 return impl_.get_value_comp();
837 }
838
839 // ----------------------------------------------------------------------------
840 // Search operations.
841
842 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
843 template <typename K>
844 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::count(
845 const K& key) const -> size_type {
846 auto eq_range = equal_range(key);
847 return std::distance(eq_range.first, eq_range.second);
848 }
849
850 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
851 template <typename K>
852 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(const K& key)
853 -> iterator {
854 return const_cast_it(as_const().find(key));
855 }
856
857 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
858 template <typename K>
859 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(
860 const K& key) const -> const_iterator {
861 auto eq_range = equal_range(key);
862 return (eq_range.first == eq_range.second) ? end() : eq_range.first;
863 }
864
865 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
866 template <typename K>
867 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range(
868 const K& key) -> std::pair<iterator, iterator> {
869 auto res = as_const().equal_range(key);
870 return {const_cast_it(res.first), const_cast_it(res.second)};
871 }
872
873 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
874 template <typename K>
875 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range(
876 const K& key) const -> std::pair<const_iterator, const_iterator> {
877 auto lower = lower_bound(key);
878
879 GetKeyFromValue extractor;
880 if (lower == end() || impl_.get_key_comp()(key, extractor(*lower)))
881 return {lower, lower};
882
883 return {lower, std::next(lower)};
884 }
885
886 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
887 template <typename K>
888 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound(
889 const K& key) -> iterator {
890 return const_cast_it(as_const().lower_bound(key));
891 }
892
893 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
894 template <typename K>
895 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound(
896 const K& key) const -> const_iterator {
897 static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value,
898 "Requested type cannot be bound to the container's key_type "
899 "which is required for a non-transparent compare.");
900
901 const KeyTypeOrK<K>& key_ref = key;
902
903 KeyValueCompare key_value(impl_.get_key_comp());
904 return std::lower_bound(begin(), end(), key_ref, key_value);
905 }
906
907 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
908 template <typename K>
909 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound(
910 const K& key) -> iterator {
911 return const_cast_it(as_const().upper_bound(key));
912 }
913
914 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
915 template <typename K>
916 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound(
917 const K& key) const -> const_iterator {
918 static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value,
919 "Requested type cannot be bound to the container's key_type "
920 "which is required for a non-transparent compare.");
921
922 const KeyTypeOrK<K>& key_ref = key;
923
924 KeyValueCompare key_value(impl_.get_key_comp());
925 return std::upper_bound(begin(), end(), key_ref, key_value);
926 }
927
928 // ----------------------------------------------------------------------------
929 // General operations.
930
931 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
932 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::swap(
933 flat_tree& other) noexcept {
934 std::swap(impl_, other.impl_);
935 }
936
937 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
938 template <class... Args>
939 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::unsafe_emplace(
940 const_iterator position,
941 Args&&... args) -> iterator {
942 return impl_.body_.emplace(position, std::forward<Args>(args)...);
943 }
944
945 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
946 template <class K, class... Args>
947 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_key_args(
948 const K& key,
949 Args&&... args) -> std::pair<iterator, bool> {
950 auto lower = lower_bound(key);
951 if (lower == end() || key_comp()(key, GetKeyFromValue()(*lower)))
952 return {unsafe_emplace(lower, std::forward<Args>(args)...), true};
953 return {lower, false};
954 }
955
956 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
957 template <class K, class... Args>
958 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint_key_args(
959 const_iterator hint,
960 const K& key,
961 Args&&... args) -> std::pair<iterator, bool> {
962 GetKeyFromValue extractor;
963 if ((hint == begin() || key_comp()(extractor(*std::prev(hint)), key))) {
964 if (hint == end() || key_comp()(key, extractor(*hint))) {
965 // *(hint - 1) < key < *hint => key did not exist and hint is correct.
966 return {unsafe_emplace(hint, std::forward<Args>(args)...), true};
967 }
968 if (!key_comp()(extractor(*hint), key)) {
969 // key == *hint => no-op, return correct hint.
970 return {const_cast_it(hint), false};
971 }
972 }
973 // hint was not helpful, dispatch to hintless version.
974 return emplace_key_args(key, std::forward<Args>(args)...);
975 }
976
977 // For containers like sets, the key is the same as the value. This implements
978 // the GetKeyFromValue template parameter to flat_tree for this case.
979 template <class Key>
980 struct GetKeyFromValueIdentity {
981 const Key& operator()(const Key& k) const { return k; }
982 };
983
984 } // namespace internal
985
986 // ----------------------------------------------------------------------------
987 // Free functions.
988
989 // Erases all elements that match predicate. It has O(size) complexity.
990 template <class Key,
991 class Value,
992 class GetKeyFromValue,
993 class KeyCompare,
994 typename Predicate>
995 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>&
996 container,
997 Predicate pred) {
998 container.erase(std::remove_if(container.begin(), container.end(), pred),
999 container.end());
1000 }
1001
1002 } // namespace base
1003
1004 #endif // BASE_CONTAINERS_FLAT_TREE_H_
1005