xref: /aosp_15_r20/external/libchrome/base/containers/README.md (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker# base/containers library
2*635a8641SAndroid Build Coastguard Worker
3*635a8641SAndroid Build Coastguard Worker## What goes here
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard WorkerThis directory contains some STL-like containers.
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard WorkerThings should be moved here that are generally applicable across the code base.
8*635a8641SAndroid Build Coastguard WorkerDon't add things here just because you need them in one place and think others
9*635a8641SAndroid Build Coastguard Workermay someday want something similar. You can put specialized containers in
10*635a8641SAndroid Build Coastguard Workeryour component's directory and we can promote them here later if we feel there
11*635a8641SAndroid Build Coastguard Workeris broad applicability.
12*635a8641SAndroid Build Coastguard Worker
13*635a8641SAndroid Build Coastguard Worker### Design and naming
14*635a8641SAndroid Build Coastguard Worker
15*635a8641SAndroid Build Coastguard WorkerContainers should adhere as closely to STL as possible. Functions and behaviors
16*635a8641SAndroid Build Coastguard Workernot present in STL should only be added when they are related to the specific
17*635a8641SAndroid Build Coastguard Workerdata structure implemented by the container.
18*635a8641SAndroid Build Coastguard Worker
19*635a8641SAndroid Build Coastguard WorkerFor STL-like containers our policy is that they should use STL-like naming even
20*635a8641SAndroid Build Coastguard Workerwhen it may conflict with the style guide. So functions and class names should
21*635a8641SAndroid Build Coastguard Workerbe lower case with underscores. Non-STL-like classes and functions should use
22*635a8641SAndroid Build Coastguard WorkerGoogle naming. Be sure to use the base namespace.
23*635a8641SAndroid Build Coastguard Worker
24*635a8641SAndroid Build Coastguard Worker## Map and set selection
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker### Usage advice
27*635a8641SAndroid Build Coastguard Worker
28*635a8641SAndroid Build Coastguard Worker  * Generally avoid **std::unordered\_set** and **std::unordered\_map**. In the
29*635a8641SAndroid Build Coastguard Worker    common case, query performance is unlikely to be sufficiently higher than
30*635a8641SAndroid Build Coastguard Worker    std::map to make a difference, insert performance is slightly worse, and
31*635a8641SAndroid Build Coastguard Worker    the memory overhead is high. This makes sense mostly for large tables where
32*635a8641SAndroid Build Coastguard Worker    you expect a lot of lookups.
33*635a8641SAndroid Build Coastguard Worker
34*635a8641SAndroid Build Coastguard Worker  * Most maps and sets in Chrome are small and contain objects that can be
35*635a8641SAndroid Build Coastguard Worker    moved efficiently. In this case, consider **base::flat\_map** and
36*635a8641SAndroid Build Coastguard Worker    **base::flat\_set**. You need to be aware of the maximum expected size of
37*635a8641SAndroid Build Coastguard Worker    the container since individual inserts and deletes are O(n), giving O(n^2)
38*635a8641SAndroid Build Coastguard Worker    construction time for the entire map. But because it avoids mallocs in most
39*635a8641SAndroid Build Coastguard Worker    cases, inserts are better or comparable to other containers even for
40*635a8641SAndroid Build Coastguard Worker    several dozen items, and efficiently-moved types are unlikely to have
41*635a8641SAndroid Build Coastguard Worker    performance problems for most cases until you have hundreds of items. If
42*635a8641SAndroid Build Coastguard Worker    your container can be constructed in one shot, the constructor from vector
43*635a8641SAndroid Build Coastguard Worker    gives O(n log n) construction times and it should be strictly better than
44*635a8641SAndroid Build Coastguard Worker    a std::map.
45*635a8641SAndroid Build Coastguard Worker
46*635a8641SAndroid Build Coastguard Worker  * **base::small\_map** has better runtime memory usage without the poor
47*635a8641SAndroid Build Coastguard Worker    mutation performance of large containers that base::flat\_map has. But this
48*635a8641SAndroid Build Coastguard Worker    advantage is partially offset by additional code size. Prefer in cases
49*635a8641SAndroid Build Coastguard Worker    where you make many objects so that the code/heap tradeoff is good.
50*635a8641SAndroid Build Coastguard Worker
51*635a8641SAndroid Build Coastguard Worker  * Use **std::map** and **std::set** if you can't decide. Even if they're not
52*635a8641SAndroid Build Coastguard Worker    great, they're unlikely to be bad or surprising.
53*635a8641SAndroid Build Coastguard Worker
54*635a8641SAndroid Build Coastguard Worker### Map and set details
55*635a8641SAndroid Build Coastguard Worker
56*635a8641SAndroid Build Coastguard WorkerSizes are on 64-bit platforms. Stable iterators aren't invalidated when the
57*635a8641SAndroid Build Coastguard Workercontainer is mutated.
58*635a8641SAndroid Build Coastguard Worker
59*635a8641SAndroid Build Coastguard Worker| Container                                | Empty size            | Per-item overhead | Stable iterators? |
60*635a8641SAndroid Build Coastguard Worker|:---------------------------------------- |:--------------------- |:----------------- |:----------------- |
61*635a8641SAndroid Build Coastguard Worker| std::map, std::set                       | 16 bytes              | 32 bytes          | Yes               |
62*635a8641SAndroid Build Coastguard Worker| std::unordered\_map, std::unordered\_set | 128 bytes             | 16-24 bytes       | No                |
63*635a8641SAndroid Build Coastguard Worker| base::flat\_map and base::flat\_set      | 24 bytes              | 0 (see notes)     | No                |
64*635a8641SAndroid Build Coastguard Worker| base::small\_map                         | 24 bytes (see notes)  | 32 bytes          | No                |
65*635a8641SAndroid Build Coastguard Worker
66*635a8641SAndroid Build Coastguard Worker**Takeaways:** std::unordered\_map and std::unordered\_map have high
67*635a8641SAndroid Build Coastguard Workeroverhead for small container sizes, prefer these only for larger workloads.
68*635a8641SAndroid Build Coastguard Worker
69*635a8641SAndroid Build Coastguard WorkerCode size comparisons for a block of code (see appendix) on Windows using
70*635a8641SAndroid Build Coastguard Workerstrings as keys.
71*635a8641SAndroid Build Coastguard Worker
72*635a8641SAndroid Build Coastguard Worker| Container           | Code size  |
73*635a8641SAndroid Build Coastguard Worker|:------------------- |:---------- |
74*635a8641SAndroid Build Coastguard Worker| std::unordered\_map | 1646 bytes |
75*635a8641SAndroid Build Coastguard Worker| std::map            | 1759 bytes |
76*635a8641SAndroid Build Coastguard Worker| base::flat\_map     | 1872 bytes |
77*635a8641SAndroid Build Coastguard Worker| base::small\_map    | 2410 bytes |
78*635a8641SAndroid Build Coastguard Worker
79*635a8641SAndroid Build Coastguard Worker**Takeaways:** base::small\_map generates more code because of the inlining of
80*635a8641SAndroid Build Coastguard Workerboth brute-force and red-black tree searching. This makes it less attractive
81*635a8641SAndroid Build Coastguard Workerfor random one-off uses. But if your code is called frequently, the runtime
82*635a8641SAndroid Build Coastguard Workermemory benefits will be more important. The code sizes of the other maps are
83*635a8641SAndroid Build Coastguard Workerclose enough it's not worth worrying about.
84*635a8641SAndroid Build Coastguard Worker
85*635a8641SAndroid Build Coastguard Worker### std::map and std::set
86*635a8641SAndroid Build Coastguard Worker
87*635a8641SAndroid Build Coastguard WorkerA red-black tree. Each inserted item requires the memory allocation of a node
88*635a8641SAndroid Build Coastguard Workeron the heap. Each node contains a left pointer, a right pointer, a parent
89*635a8641SAndroid Build Coastguard Workerpointer, and a "color" for the red-black tree (32-bytes per item on 64-bits).
90*635a8641SAndroid Build Coastguard Worker
91*635a8641SAndroid Build Coastguard Worker### std::unordered\_map and std::unordered\_set
92*635a8641SAndroid Build Coastguard Worker
93*635a8641SAndroid Build Coastguard WorkerA hash table. Implemented on Windows as a std::vector + std::list and in libc++
94*635a8641SAndroid Build Coastguard Workeras the equivalent of a std::vector + a std::forward\_list. Both implementations
95*635a8641SAndroid Build Coastguard Workerallocate an 8-entry hash table (containing iterators into the list) on
96*635a8641SAndroid Build Coastguard Workerinitialization, and grow to 64 entries once 8 items are inserted. Above 64
97*635a8641SAndroid Build Coastguard Workeritems, the size doubles every time the load factor exceeds 1.
98*635a8641SAndroid Build Coastguard Worker
99*635a8641SAndroid Build Coastguard WorkerThe empty size is sizeof(std::unordered\_map) = 64 +
100*635a8641SAndroid Build Coastguard Workerthe initial hash table size which is 8 pointers. The per-item overhead in the
101*635a8641SAndroid Build Coastguard Workertable above counts the list node (2 pointers on Windows, 1 pointer in libc++),
102*635a8641SAndroid Build Coastguard Workerplus amortizes the hash table assuming a 0.5 load factor on average.
103*635a8641SAndroid Build Coastguard Worker
104*635a8641SAndroid Build Coastguard WorkerIn a microbenchmark on Windows, inserts of 1M integers into a
105*635a8641SAndroid Build Coastguard Workerstd::unordered\_set took 1.07x the time of std::set, and queries took 0.67x the
106*635a8641SAndroid Build Coastguard Workertime of std::set. For a typical 4-entry set (the statistical mode of map sizes
107*635a8641SAndroid Build Coastguard Workerin the browser), query performance is identical to std::set and base::flat\_set.
108*635a8641SAndroid Build Coastguard WorkerOn ARM, unordered\_set performance can be worse because integer division to
109*635a8641SAndroid Build Coastguard Workercompute the bucket is slow, and a few "less than" operations can be faster than
110*635a8641SAndroid Build Coastguard Workercomputing a hash depending on the key type. The takeaway is that you should not
111*635a8641SAndroid Build Coastguard Workerdefault to using unordered maps because "they're faster."
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker### base::flat\_map and base::flat\_set
114*635a8641SAndroid Build Coastguard Worker
115*635a8641SAndroid Build Coastguard WorkerA sorted std::vector. Seached via binary search, inserts in the middle require
116*635a8641SAndroid Build Coastguard Workermoving elements to make room. Good cache locality. For large objects and large
117*635a8641SAndroid Build Coastguard Workerset sizes, std::vector's doubling-when-full strategy can waste memory.
118*635a8641SAndroid Build Coastguard Worker
119*635a8641SAndroid Build Coastguard WorkerSupports efficient construction from a vector of items which avoids the O(n^2)
120*635a8641SAndroid Build Coastguard Workerinsertion time of each element separately.
121*635a8641SAndroid Build Coastguard Worker
122*635a8641SAndroid Build Coastguard WorkerThe per-item overhead will depend on the underlying std::vector's reallocation
123*635a8641SAndroid Build Coastguard Workerstrategy and the memory access pattern. Assuming items are being linearly added,
124*635a8641SAndroid Build Coastguard Workerone would expect it to be 3/4 full, so per-item overhead will be 0.25 *
125*635a8641SAndroid Build Coastguard Workersizeof(T).
126*635a8641SAndroid Build Coastguard Worker
127*635a8641SAndroid Build Coastguard Worker
128*635a8641SAndroid Build Coastguard Workerflat\_set/flat\_map support a notion of transparent comparisons. Therefore you
129*635a8641SAndroid Build Coastguard Workercan, for example, lookup base::StringPiece in a set of std::strings without
130*635a8641SAndroid Build Coastguard Workerconstructing a temporary std::string. This functionality is based on C++14
131*635a8641SAndroid Build Coastguard Workerextensions to std::set/std::map interface.
132*635a8641SAndroid Build Coastguard Worker
133*635a8641SAndroid Build Coastguard WorkerYou can find more information about transparent comparisons here:
134*635a8641SAndroid Build Coastguard Workerhttp://en.cppreference.com/w/cpp/utility/functional/less_void
135*635a8641SAndroid Build Coastguard Worker
136*635a8641SAndroid Build Coastguard WorkerExample, smart pointer set:
137*635a8641SAndroid Build Coastguard Worker
138*635a8641SAndroid Build Coastguard Worker```cpp
139*635a8641SAndroid Build Coastguard Worker// Declare a type alias using base::UniquePtrComparator.
140*635a8641SAndroid Build Coastguard Workertemplate <typename T>
141*635a8641SAndroid Build Coastguard Workerusing UniquePtrSet = base::flat_set<std::unique_ptr<T>,
142*635a8641SAndroid Build Coastguard Worker                                    base::UniquePtrComparator>;
143*635a8641SAndroid Build Coastguard Worker
144*635a8641SAndroid Build Coastguard Worker// ...
145*635a8641SAndroid Build Coastguard Worker// Collect data.
146*635a8641SAndroid Build Coastguard Workerstd::vector<std::unique_ptr<int>> ptr_vec;
147*635a8641SAndroid Build Coastguard Workerptr_vec.reserve(5);
148*635a8641SAndroid Build Coastguard Workerstd::generate_n(std::back_inserter(ptr_vec), 5, []{
149*635a8641SAndroid Build Coastguard Worker  return std::make_unique<int>(0);
150*635a8641SAndroid Build Coastguard Worker});
151*635a8641SAndroid Build Coastguard Worker
152*635a8641SAndroid Build Coastguard Worker// Construct a set.
153*635a8641SAndroid Build Coastguard WorkerUniquePtrSet<int> ptr_set(std::move(ptr_vec), base::KEEP_FIRST_OF_DUPES);
154*635a8641SAndroid Build Coastguard Worker
155*635a8641SAndroid Build Coastguard Worker// Use raw pointers to lookup keys.
156*635a8641SAndroid Build Coastguard Workerint* ptr = ptr_set.begin()->get();
157*635a8641SAndroid Build Coastguard WorkerEXPECT_TRUE(ptr_set.find(ptr) == ptr_set.begin());
158*635a8641SAndroid Build Coastguard Worker```
159*635a8641SAndroid Build Coastguard Worker
160*635a8641SAndroid Build Coastguard WorkerExample flat_map<std\::string, int>:
161*635a8641SAndroid Build Coastguard Worker
162*635a8641SAndroid Build Coastguard Worker```cpp
163*635a8641SAndroid Build Coastguard Workerbase::flat_map<std::string, int> str_to_int({{"a", 1}, {"c", 2},{"b", 2}},
164*635a8641SAndroid Build Coastguard Worker                                            base::KEEP_FIRST_OF_DUPES);
165*635a8641SAndroid Build Coastguard Worker
166*635a8641SAndroid Build Coastguard Worker// Does not construct temporary strings.
167*635a8641SAndroid Build Coastguard Workerstr_to_int.find("c")->second = 3;
168*635a8641SAndroid Build Coastguard Workerstr_to_int.erase("c");
169*635a8641SAndroid Build Coastguard WorkerEXPECT_EQ(str_to_int.end(), str_to_int.find("c")->second);
170*635a8641SAndroid Build Coastguard Worker
171*635a8641SAndroid Build Coastguard Worker// NOTE: This does construct a temporary string. This happens since if the
172*635a8641SAndroid Build Coastguard Worker// item is not in the container, then it needs to be constructed, which is
173*635a8641SAndroid Build Coastguard Worker// something that transparent comparators don't have to guarantee.
174*635a8641SAndroid Build Coastguard Workerstr_to_int["c"] = 3;
175*635a8641SAndroid Build Coastguard Worker```
176*635a8641SAndroid Build Coastguard Worker
177*635a8641SAndroid Build Coastguard Worker### base::small\_map
178*635a8641SAndroid Build Coastguard Worker
179*635a8641SAndroid Build Coastguard WorkerA small inline buffer that is brute-force searched that overflows into a full
180*635a8641SAndroid Build Coastguard Workerstd::map or std::unordered\_map. This gives the memory benefit of
181*635a8641SAndroid Build Coastguard Workerbase::flat\_map for small data sizes without the degenerate insertion
182*635a8641SAndroid Build Coastguard Workerperformance for large container sizes.
183*635a8641SAndroid Build Coastguard Worker
184*635a8641SAndroid Build Coastguard WorkerSince instantiations require both code for a std::map and a brute-force search
185*635a8641SAndroid Build Coastguard Workerof the inline container, plus a fancy iterator to cover both cases, code size
186*635a8641SAndroid Build Coastguard Workeris larger.
187*635a8641SAndroid Build Coastguard Worker
188*635a8641SAndroid Build Coastguard WorkerThe initial size in the above table is assuming a very small inline table. The
189*635a8641SAndroid Build Coastguard Workeractual size will be sizeof(int) + min(sizeof(std::map), sizeof(T) *
190*635a8641SAndroid Build Coastguard Workerinline\_size).
191*635a8641SAndroid Build Coastguard Worker
192*635a8641SAndroid Build Coastguard Worker# Deque
193*635a8641SAndroid Build Coastguard Worker
194*635a8641SAndroid Build Coastguard Worker### Usage advice
195*635a8641SAndroid Build Coastguard Worker
196*635a8641SAndroid Build Coastguard WorkerChromium code should always use `base::circular_deque` or `base::queue` in
197*635a8641SAndroid Build Coastguard Workerpreference to `std::deque` or `std::queue` due to memory usage and platform
198*635a8641SAndroid Build Coastguard Workervariation.
199*635a8641SAndroid Build Coastguard Worker
200*635a8641SAndroid Build Coastguard WorkerThe `base::circular_deque` implementation (and the `base::queue` which uses it)
201*635a8641SAndroid Build Coastguard Workerprovide performance consistent across platforms that better matches most
202*635a8641SAndroid Build Coastguard Workerprogrammer's expectations on performance (it doesn't waste as much space as
203*635a8641SAndroid Build Coastguard Workerlibc++ and doesn't do as many heap allocations as MSVC). It also generates less
204*635a8641SAndroid Build Coastguard Workercode tham `std::queue`: using it across the code base saves several hundred
205*635a8641SAndroid Build Coastguard Workerkilobytes.
206*635a8641SAndroid Build Coastguard Worker
207*635a8641SAndroid Build Coastguard WorkerSince `base::deque` does not have stable iterators and it will move the objects
208*635a8641SAndroid Build Coastguard Workerit contains, it may not be appropriate for all uses. If you need these,
209*635a8641SAndroid Build Coastguard Workerconsider using a `std::list` which will provide constant time insert and erase.
210*635a8641SAndroid Build Coastguard Worker
211*635a8641SAndroid Build Coastguard Worker### std::deque and std::queue
212*635a8641SAndroid Build Coastguard Worker
213*635a8641SAndroid Build Coastguard WorkerThe implementation of `std::deque` varies considerably which makes it hard to
214*635a8641SAndroid Build Coastguard Workerreason about. All implementations use a sequence of data blocks referenced by
215*635a8641SAndroid Build Coastguard Workeran array of pointers. The standard guarantees random access, amortized
216*635a8641SAndroid Build Coastguard Workerconstant operations at the ends, and linear mutations in the middle.
217*635a8641SAndroid Build Coastguard Worker
218*635a8641SAndroid Build Coastguard WorkerIn Microsoft's implementation, each block is the smaller of 16 bytes or the
219*635a8641SAndroid Build Coastguard Workersize of the contained element. This means in practice that every expansion of
220*635a8641SAndroid Build Coastguard Workerthe deque of non-trivial classes requires a heap allocation. libc++ (on Android
221*635a8641SAndroid Build Coastguard Workerand Mac) uses 4K blocks which elimiates the problem of many heap allocations,
222*635a8641SAndroid Build Coastguard Workerbut generally wastes a large amount of space (an Android analysis revealed more
223*635a8641SAndroid Build Coastguard Workerthan 2.5MB wasted space from deque alone, resulting in some optimizations).
224*635a8641SAndroid Build Coastguard Workerlibstdc++ uses an intermediate-size 512 byte buffer.
225*635a8641SAndroid Build Coastguard Worker
226*635a8641SAndroid Build Coastguard WorkerMicrosoft's implementation never shrinks the deque capacity, so the capacity
227*635a8641SAndroid Build Coastguard Workerwill always be the maximum number of elements ever contained. libstdc++
228*635a8641SAndroid Build Coastguard Workerdeallocates blocks as they are freed. libc++ keeps up to two empty blocks.
229*635a8641SAndroid Build Coastguard Worker
230*635a8641SAndroid Build Coastguard Worker### base::circular_deque and base::queue
231*635a8641SAndroid Build Coastguard Worker
232*635a8641SAndroid Build Coastguard WorkerA deque implemented as a circular buffer in an array. The underlying array will
233*635a8641SAndroid Build Coastguard Workergrow like a `std::vector` while the beginning and end of the deque will move
234*635a8641SAndroid Build Coastguard Workeraround. The items will wrap around the underlying buffer so the storage will
235*635a8641SAndroid Build Coastguard Workernot be contiguous, but fast random access iterators are still possible.
236*635a8641SAndroid Build Coastguard Worker
237*635a8641SAndroid Build Coastguard WorkerWhen the underlying buffer is filled, it will be reallocated and the constents
238*635a8641SAndroid Build Coastguard Workermoved (like a `std::vector`). The underlying buffer will be shrunk if there is
239*635a8641SAndroid Build Coastguard Workertoo much wasted space (_unlike_ a `std::vector`). As a result, iterators are
240*635a8641SAndroid Build Coastguard Workernot stable across mutations.
241*635a8641SAndroid Build Coastguard Worker
242*635a8641SAndroid Build Coastguard Worker# Stack
243*635a8641SAndroid Build Coastguard Worker
244*635a8641SAndroid Build Coastguard Worker`std::stack` is like `std::queue` in that it is a wrapper around an underlying
245*635a8641SAndroid Build Coastguard Workercontainer. The default container is `std::deque` so everything from the deque
246*635a8641SAndroid Build Coastguard Workersection applies.
247*635a8641SAndroid Build Coastguard Worker
248*635a8641SAndroid Build Coastguard WorkerChromium provides `base/containers/stack.h` which defines `base::stack` that
249*635a8641SAndroid Build Coastguard Workershould be used in preference to std::stack. This changes the underlying
250*635a8641SAndroid Build Coastguard Workercontainer to `base::circular_deque`. The result will be very similar to
251*635a8641SAndroid Build Coastguard Workermanually specifying a `std::vector` for the underlying implementation except
252*635a8641SAndroid Build Coastguard Workerthat the storage will shrink when it gets too empty (vector will never
253*635a8641SAndroid Build Coastguard Workerreallocate to a smaller size).
254*635a8641SAndroid Build Coastguard Worker
255*635a8641SAndroid Build Coastguard WorkerWatch out: with some stack usage patterns it's easy to depend on unstable
256*635a8641SAndroid Build Coastguard Workerbehavior:
257*635a8641SAndroid Build Coastguard Worker
258*635a8641SAndroid Build Coastguard Worker```cpp
259*635a8641SAndroid Build Coastguard Workerbase::stack<Foo> stack;
260*635a8641SAndroid Build Coastguard Workerfor (...) {
261*635a8641SAndroid Build Coastguard Worker  Foo& current = stack.top();
262*635a8641SAndroid Build Coastguard Worker  DoStuff();  // May call stack.push(), say if writing a parser.
263*635a8641SAndroid Build Coastguard Worker  current.done = true;  // Current may reference deleted item!
264*635a8641SAndroid Build Coastguard Worker}
265*635a8641SAndroid Build Coastguard Worker```
266*635a8641SAndroid Build Coastguard Worker
267*635a8641SAndroid Build Coastguard Worker## Appendix
268*635a8641SAndroid Build Coastguard Worker
269*635a8641SAndroid Build Coastguard Worker### Code for map code size comparison
270*635a8641SAndroid Build Coastguard Worker
271*635a8641SAndroid Build Coastguard WorkerThis just calls insert and query a number of times, with printfs that prevent
272*635a8641SAndroid Build Coastguard Workerthings from being dead-code eliminated.
273*635a8641SAndroid Build Coastguard Worker
274*635a8641SAndroid Build Coastguard Worker```cpp
275*635a8641SAndroid Build Coastguard WorkerTEST(Foo, Bar) {
276*635a8641SAndroid Build Coastguard Worker  base::small_map<std::map<std::string, Flubber>> foo;
277*635a8641SAndroid Build Coastguard Worker  foo.insert(std::make_pair("foo", Flubber(8, "bar")));
278*635a8641SAndroid Build Coastguard Worker  foo.insert(std::make_pair("bar", Flubber(8, "bar")));
279*635a8641SAndroid Build Coastguard Worker  foo.insert(std::make_pair("foo1", Flubber(8, "bar")));
280*635a8641SAndroid Build Coastguard Worker  foo.insert(std::make_pair("bar1", Flubber(8, "bar")));
281*635a8641SAndroid Build Coastguard Worker  foo.insert(std::make_pair("foo", Flubber(8, "bar")));
282*635a8641SAndroid Build Coastguard Worker  foo.insert(std::make_pair("bar", Flubber(8, "bar")));
283*635a8641SAndroid Build Coastguard Worker  auto found = foo.find("asdf");
284*635a8641SAndroid Build Coastguard Worker  printf("Found is %d\n", (int)(found == foo.end()));
285*635a8641SAndroid Build Coastguard Worker  found = foo.find("foo");
286*635a8641SAndroid Build Coastguard Worker  printf("Found is %d\n", (int)(found == foo.end()));
287*635a8641SAndroid Build Coastguard Worker  found = foo.find("bar");
288*635a8641SAndroid Build Coastguard Worker  printf("Found is %d\n", (int)(found == foo.end()));
289*635a8641SAndroid Build Coastguard Worker  found = foo.find("asdfhf");
290*635a8641SAndroid Build Coastguard Worker  printf("Found is %d\n", (int)(found == foo.end()));
291*635a8641SAndroid Build Coastguard Worker  found = foo.find("bar1");
292*635a8641SAndroid Build Coastguard Worker  printf("Found is %d\n", (int)(found == foo.end()));
293*635a8641SAndroid Build Coastguard Worker}
294*635a8641SAndroid Build Coastguard Worker```
295*635a8641SAndroid Build Coastguard Worker
296