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