xref: /aosp_15_r20/external/webrtc/rtc_base/containers/flat_map.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker // This implementation is borrowed from Chromium.
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #ifndef RTC_BASE_CONTAINERS_FLAT_MAP_H_
14*d9f75844SAndroid Build Coastguard Worker #define RTC_BASE_CONTAINERS_FLAT_MAP_H_
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include <functional>
17*d9f75844SAndroid Build Coastguard Worker #include <tuple>
18*d9f75844SAndroid Build Coastguard Worker #include <utility>
19*d9f75844SAndroid Build Coastguard Worker #include <vector>
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/containers/flat_tree.h"  // IWYU pragma: export
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker namespace flat_containers_internal {
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker // An implementation of the flat_tree GetKeyFromValue template parameter that
29*d9f75844SAndroid Build Coastguard Worker // extracts the key as the first element of a pair.
30*d9f75844SAndroid Build Coastguard Worker struct GetFirst {
31*d9f75844SAndroid Build Coastguard Worker   template <class Key, class Mapped>
operatorGetFirst32*d9f75844SAndroid Build Coastguard Worker   constexpr const Key& operator()(const std::pair<Key, Mapped>& p) const {
33*d9f75844SAndroid Build Coastguard Worker     return p.first;
34*d9f75844SAndroid Build Coastguard Worker   }
35*d9f75844SAndroid Build Coastguard Worker };
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker }  // namespace flat_containers_internal
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker // flat_map is a container with a std::map-like interface that stores its
40*d9f75844SAndroid Build Coastguard Worker // contents in a sorted container, by default a vector.
41*d9f75844SAndroid Build Coastguard Worker //
42*d9f75844SAndroid Build Coastguard Worker // Its implementation mostly tracks the corresponding standardization proposal
43*d9f75844SAndroid Build Coastguard Worker // https://wg21.link/P0429, except that the storage of keys and values is not
44*d9f75844SAndroid Build Coastguard Worker // split.
45*d9f75844SAndroid Build Coastguard Worker //
46*d9f75844SAndroid Build Coastguard Worker // PROS
47*d9f75844SAndroid Build Coastguard Worker //
48*d9f75844SAndroid Build Coastguard Worker //  - Good memory locality.
49*d9f75844SAndroid Build Coastguard Worker //  - Low overhead, especially for smaller maps.
50*d9f75844SAndroid Build Coastguard Worker //  - Performance is good for more workloads than you might expect (see
51*d9f75844SAndroid Build Coastguard Worker //    //base/containers/README.md in Chromium repository)
52*d9f75844SAndroid Build Coastguard Worker //  - Supports C++14 map interface.
53*d9f75844SAndroid Build Coastguard Worker //
54*d9f75844SAndroid Build Coastguard Worker // CONS
55*d9f75844SAndroid Build Coastguard Worker //
56*d9f75844SAndroid Build Coastguard Worker //  - Inserts and removals are O(n).
57*d9f75844SAndroid Build Coastguard Worker //
58*d9f75844SAndroid Build Coastguard Worker // IMPORTANT NOTES
59*d9f75844SAndroid Build Coastguard Worker //
60*d9f75844SAndroid Build Coastguard Worker //  - Iterators are invalidated across mutations. This means that the following
61*d9f75844SAndroid Build Coastguard Worker //    line of code has undefined behavior since adding a new element could
62*d9f75844SAndroid Build Coastguard Worker //    resize the container, invalidating all iterators:
63*d9f75844SAndroid Build Coastguard Worker //      container["new element"] = it.second;
64*d9f75844SAndroid Build Coastguard Worker //  - If possible, construct a flat_map in one operation by inserting into
65*d9f75844SAndroid Build Coastguard Worker //    a container and moving that container into the flat_map constructor.
66*d9f75844SAndroid Build Coastguard Worker //
67*d9f75844SAndroid Build Coastguard Worker // QUICK REFERENCE
68*d9f75844SAndroid Build Coastguard Worker //
69*d9f75844SAndroid Build Coastguard Worker // Most of the core functionality is inherited from flat_tree. Please see
70*d9f75844SAndroid Build Coastguard Worker // flat_tree.h for more details for most of these functions. As a quick
71*d9f75844SAndroid Build Coastguard Worker // reference, the functions available are:
72*d9f75844SAndroid Build Coastguard Worker //
73*d9f75844SAndroid Build Coastguard Worker // Constructors (inputs need not be sorted):
74*d9f75844SAndroid Build Coastguard Worker //   flat_map(const flat_map&);
75*d9f75844SAndroid Build Coastguard Worker //   flat_map(flat_map&&);
76*d9f75844SAndroid Build Coastguard Worker //   flat_map(InputIterator first, InputIterator last,
77*d9f75844SAndroid Build Coastguard Worker //            const Compare& compare = Compare());
78*d9f75844SAndroid Build Coastguard Worker //   flat_map(const container_type& items,
79*d9f75844SAndroid Build Coastguard Worker //            const Compare& compare = Compare());
80*d9f75844SAndroid Build Coastguard Worker //   flat_map(container_type&& items,
81*d9f75844SAndroid Build Coastguard Worker //            const Compare& compare = Compare()); // Re-use storage.
82*d9f75844SAndroid Build Coastguard Worker //   flat_map(std::initializer_list<value_type> ilist,
83*d9f75844SAndroid Build Coastguard Worker //            const Compare& comp = Compare());
84*d9f75844SAndroid Build Coastguard Worker //
85*d9f75844SAndroid Build Coastguard Worker // Constructors (inputs need to be sorted):
86*d9f75844SAndroid Build Coastguard Worker //   flat_map(sorted_unique_t,
87*d9f75844SAndroid Build Coastguard Worker //            InputIterator first, InputIterator last,
88*d9f75844SAndroid Build Coastguard Worker //            const Compare& compare = Compare());
89*d9f75844SAndroid Build Coastguard Worker //   flat_map(sorted_unique_t,
90*d9f75844SAndroid Build Coastguard Worker //            const container_type& items,
91*d9f75844SAndroid Build Coastguard Worker //            const Compare& compare = Compare());
92*d9f75844SAndroid Build Coastguard Worker //   flat_map(sorted_unique_t,
93*d9f75844SAndroid Build Coastguard Worker //            container_type&& items,
94*d9f75844SAndroid Build Coastguard Worker //            const Compare& compare = Compare());  // Re-use storage.
95*d9f75844SAndroid Build Coastguard Worker //   flat_map(sorted_unique_t,
96*d9f75844SAndroid Build Coastguard Worker //            std::initializer_list<value_type> ilist,
97*d9f75844SAndroid Build Coastguard Worker //            const Compare& comp = Compare());
98*d9f75844SAndroid Build Coastguard Worker //
99*d9f75844SAndroid Build Coastguard Worker // Assignment functions:
100*d9f75844SAndroid Build Coastguard Worker //   flat_map& operator=(const flat_map&);
101*d9f75844SAndroid Build Coastguard Worker //   flat_map& operator=(flat_map&&);
102*d9f75844SAndroid Build Coastguard Worker //   flat_map& operator=(initializer_list<value_type>);
103*d9f75844SAndroid Build Coastguard Worker //
104*d9f75844SAndroid Build Coastguard Worker // Memory management functions:
105*d9f75844SAndroid Build Coastguard Worker //   void   reserve(size_t);
106*d9f75844SAndroid Build Coastguard Worker //   size_t capacity() const;
107*d9f75844SAndroid Build Coastguard Worker //   void   shrink_to_fit();
108*d9f75844SAndroid Build Coastguard Worker //
109*d9f75844SAndroid Build Coastguard Worker // Size management functions:
110*d9f75844SAndroid Build Coastguard Worker //   void   clear();
111*d9f75844SAndroid Build Coastguard Worker //   size_t size() const;
112*d9f75844SAndroid Build Coastguard Worker //   size_t max_size() const;
113*d9f75844SAndroid Build Coastguard Worker //   bool   empty() const;
114*d9f75844SAndroid Build Coastguard Worker //
115*d9f75844SAndroid Build Coastguard Worker // Iterator functions:
116*d9f75844SAndroid Build Coastguard Worker //   iterator               begin();
117*d9f75844SAndroid Build Coastguard Worker //   const_iterator         begin() const;
118*d9f75844SAndroid Build Coastguard Worker //   const_iterator         cbegin() const;
119*d9f75844SAndroid Build Coastguard Worker //   iterator               end();
120*d9f75844SAndroid Build Coastguard Worker //   const_iterator         end() const;
121*d9f75844SAndroid Build Coastguard Worker //   const_iterator         cend() const;
122*d9f75844SAndroid Build Coastguard Worker //   reverse_iterator       rbegin();
123*d9f75844SAndroid Build Coastguard Worker //   const reverse_iterator rbegin() const;
124*d9f75844SAndroid Build Coastguard Worker //   const_reverse_iterator crbegin() const;
125*d9f75844SAndroid Build Coastguard Worker //   reverse_iterator       rend();
126*d9f75844SAndroid Build Coastguard Worker //   const_reverse_iterator rend() const;
127*d9f75844SAndroid Build Coastguard Worker //   const_reverse_iterator crend() const;
128*d9f75844SAndroid Build Coastguard Worker //
129*d9f75844SAndroid Build Coastguard Worker // Insert and accessor functions:
130*d9f75844SAndroid Build Coastguard Worker //   mapped_type&         operator[](const key_type&);
131*d9f75844SAndroid Build Coastguard Worker //   mapped_type&         operator[](key_type&&);
132*d9f75844SAndroid Build Coastguard Worker //   mapped_type&         at(const K&);
133*d9f75844SAndroid Build Coastguard Worker //   const mapped_type&   at(const K&) const;
134*d9f75844SAndroid Build Coastguard Worker //   pair<iterator, bool> insert(const value_type&);
135*d9f75844SAndroid Build Coastguard Worker //   pair<iterator, bool> insert(value_type&&);
136*d9f75844SAndroid Build Coastguard Worker //   iterator             insert(const_iterator hint, const value_type&);
137*d9f75844SAndroid Build Coastguard Worker //   iterator             insert(const_iterator hint, value_type&&);
138*d9f75844SAndroid Build Coastguard Worker //   void                 insert(InputIterator first, InputIterator last);
139*d9f75844SAndroid Build Coastguard Worker //   pair<iterator, bool> insert_or_assign(K&&, M&&);
140*d9f75844SAndroid Build Coastguard Worker //   iterator             insert_or_assign(const_iterator hint, K&&, M&&);
141*d9f75844SAndroid Build Coastguard Worker //   pair<iterator, bool> emplace(Args&&...);
142*d9f75844SAndroid Build Coastguard Worker //   iterator             emplace_hint(const_iterator, Args&&...);
143*d9f75844SAndroid Build Coastguard Worker //   pair<iterator, bool> try_emplace(K&&, Args&&...);
144*d9f75844SAndroid Build Coastguard Worker //   iterator             try_emplace(const_iterator hint, K&&, Args&&...);
145*d9f75844SAndroid Build Coastguard Worker 
146*d9f75844SAndroid Build Coastguard Worker // Underlying type functions:
147*d9f75844SAndroid Build Coastguard Worker //   container_type       extract() &&;
148*d9f75844SAndroid Build Coastguard Worker //   void                 replace(container_type&&);
149*d9f75844SAndroid Build Coastguard Worker //
150*d9f75844SAndroid Build Coastguard Worker // Erase functions:
151*d9f75844SAndroid Build Coastguard Worker //   iterator erase(iterator);
152*d9f75844SAndroid Build Coastguard Worker //   iterator erase(const_iterator);
153*d9f75844SAndroid Build Coastguard Worker //   iterator erase(const_iterator first, const_iterator& last);
154*d9f75844SAndroid Build Coastguard Worker //   template <class K> size_t erase(const K& key);
155*d9f75844SAndroid Build Coastguard Worker //
156*d9f75844SAndroid Build Coastguard Worker // Comparators (see std::map documentation).
157*d9f75844SAndroid Build Coastguard Worker //   key_compare   key_comp() const;
158*d9f75844SAndroid Build Coastguard Worker //   value_compare value_comp() const;
159*d9f75844SAndroid Build Coastguard Worker //
160*d9f75844SAndroid Build Coastguard Worker // Search functions:
161*d9f75844SAndroid Build Coastguard Worker //   template <typename K> size_t                   count(const K&) const;
162*d9f75844SAndroid Build Coastguard Worker //   template <typename K> iterator                 find(const K&);
163*d9f75844SAndroid Build Coastguard Worker //   template <typename K> const_iterator           find(const K&) const;
164*d9f75844SAndroid Build Coastguard Worker //   template <typename K> bool                     contains(const K&) const;
165*d9f75844SAndroid Build Coastguard Worker //   template <typename K> pair<iterator, iterator> equal_range(const K&);
166*d9f75844SAndroid Build Coastguard Worker //   template <typename K> iterator                 lower_bound(const K&);
167*d9f75844SAndroid Build Coastguard Worker //   template <typename K> const_iterator           lower_bound(const K&) const;
168*d9f75844SAndroid Build Coastguard Worker //   template <typename K> iterator                 upper_bound(const K&);
169*d9f75844SAndroid Build Coastguard Worker //   template <typename K> const_iterator           upper_bound(const K&) const;
170*d9f75844SAndroid Build Coastguard Worker //
171*d9f75844SAndroid Build Coastguard Worker // General functions:
172*d9f75844SAndroid Build Coastguard Worker //   void swap(flat_map&);
173*d9f75844SAndroid Build Coastguard Worker //
174*d9f75844SAndroid Build Coastguard Worker // Non-member operators:
175*d9f75844SAndroid Build Coastguard Worker //   bool operator==(const flat_map&, const flat_map);
176*d9f75844SAndroid Build Coastguard Worker //   bool operator!=(const flat_map&, const flat_map);
177*d9f75844SAndroid Build Coastguard Worker //   bool operator<(const flat_map&, const flat_map);
178*d9f75844SAndroid Build Coastguard Worker //   bool operator>(const flat_map&, const flat_map);
179*d9f75844SAndroid Build Coastguard Worker //   bool operator>=(const flat_map&, const flat_map);
180*d9f75844SAndroid Build Coastguard Worker //   bool operator<=(const flat_map&, const flat_map);
181*d9f75844SAndroid Build Coastguard Worker //
182*d9f75844SAndroid Build Coastguard Worker template <class Key,
183*d9f75844SAndroid Build Coastguard Worker           class Mapped,
184*d9f75844SAndroid Build Coastguard Worker           class Compare = std::less<>,
185*d9f75844SAndroid Build Coastguard Worker           class Container = std::vector<std::pair<Key, Mapped>>>
186*d9f75844SAndroid Build Coastguard Worker class flat_map : public ::webrtc::flat_containers_internal::flat_tree<
187*d9f75844SAndroid Build Coastguard Worker                      Key,
188*d9f75844SAndroid Build Coastguard Worker                      flat_containers_internal::GetFirst,
189*d9f75844SAndroid Build Coastguard Worker                      Compare,
190*d9f75844SAndroid Build Coastguard Worker                      Container> {
191*d9f75844SAndroid Build Coastguard Worker  private:
192*d9f75844SAndroid Build Coastguard Worker   using tree = typename ::webrtc::flat_containers_internal::
193*d9f75844SAndroid Build Coastguard Worker       flat_tree<Key, flat_containers_internal::GetFirst, Compare, Container>;
194*d9f75844SAndroid Build Coastguard Worker 
195*d9f75844SAndroid Build Coastguard Worker  public:
196*d9f75844SAndroid Build Coastguard Worker   using key_type = typename tree::key_type;
197*d9f75844SAndroid Build Coastguard Worker   using mapped_type = Mapped;
198*d9f75844SAndroid Build Coastguard Worker   using value_type = typename tree::value_type;
199*d9f75844SAndroid Build Coastguard Worker   using reference = typename Container::reference;
200*d9f75844SAndroid Build Coastguard Worker   using const_reference = typename Container::const_reference;
201*d9f75844SAndroid Build Coastguard Worker   using size_type = typename Container::size_type;
202*d9f75844SAndroid Build Coastguard Worker   using difference_type = typename Container::difference_type;
203*d9f75844SAndroid Build Coastguard Worker   using iterator = typename tree::iterator;
204*d9f75844SAndroid Build Coastguard Worker   using const_iterator = typename tree::const_iterator;
205*d9f75844SAndroid Build Coastguard Worker   using reverse_iterator = typename tree::reverse_iterator;
206*d9f75844SAndroid Build Coastguard Worker   using const_reverse_iterator = typename tree::const_reverse_iterator;
207*d9f75844SAndroid Build Coastguard Worker   using container_type = typename tree::container_type;
208*d9f75844SAndroid Build Coastguard Worker 
209*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
210*d9f75844SAndroid Build Coastguard Worker   // Lifetime and assignments.
211*d9f75844SAndroid Build Coastguard Worker   //
212*d9f75844SAndroid Build Coastguard Worker   // Note: we explicitly bring operator= in because otherwise
213*d9f75844SAndroid Build Coastguard Worker   //   flat_map<...> x;
214*d9f75844SAndroid Build Coastguard Worker   //   x = {...};
215*d9f75844SAndroid Build Coastguard Worker   // Would first create a flat_map and then move assign it. This most likely
216*d9f75844SAndroid Build Coastguard Worker   // would be optimized away but still affects our debug builds.
217*d9f75844SAndroid Build Coastguard Worker 
218*d9f75844SAndroid Build Coastguard Worker   using tree::tree;
219*d9f75844SAndroid Build Coastguard Worker   using tree::operator=;
220*d9f75844SAndroid Build Coastguard Worker 
221*d9f75844SAndroid Build Coastguard Worker   // Out-of-bound calls to at() will CHECK.
222*d9f75844SAndroid Build Coastguard Worker   template <class K>
223*d9f75844SAndroid Build Coastguard Worker   mapped_type& at(const K& key);
224*d9f75844SAndroid Build Coastguard Worker   template <class K>
225*d9f75844SAndroid Build Coastguard Worker   const mapped_type& at(const K& key) const;
226*d9f75844SAndroid Build Coastguard Worker 
227*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
228*d9f75844SAndroid Build Coastguard Worker   // Map-specific insert operations.
229*d9f75844SAndroid Build Coastguard Worker   //
230*d9f75844SAndroid Build Coastguard Worker   // Normal insert() functions are inherited from flat_tree.
231*d9f75844SAndroid Build Coastguard Worker   //
232*d9f75844SAndroid Build Coastguard Worker   // Assume that every operation invalidates iterators and references.
233*d9f75844SAndroid Build Coastguard Worker   // Insertion of one element can take O(size).
234*d9f75844SAndroid Build Coastguard Worker 
235*d9f75844SAndroid Build Coastguard Worker   mapped_type& operator[](const key_type& key);
236*d9f75844SAndroid Build Coastguard Worker   mapped_type& operator[](key_type&& key);
237*d9f75844SAndroid Build Coastguard Worker 
238*d9f75844SAndroid Build Coastguard Worker   template <class K, class M>
239*d9f75844SAndroid Build Coastguard Worker   std::pair<iterator, bool> insert_or_assign(K&& key, M&& obj);
240*d9f75844SAndroid Build Coastguard Worker   template <class K, class M>
241*d9f75844SAndroid Build Coastguard Worker   iterator insert_or_assign(const_iterator hint, K&& key, M&& obj);
242*d9f75844SAndroid Build Coastguard Worker 
243*d9f75844SAndroid Build Coastguard Worker   template <class K, class... Args>
244*d9f75844SAndroid Build Coastguard Worker   std::enable_if_t<std::is_constructible<key_type, K&&>::value,
245*d9f75844SAndroid Build Coastguard Worker                    std::pair<iterator, bool>>
246*d9f75844SAndroid Build Coastguard Worker   try_emplace(K&& key, Args&&... args);
247*d9f75844SAndroid Build Coastguard Worker 
248*d9f75844SAndroid Build Coastguard Worker   template <class K, class... Args>
249*d9f75844SAndroid Build Coastguard Worker   std::enable_if_t<std::is_constructible<key_type, K&&>::value, iterator>
250*d9f75844SAndroid Build Coastguard Worker   try_emplace(const_iterator hint, K&& key, Args&&... args);
251*d9f75844SAndroid Build Coastguard Worker 
252*d9f75844SAndroid Build Coastguard Worker   // --------------------------------------------------------------------------
253*d9f75844SAndroid Build Coastguard Worker   // General operations.
254*d9f75844SAndroid Build Coastguard Worker   //
255*d9f75844SAndroid Build Coastguard Worker   // Assume that swap invalidates iterators and references.
256*d9f75844SAndroid Build Coastguard Worker 
257*d9f75844SAndroid Build Coastguard Worker   void swap(flat_map& other) noexcept;
258*d9f75844SAndroid Build Coastguard Worker 
swap(flat_map & lhs,flat_map & rhs)259*d9f75844SAndroid Build Coastguard Worker   friend void swap(flat_map& lhs, flat_map& rhs) noexcept { lhs.swap(rhs); }
260*d9f75844SAndroid Build Coastguard Worker };
261*d9f75844SAndroid Build Coastguard Worker 
262*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
263*d9f75844SAndroid Build Coastguard Worker // Lookups.
264*d9f75844SAndroid Build Coastguard Worker 
265*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
266*d9f75844SAndroid Build Coastguard Worker template <class K>
267*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::at(const K& key)
268*d9f75844SAndroid Build Coastguard Worker     -> mapped_type& {
269*d9f75844SAndroid Build Coastguard Worker   iterator found = tree::find(key);
270*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(found != tree::end());
271*d9f75844SAndroid Build Coastguard Worker   return found->second;
272*d9f75844SAndroid Build Coastguard Worker }
273*d9f75844SAndroid Build Coastguard Worker 
274*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
275*d9f75844SAndroid Build Coastguard Worker template <class K>
276*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::at(const K& key) const
277*d9f75844SAndroid Build Coastguard Worker     -> const mapped_type& {
278*d9f75844SAndroid Build Coastguard Worker   const_iterator found = tree::find(key);
279*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(found != tree::cend());
280*d9f75844SAndroid Build Coastguard Worker   return found->second;
281*d9f75844SAndroid Build Coastguard Worker }
282*d9f75844SAndroid Build Coastguard Worker 
283*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
284*d9f75844SAndroid Build Coastguard Worker // Insert operations.
285*d9f75844SAndroid Build Coastguard Worker 
286*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
287*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::operator[](const key_type& key)
288*d9f75844SAndroid Build Coastguard Worker     -> mapped_type& {
289*d9f75844SAndroid Build Coastguard Worker   iterator found = tree::lower_bound(key);
290*d9f75844SAndroid Build Coastguard Worker   if (found == tree::end() || tree::key_comp()(key, found->first))
291*d9f75844SAndroid Build Coastguard Worker     found = tree::unsafe_emplace(found, key, mapped_type());
292*d9f75844SAndroid Build Coastguard Worker   return found->second;
293*d9f75844SAndroid Build Coastguard Worker }
294*d9f75844SAndroid Build Coastguard Worker 
295*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
296*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::operator[](key_type&& key)
297*d9f75844SAndroid Build Coastguard Worker     -> mapped_type& {
298*d9f75844SAndroid Build Coastguard Worker   iterator found = tree::lower_bound(key);
299*d9f75844SAndroid Build Coastguard Worker   if (found == tree::end() || tree::key_comp()(key, found->first))
300*d9f75844SAndroid Build Coastguard Worker     found = tree::unsafe_emplace(found, std::move(key), mapped_type());
301*d9f75844SAndroid Build Coastguard Worker   return found->second;
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker 
304*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
305*d9f75844SAndroid Build Coastguard Worker template <class K, class M>
306*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::insert_or_assign(K&& key,
307*d9f75844SAndroid Build Coastguard Worker                                                                  M&& obj)
308*d9f75844SAndroid Build Coastguard Worker     -> std::pair<iterator, bool> {
309*d9f75844SAndroid Build Coastguard Worker   auto result =
310*d9f75844SAndroid Build Coastguard Worker       tree::emplace_key_args(key, std::forward<K>(key), std::forward<M>(obj));
311*d9f75844SAndroid Build Coastguard Worker   if (!result.second)
312*d9f75844SAndroid Build Coastguard Worker     result.first->second = std::forward<M>(obj);
313*d9f75844SAndroid Build Coastguard Worker   return result;
314*d9f75844SAndroid Build Coastguard Worker }
315*d9f75844SAndroid Build Coastguard Worker 
316*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
317*d9f75844SAndroid Build Coastguard Worker template <class K, class M>
318*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::insert_or_assign(
319*d9f75844SAndroid Build Coastguard Worker     const_iterator hint,
320*d9f75844SAndroid Build Coastguard Worker     K&& key,
321*d9f75844SAndroid Build Coastguard Worker     M&& obj) -> iterator {
322*d9f75844SAndroid Build Coastguard Worker   auto result = tree::emplace_hint_key_args(hint, key, std::forward<K>(key),
323*d9f75844SAndroid Build Coastguard Worker                                             std::forward<M>(obj));
324*d9f75844SAndroid Build Coastguard Worker   if (!result.second)
325*d9f75844SAndroid Build Coastguard Worker     result.first->second = std::forward<M>(obj);
326*d9f75844SAndroid Build Coastguard Worker   return result.first;
327*d9f75844SAndroid Build Coastguard Worker }
328*d9f75844SAndroid Build Coastguard Worker 
329*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
330*d9f75844SAndroid Build Coastguard Worker template <class K, class... Args>
331*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::try_emplace(K&& key,
332*d9f75844SAndroid Build Coastguard Worker                                                             Args&&... args)
333*d9f75844SAndroid Build Coastguard Worker     -> std::enable_if_t<std::is_constructible<key_type, K&&>::value,
334*d9f75844SAndroid Build Coastguard Worker                         std::pair<iterator, bool>> {
335*d9f75844SAndroid Build Coastguard Worker   return tree::emplace_key_args(
336*d9f75844SAndroid Build Coastguard Worker       key, std::piecewise_construct,
337*d9f75844SAndroid Build Coastguard Worker       std::forward_as_tuple(std::forward<K>(key)),
338*d9f75844SAndroid Build Coastguard Worker       std::forward_as_tuple(std::forward<Args>(args)...));
339*d9f75844SAndroid Build Coastguard Worker }
340*d9f75844SAndroid Build Coastguard Worker 
341*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
342*d9f75844SAndroid Build Coastguard Worker template <class K, class... Args>
343*d9f75844SAndroid Build Coastguard Worker auto flat_map<Key, Mapped, Compare, Container>::try_emplace(const_iterator hint,
344*d9f75844SAndroid Build Coastguard Worker                                                             K&& key,
345*d9f75844SAndroid Build Coastguard Worker                                                             Args&&... args)
346*d9f75844SAndroid Build Coastguard Worker     -> std::enable_if_t<std::is_constructible<key_type, K&&>::value, iterator> {
347*d9f75844SAndroid Build Coastguard Worker   return tree::emplace_hint_key_args(
348*d9f75844SAndroid Build Coastguard Worker              hint, key, std::piecewise_construct,
349*d9f75844SAndroid Build Coastguard Worker              std::forward_as_tuple(std::forward<K>(key)),
350*d9f75844SAndroid Build Coastguard Worker              std::forward_as_tuple(std::forward<Args>(args)...))
351*d9f75844SAndroid Build Coastguard Worker       .first;
352*d9f75844SAndroid Build Coastguard Worker }
353*d9f75844SAndroid Build Coastguard Worker 
354*d9f75844SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
355*d9f75844SAndroid Build Coastguard Worker // General operations.
356*d9f75844SAndroid Build Coastguard Worker 
357*d9f75844SAndroid Build Coastguard Worker template <class Key, class Mapped, class Compare, class Container>
swap(flat_map & other)358*d9f75844SAndroid Build Coastguard Worker void flat_map<Key, Mapped, Compare, Container>::swap(flat_map& other) noexcept {
359*d9f75844SAndroid Build Coastguard Worker   tree::swap(other);
360*d9f75844SAndroid Build Coastguard Worker }
361*d9f75844SAndroid Build Coastguard Worker 
362*d9f75844SAndroid Build Coastguard Worker // Erases all elements that match predicate. It has O(size) complexity.
363*d9f75844SAndroid Build Coastguard Worker //
364*d9f75844SAndroid Build Coastguard Worker //  flat_map<int, Timestamp> last_times;
365*d9f75844SAndroid Build Coastguard Worker //  ...
366*d9f75844SAndroid Build Coastguard Worker //  EraseIf(last_times,
367*d9f75844SAndroid Build Coastguard Worker //          [&](const auto& element) { return now - element.second > kLimit; });
368*d9f75844SAndroid Build Coastguard Worker 
369*d9f75844SAndroid Build Coastguard Worker // NOLINTNEXTLINE(misc-unused-using-decls)
370*d9f75844SAndroid Build Coastguard Worker using ::webrtc::flat_containers_internal::EraseIf;
371*d9f75844SAndroid Build Coastguard Worker 
372*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
373*d9f75844SAndroid Build Coastguard Worker 
374*d9f75844SAndroid Build Coastguard Worker #endif  // RTC_BASE_CONTAINERS_FLAT_MAP_H_
375