Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: base/containers/flat_tree.h

Issue 2715433007: Add a flat_map container (Closed)
Patch Set: Fixes Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_
6 #define BASE_CONTAINERS_FLAT_TREE_H_
7
8 #include <algorithm>
9 #include <vector>
10
11 namespace base {
12 namespace internal {
13
14 // Implementation of a sorted vector for backing flat_set and flat_map. Do not
15 // use directly.
16 //
17 // The use of "value" in this is like std::map uses, meaning it's the thing
18 // contained (in the case of map it's a <Kay, Mapped> pair). The Key is how
19 // things are looked up. In the case of a set, Key == Value. In the case of
20 // a map, the Key is a component of a Value.
21 //
22 // The helper class GetKeyFromValue provides the means to extract a key from a
23 // value for comparison purposes. It should implement:
24 // const Key& operator()(const Value&).
25 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
26 class flat_tree {
27 public:
28 private:
29 using underlying_type = std::vector<Value>;
30
31 public:
32 // --------------------------------------------------------------------------
33 // Types.
34 //
35 using key_type = Key;
36 using key_compare = KeyCompare;
37 using value_type = Value;
38
39 // Wraps the templated key comparison to compare values.
40 class value_compare : public key_compare {
41 public:
42 value_compare() = default;
43
44 template <class Cmp>
45 explicit value_compare(Cmp&& compare_arg)
46 : KeyCompare(std::forward<Cmp>(compare_arg)) {}
47
48 bool operator()(const Value& left, const Value& right) const {
49 GetKeyFromValue extractor;
50 return key_compare::operator()(extractor(left), extractor(right));
51 }
52 };
53
54 using pointer = typename underlying_type::pointer;
55 using const_pointer = typename underlying_type::const_pointer;
56 using reference = typename underlying_type::reference;
57 using const_reference = typename underlying_type::const_reference;
58 using size_type = typename underlying_type::size_type;
59 using difference_type = typename underlying_type::difference_type;
60 using iterator = typename underlying_type::iterator;
61 using const_iterator = typename underlying_type::const_iterator;
62 using reverse_iterator = typename underlying_type::reverse_iterator;
63 using const_reverse_iterator =
64 typename underlying_type::const_reverse_iterator;
65
66 // --------------------------------------------------------------------------
67 // Lifetime.
68 //
69 // Constructors that take range guarantee O(N * log^2(N)) + O(N) complexity
70 // and take O(N * log(N)) + O(N) if extra memory is available (N is a range
71 // length).
72 //
73 // Assume that move constructors invalidate iterators and references.
74
75 flat_tree();
76 explicit flat_tree(const key_compare& comp);
77
78 template <class InputIterator>
79 flat_tree(InputIterator first,
80 InputIterator last,
81 const key_compare& comp = key_compare());
82
83 flat_tree(const flat_tree&);
84 flat_tree(flat_tree&&) noexcept;
85
86 flat_tree(std::initializer_list<value_type> ilist,
87 const key_compare& comp = key_compare());
88
89 ~flat_tree();
90
91 // --------------------------------------------------------------------------
92 // Assignments.
93 //
94 // Assume that move assignment invalidates iterators and references.
95
96 flat_tree& operator=(const flat_tree&);
97 flat_tree& operator=(flat_tree&&) noexcept;
98 // Not stable in the presence of duplicates in the initializer list.
99 flat_tree& operator=(std::initializer_list<value_type> ilist);
100
101 // --------------------------------------------------------------------------
102 // Memory management.
103 //
104 // Beware that shrink_to_fit() simply forwards the request to the
105 // underlying_type and its implementation is free to optimize otherwise and
106 // leave capacity() to be greater that its size.
107 //
108 // reserve() and shrink_to_fit() invalidate iterators and references.
109
110 void reserve(size_type new_capacity);
111 size_type capacity() const;
112 void shrink_to_fit();
113
114 // --------------------------------------------------------------------------
115 // Size management.
116 //
117 // clear() leaves the capacity() of the flat_tree unchanged.
118
119 void clear();
120
121 size_type size() const;
122 size_type max_size() const;
123 bool empty() const;
124
125 // --------------------------------------------------------------------------
126 // Iterators.
127
128 iterator begin();
129 const_iterator begin() const;
130 const_iterator cbegin() const;
131
132 iterator end();
133 const_iterator end() const;
134 const_iterator cend() const;
135
136 reverse_iterator rbegin();
137 const_reverse_iterator rbegin() const;
138 const_reverse_iterator crbegin() const;
139
140 reverse_iterator rend();
141 const_reverse_iterator rend() const;
142 const_reverse_iterator crend() const;
143
144 // --------------------------------------------------------------------------
145 // Insert operations.
146 //
147 // Assume that every operation invalidates iterators and references.
148 // Insertion of one element can take O(size). See the Notes section in the
149 // class comments on why we do not currently implement range insertion.
150 // Capacity of flat_tree grows in an implementation-defined manner.
151 //
152 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar)
153 // instead of calling insert() repeatedly.
154
155 std::pair<iterator, bool> insert(const value_type& val);
156 std::pair<iterator, bool> insert(value_type&& val);
157
158 iterator insert(const_iterator position_hint, const value_type& x);
159 iterator insert(const_iterator position_hint, value_type&& x);
160
161 template <class... Args>
162 std::pair<iterator, bool> emplace(Args&&... args);
163
164 template <class... Args>
165 iterator emplace_hint(const_iterator position_hint, Args&&... args);
166
167 // --------------------------------------------------------------------------
168 // Erase operations.
169 //
170 // Assume that every operation invalidates iterators and references.
171 //
172 // erase(position), erase(first, last) can take O(size).
173 // erase(key) may take O(size) + O(log(size)).
174 //
175 // Prefer the erase(std::remove(), end()) idiom for deleting multiple
176 // elements.
177
178 iterator erase(const_iterator position);
179 iterator erase(const_iterator first, const_iterator last);
180 size_type erase(const key_type& key);
181
182 // --------------------------------------------------------------------------
183 // Comparators.
184
185 key_compare key_comp() const;
186 value_compare value_comp() const;
187
188 // --------------------------------------------------------------------------
189 // Search operations.
190 //
191 // Search operations have O(log(size)) complexity.
192
193 size_type count(const key_type& key) const;
194
195 iterator find(const key_type& key);
196 const_iterator find(const key_type& key) const;
197
198 std::pair<iterator, iterator> equal_range(const key_type& ket);
199 std::pair<const_iterator, const_iterator> equal_range(
200 const key_type& key) const;
201
202 iterator lower_bound(const key_type& key);
203 const_iterator lower_bound(const key_type& key) const;
204
205 iterator upper_bound(const key_type& key);
206 const_iterator upper_bound(const key_type& key) const;
207
208 // --------------------------------------------------------------------------
209 // General operations.
210 //
211 // Assume that swap invalidates iterators and references.
212 //
213 // Implementation note: currently we use operator==() and operator<() on
214 // std::vector, because they have the same contract we need, so we use them
215 // directly for brevity and in case it is more optimal than calling equal()
216 // and lexicograhpical_compare(). If the underlying container type is changed,
217 // this code may need to be modified.
218
219 void swap(flat_tree& other) noexcept;
220
221 friend bool operator==(const flat_tree& lhs, const flat_tree& rhs) {
222 return lhs.impl_.body_ == rhs.impl_.body_;
223 }
224
225 friend bool operator!=(const flat_tree& lhs, const flat_tree& rhs) {
226 return !(lhs == rhs);
227 }
228
229 friend bool operator<(const flat_tree& lhs, const flat_tree& rhs) {
230 return lhs.impl_.body_ < rhs.impl_.body_;
231 }
232
233 friend bool operator>(const flat_tree& lhs, const flat_tree& rhs) {
234 return rhs < lhs;
235 }
236
237 friend bool operator>=(const flat_tree& lhs, const flat_tree& rhs) {
238 return !(lhs < rhs);
239 }
240
241 friend bool operator<=(const flat_tree& lhs, const flat_tree& rhs) {
242 return !(lhs > rhs);
243 }
244
245 friend void swap(flat_tree& lhs, flat_tree& rhs) noexcept { lhs.swap(rhs); }
246
247 protected:
248 // Inserts a new item into the tree that is known not to be in it. This
249 // is for implementing map [] and at().
250 iterator unsafe_insert_new_at(const_iterator position, const value_type& val);
251 iterator unsafe_insert_new_at(const_iterator position, value_type&& val);
252
253 private:
254 // Helper class for e.g. lower_bound that can compare a value on the left
255 // to a key on the right.
256 struct KeyValueCompare {
257 // The key comparison object must outlive this class.
258 explicit KeyValueCompare(const key_compare& key_comp)
259 : key_comp_(key_comp) {}
260
261 bool operator()(const value_type& left, const key_type& right) const {
262 GetKeyFromValue extractor;
263 return key_comp_(extractor(left), right);
264 }
265
266 private:
267 const key_compare& key_comp_;
268 };
269
270 const flat_tree& as_const() { return *this; }
271
272 iterator const_cast_it(const_iterator c_it) {
273 auto distance = std::distance(cbegin(), c_it);
274 return std::next(begin(), distance);
275 }
276
277 void sort_and_unique() {
278 // std::set sorts elements preserving stability because it doesn't have any
279 // performance wins in not doing that. We do, so we use an unstable sort.
280 std::sort(begin(), end(), impl_.get_value_comp());
281 erase(std::unique(begin(), end(),
282 [this](const value_type& lhs, const value_type& rhs) {
283 // lhs is already <= rhs due to sort, therefore
284 // !(lhs < rhs) <=> lhs == rhs.
285 return !impl_.get_value_comp()(lhs, rhs);
286 }),
287 end());
288 }
289
290 // To support comparators that may not be possible to default-construct, we
291 // have to store an instance of Compare. Using this to store all internal
292 // state of flat_tree and using private inheritance to store compare lets us
293 // take advantage of an empty base class optimization to avoid extra space in
294 // the common case when Compare has no state.
295 struct Impl : private value_compare {
296 Impl() = default;
297
298 template <class Cmp, class... Body>
299 explicit Impl(Cmp&& compare_arg, Body&&... underlying_type_args)
300 : value_compare(std::forward<Cmp>(compare_arg)),
301 body_(std::forward<Body>(underlying_type_args)...) {}
302
303 const value_compare& get_value_comp() const { return *this; }
304 const key_compare& get_key_comp() const { return *this; }
305
306 underlying_type body_;
307 } impl_;
308 };
309
310 // ----------------------------------------------------------------------------
311 // Lifetime.
312
313 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
314 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree() = default;
315
316 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
317 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
318 const KeyCompare& comp)
319 : impl_(comp) {}
320
321 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
322 template <class InputIterator>
323 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
324 InputIterator first,
325 InputIterator last,
326 const KeyCompare& comp)
327 : impl_(comp, first, last) {
328 sort_and_unique();
329 }
330
331 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
332 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
333 const flat_tree&) = default;
334
335 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
336 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) =
337 default;
338
339 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
340 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
341 std::initializer_list<value_type> ilist,
342 const KeyCompare& comp)
343 : flat_tree(std::begin(ilist), std::end(ilist), comp) {}
344
345 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
346 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default;
347
348 // ----------------------------------------------------------------------------
349 // Assignments.
350
351 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
352 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(
353 const flat_tree&) -> flat_tree& = default;
354
355 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
356 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&)
357 -> flat_tree& = default;
358
359 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
360 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(
361 std::initializer_list<value_type> ilist) noexcept -> flat_tree& {
362 impl_.body_ = ilist;
363 sort_and_unique();
364 return *this;
365 }
366
367 // ----------------------------------------------------------------------------
368 // Memory management.
369
370 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
371 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve(
372 size_type new_capacity) {
373 impl_.body_.reserve(new_capacity);
374 }
375
376 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
377 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::capacity() const
378 -> size_type {
379 return impl_.body_.capacity();
380 }
381
382 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
383 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::shrink_to_fit() {
384 impl_.body_.shrink_to_fit();
385 }
386
387 // ----------------------------------------------------------------------------
388 // Size management.
389
390 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
391 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::clear() {
392 impl_.body_.clear();
393 }
394
395 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
396 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::size() const
397 -> size_type {
398 return impl_.body_.size();
399 }
400
401 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
402 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::max_size() const
403 -> size_type {
404 return impl_.body_.max_size();
405 }
406
407 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
408 bool flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::empty() const {
409 return impl_.body_.empty();
410 }
411
412 // ----------------------------------------------------------------------------
413 // Iterators.
414
415 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
416 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::begin() -> iterator {
417 return impl_.body_.begin();
418 }
419
420 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
421 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::begin() const
422 -> const_iterator {
423 return impl_.body_.begin();
424 }
425
426 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
427 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::cbegin() const
428 -> const_iterator {
429 return impl_.body_.cbegin();
430 }
431
432 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
433 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::end() -> iterator {
434 return impl_.body_.end();
435 }
436
437 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
438 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::end() const
439 -> const_iterator {
440 return impl_.body_.end();
441 }
442
443 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
444 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::cend() const
445 -> const_iterator {
446 return impl_.body_.cend();
447 }
448
449 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
450 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rbegin()
451 -> reverse_iterator {
452 return impl_.body_.rbegin();
453 }
454
455 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
456 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rbegin() const
457 -> const_reverse_iterator {
458 return impl_.body_.rbegin();
459 }
460
461 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
462 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::crbegin() const
463 -> const_reverse_iterator {
464 return impl_.body_.crbegin();
465 }
466
467 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
468 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rend()
469 -> reverse_iterator {
470 return impl_.body_.rend();
471 }
472
473 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
474 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rend() const
475 -> const_reverse_iterator {
476 return impl_.body_.rend();
477 }
478
479 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
480 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::crend() const
481 -> const_reverse_iterator {
482 return impl_.body_.crend();
483 }
484
485 // ----------------------------------------------------------------------------
486 // Insert operations.
487 //
488 // Currently we use position_hint the same way as eastl or boost:
489 // https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set. h#L493
490 //
491 // We duplicate code between copy and move version so that we can avoid
492 // creating a temporary value.
493
494 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
495 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
496 const value_type& val) -> std::pair<iterator, bool> {
497 auto position = lower_bound(val);
498
499 if (position == end() || impl_.get_value_comp()(val, *position))
500 return {impl_.body_.insert(position, val), true};
501
502 return {position, false};
503 }
504
505 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
506 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
507 value_type&& val) -> std::pair<iterator, bool> {
508 GetKeyFromValue extractor;
509 auto position = lower_bound(extractor(val));
510
511 if (position == end() || impl_.get_value_comp()(val, *position))
512 return {impl_.body_.insert(position, std::move(val)), true};
513
514 return {position, false};
515 }
516
517 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
518 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
519 const_iterator position_hint,
520 const value_type& val) -> iterator {
521 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) {
522 if (position_hint == begin() ||
523 impl_.get_value_comp()(*(position_hint - 1), val))
524 // We have to cast away const because of crbug.com/677044.
525 return impl_.body_.insert(const_cast_it(position_hint), val);
526 }
527 return insert(val).first;
528 }
529
530 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
531 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
532 const_iterator position_hint,
533 value_type&& val) -> iterator {
534 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) {
535 if (position_hint == begin() ||
536 impl_.get_value_comp()(*(position_hint - 1), val))
537 // We have to cast away const because of crbug.com/677044.
538 return impl_.body_.insert(const_cast_it(position_hint), std::move(val));
539 }
540 return insert(std::move(val)).first;
541 }
542
543 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
544 template <class... Args>
545 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args)
546 -> std::pair<iterator, bool> {
547 return insert(value_type(std::forward<Args>(args)...));
548 }
549
550 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
551 template <class... Args>
552 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint(
553 const_iterator position_hint,
554 Args&&... args) -> iterator {
555 return insert(position_hint, value_type(std::forward<Args>(args)...));
556 }
557
558 // ----------------------------------------------------------------------------
559 // Erase operations.
560
561 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
562 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
563 const_iterator position) -> iterator {
564 // We have to cast away const because of crbug.com/677044.
565 return impl_.body_.erase(const_cast_it(position));
566 }
567
568 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
569 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
570 const key_type& val) -> size_type {
571 auto eq_range = equal_range(val);
572 auto res = std::distance(eq_range.first, eq_range.second);
573 // We have to cast away const because of crbug.com/677044.
574 erase(const_cast_it(eq_range.first), const_cast_it(eq_range.second));
575 return res;
576 }
577
578 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
579 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
580 const_iterator first,
581 const_iterator last) -> iterator {
582 // We have to cast away const because of crbug.com/677044.
583 return impl_.body_.erase(const_cast_it(first), const_cast_it(last));
584 }
585
586 // ----------------------------------------------------------------------------
587 // Comparators.
588
589 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
590 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::key_comp() const
591 -> key_compare {
592 return impl_.get_key_comp();
593 }
594
595 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
596 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::value_comp() const
597 -> value_compare {
598 return impl_.get_value_comp();
599 }
600
601 // ----------------------------------------------------------------------------
602 // Search operations.
603
604 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
605 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::count(
606 const key_type& key) const -> size_type {
607 auto eq_range = equal_range(key);
608 return std::distance(eq_range.first, eq_range.second);
609 }
610
611 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
612 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(
613 const key_type& key) -> iterator {
614 return const_cast_it(as_const().find(key));
615 }
616
617 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
618 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(
619 const key_type& key) const -> const_iterator {
620 auto eq_range = equal_range(key);
621 return (eq_range.first == eq_range.second) ? end() : eq_range.first;
622 }
623
624 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
625 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range(
626 const key_type& key) -> std::pair<iterator, iterator> {
627 auto res = as_const().equal_range(key);
628 return {const_cast_it(res.first), const_cast_it(res.second)};
629 }
630
631 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
632 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range(
633 const key_type& key) const -> std::pair<const_iterator, const_iterator> {
634 auto lower = lower_bound(key);
635
636 GetKeyFromValue extractor;
637 if (lower == end() || impl_.get_key_comp()(key, extractor(*lower)))
638 return {lower, lower};
639
640 return {lower, std::next(lower)};
641 }
642
643 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
644 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound(
645 const key_type& key) -> iterator {
646 return const_cast_it(as_const().lower_bound(key));
647 }
648
649 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
650 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound(
651 const key_type& key) const -> const_iterator {
652 KeyValueCompare key_value(impl_.get_key_comp());
653 return std::lower_bound(begin(), end(), key, key_value);
654 }
655
656 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
657 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound(
658 const key_type& key) -> iterator {
659 return const_cast_it(as_const().upper_bound(key));
660 }
661
662 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
663 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound(
664 const key_type& key) const -> const_iterator {
665 KeyValueCompare key_value(impl_.get_key_comp());
666 return std::upper_bound(begin(), end(), key, key_value);
667 }
668
669 // ----------------------------------------------------------------------------
670 // General operations.
671
672 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
673 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::swap(
674 flat_tree& other) noexcept {
675 std::swap(impl_, other.impl_);
676 }
677
678 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
679 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::unsafe_insert_new_at(
680 const_iterator position,
681 const value_type& val) -> iterator {
682 return impl_.body_.insert(const_cast_it(position), val);
683 }
684
685 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
686 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::unsafe_insert_new_at(
687 const_iterator position,
688 value_type&& val) -> iterator {
689 // We have to cast away const because of crbug.com/677044.
690 return impl_.body_.insert(const_cast_it(position), std::move(val));
691 }
692
693 // For containers like sets, the key is the same as the value. This implements
694 // the GetKeyFromValue template parameter to flat_tree for this case.
695 template <class Key>
696 struct GetKeyFromValueIdentity {
697 const Key& operator()(const Key& k) const { return k; }
698 };
699
700 } // namespace internal
701 } // namespace base
702
703 #endif // BASE_CONTAINERS_FLAT_TREE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698