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

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

Issue 2853333004: Add range insertion for base::flat_tree (Closed)
Patch Set: Reuse Binary Search Result and Dupes Created 3 years, 7 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
« no previous file with comments | « no previous file | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_ 5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_
6 #define BASE_CONTAINERS_FLAT_TREE_H_ 6 #define BASE_CONTAINERS_FLAT_TREE_H_
7 7
8 #include <algorithm> 8 #include <algorithm>
9 #include <iterator>
9 #include <vector> 10 #include <vector>
10 11
11 namespace base { 12 namespace base {
12 13
13 enum FlatContainerDupes { 14 enum FlatContainerDupes {
14 KEEP_FIRST_OF_DUPES, 15 KEEP_FIRST_OF_DUPES,
15 KEEP_LAST_OF_DUPES, 16 KEEP_LAST_OF_DUPES,
16 }; 17 };
17 18
18 namespace internal { 19 namespace internal {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 const_reverse_iterator crbegin() const; 181 const_reverse_iterator crbegin() const;
181 182
182 reverse_iterator rend(); 183 reverse_iterator rend();
183 const_reverse_iterator rend() const; 184 const_reverse_iterator rend() const;
184 const_reverse_iterator crend() const; 185 const_reverse_iterator crend() const;
185 186
186 // -------------------------------------------------------------------------- 187 // --------------------------------------------------------------------------
187 // Insert operations. 188 // Insert operations.
188 // 189 //
189 // Assume that every operation invalidates iterators and references. 190 // Assume that every operation invalidates iterators and references.
190 // Insertion of one element can take O(size). See the Notes section in the 191 // Insertion of one element can take O(size). Capacity of flat_tree grows in
191 // class comments on why we do not currently implement range insertion. 192 // an implementation-defined manner.
192 // Capacity of flat_tree grows in an implementation-defined manner.
193 // 193 //
194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) 194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar)
195 // instead of calling insert() repeatedly. 195 // instead of calling insert() repeatedly.
196 196
197 std::pair<iterator, bool> insert(const value_type& val); 197 std::pair<iterator, bool> insert(const value_type& val);
198 std::pair<iterator, bool> insert(value_type&& val); 198 std::pair<iterator, bool> insert(value_type&& val);
199 199
200 iterator insert(const_iterator position_hint, const value_type& x); 200 iterator insert(const_iterator position_hint, const value_type& x);
201 iterator insert(const_iterator position_hint, value_type&& x); 201 iterator insert(const_iterator position_hint, value_type&& x);
202 202
203 template <class InputIterator>
204 void insert(InputIterator first,
brettw 2017/05/10 16:52:06 Can you add a comment here about FlatContainerDupe
jdoerrie 2017/05/11 06:34:57 Done.
205 InputIterator last,
206 FlatContainerDupes dupes);
207
203 template <class... Args> 208 template <class... Args>
204 std::pair<iterator, bool> emplace(Args&&... args); 209 std::pair<iterator, bool> emplace(Args&&... args);
205 210
206 template <class... Args> 211 template <class... Args>
207 iterator emplace_hint(const_iterator position_hint, Args&&... args); 212 iterator emplace_hint(const_iterator position_hint, Args&&... args);
208 213
209 // -------------------------------------------------------------------------- 214 // --------------------------------------------------------------------------
210 // Erase operations. 215 // Erase operations.
211 // 216 //
212 // Assume that every operation invalidates iterators and references. 217 // Assume that every operation invalidates iterators and references.
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 const key_compare& key_comp_; 314 const key_compare& key_comp_;
310 }; 315 };
311 316
312 const flat_tree& as_const() { return *this; } 317 const flat_tree& as_const() { return *this; }
313 318
314 iterator const_cast_it(const_iterator c_it) { 319 iterator const_cast_it(const_iterator c_it) {
315 auto distance = std::distance(cbegin(), c_it); 320 auto distance = std::distance(cbegin(), c_it);
316 return std::next(begin(), distance); 321 return std::next(begin(), distance);
317 } 322 }
318 323
319 void sort_and_unique(FlatContainerDupes dupes) { 324 void sort_and_unique(iterator first,
325 iterator last,
326 FlatContainerDupes dupes) {
320 // Preserve stability for the unique code below. 327 // Preserve stability for the unique code below.
321 std::stable_sort(begin(), end(), impl_.get_value_comp()); 328 std::stable_sort(first, last, impl_.get_value_comp());
322 329
323 auto comparator = [this](const value_type& lhs, const value_type& rhs) { 330 auto comparator = [this](const value_type& lhs, const value_type& rhs) {
324 // lhs is already <= rhs due to sort, therefore 331 // lhs is already <= rhs due to sort, therefore
325 // !(lhs < rhs) <=> lhs == rhs. 332 // !(lhs < rhs) <=> lhs == rhs.
326 return !impl_.get_value_comp()(lhs, rhs); 333 return !impl_.get_value_comp()(lhs, rhs);
327 }; 334 };
328 335
329 iterator erase_after; 336 iterator erase_after;
330 switch (dupes) { 337 switch (dupes) {
331 case KEEP_FIRST_OF_DUPES: 338 case KEEP_FIRST_OF_DUPES:
332 erase_after = std::unique(begin(), end(), comparator); 339 erase_after = std::unique(first, last, comparator);
333 break; 340 break;
334 case KEEP_LAST_OF_DUPES: 341 case KEEP_LAST_OF_DUPES:
335 erase_after = LastUnique(begin(), end(), comparator); 342 erase_after = LastUnique(first, last, comparator);
336 break; 343 break;
337 } 344 }
338 erase(erase_after, end()); 345 erase(erase_after, last);
339 } 346 }
340 347
341 // To support comparators that may not be possible to default-construct, we 348 // To support comparators that may not be possible to default-construct, we
342 // have to store an instance of Compare. Using this to store all internal 349 // have to store an instance of Compare. Using this to store all internal
343 // state of flat_tree and using private inheritance to store compare lets us 350 // state of flat_tree and using private inheritance to store compare lets us
344 // take advantage of an empty base class optimization to avoid extra space in 351 // take advantage of an empty base class optimization to avoid extra space in
345 // the common case when Compare has no state. 352 // the common case when Compare has no state.
346 struct Impl : private value_compare { 353 struct Impl : private value_compare {
347 Impl() = default; 354 Impl() = default;
348 355
(...skipping 21 matching lines...) Expand all
370 : impl_(comp) {} 377 : impl_(comp) {}
371 378
372 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 379 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
373 template <class InputIterator> 380 template <class InputIterator>
374 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 381 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
375 InputIterator first, 382 InputIterator first,
376 InputIterator last, 383 InputIterator last,
377 FlatContainerDupes dupe_handling, 384 FlatContainerDupes dupe_handling,
378 const KeyCompare& comp) 385 const KeyCompare& comp)
379 : impl_(comp, first, last) { 386 : impl_(comp, first, last) {
380 sort_and_unique(dupe_handling); 387 sort_and_unique(begin(), end(), dupe_handling);
381 } 388 }
382 389
383 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 390 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
384 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 391 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
385 const flat_tree&) = default; 392 const flat_tree&) = default;
386 393
387 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 394 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
388 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) = 395 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) =
389 default; 396 default;
390 397
391 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 398 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
392 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 399 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
393 std::vector<value_type> items, 400 std::vector<value_type> items,
394 FlatContainerDupes dupe_handling, 401 FlatContainerDupes dupe_handling,
395 const KeyCompare& comp) 402 const KeyCompare& comp)
396 : impl_(comp, std::move(items)) { 403 : impl_(comp, std::move(items)) {
397 sort_and_unique(dupe_handling); 404 sort_and_unique(begin(), end(), dupe_handling);
398 } 405 }
399 406
400 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 407 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
401 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 408 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
402 std::initializer_list<value_type> ilist, 409 std::initializer_list<value_type> ilist,
403 FlatContainerDupes dupe_handling, 410 FlatContainerDupes dupe_handling,
404 const KeyCompare& comp) 411 const KeyCompare& comp)
405 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {} 412 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {}
406 413
407 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 414 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
408 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; 415 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default;
409 416
410 // ---------------------------------------------------------------------------- 417 // ----------------------------------------------------------------------------
411 // Assignments. 418 // Assignments.
412 419
413 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 420 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
414 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( 421 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(
415 const flat_tree&) -> flat_tree& = default; 422 const flat_tree&) -> flat_tree& = default;
416 423
417 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 424 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
418 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&) 425 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&)
419 -> flat_tree& = default; 426 -> flat_tree& = default;
420 427
421 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 428 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
422 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( 429 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(
423 std::initializer_list<value_type> ilist) -> flat_tree& { 430 std::initializer_list<value_type> ilist) -> flat_tree& {
424 impl_.body_ = ilist; 431 impl_.body_ = ilist;
425 sort_and_unique(KEEP_FIRST_OF_DUPES); 432 sort_and_unique(begin(), end(), KEEP_FIRST_OF_DUPES);
426 return *this; 433 return *this;
427 } 434 }
428 435
429 // ---------------------------------------------------------------------------- 436 // ----------------------------------------------------------------------------
430 // Memory management. 437 // Memory management.
431 438
432 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 439 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
433 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( 440 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve(
434 size_type new_capacity) { 441 size_type new_capacity) {
435 impl_.body_.reserve(new_capacity); 442 impl_.body_.reserve(new_capacity);
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { 603 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) {
597 if (position_hint == begin() || 604 if (position_hint == begin() ||
598 impl_.get_value_comp()(*(position_hint - 1), val)) 605 impl_.get_value_comp()(*(position_hint - 1), val))
599 // We have to cast away const because of crbug.com/677044. 606 // We have to cast away const because of crbug.com/677044.
600 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); 607 return impl_.body_.insert(const_cast_it(position_hint), std::move(val));
601 } 608 }
602 return insert(std::move(val)).first; 609 return insert(std::move(val)).first;
603 } 610 }
604 611
605 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 612 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
613 template <class InputIterator>
614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
615 InputIterator first,
616 InputIterator last,
617 FlatContainerDupes dupes) -> void {
618 // Initialize the first insertion point and provide a convenience lambda to
619 // obtain an iterator pointing past the old element. This needs to be dymanic
620 // due to possible re-allocations.
621 difference_type pos_first_new = std::distance(begin(), end());
dyaroshev 2017/05/10 17:12:09 Nit: Just say size()? Or are there problems with d
jdoerrie 2017/05/11 06:34:57 Done both now. There usually is a difference, diff
622 auto middle = [this, pos_first_new]() {
623 return std::next(begin(), pos_first_new);
624 };
dyaroshev 2017/05/10 17:12:09 How do you feel about reserve if we can compute di
jdoerrie 2017/05/11 06:34:57 I don't like using reserve, because it can lead to
dyaroshev 2017/05/11 09:46:43 That's a good point.
625
626 for (; first != last; ++first) {
627 iterator lower = std::lower_bound(begin(), middle(), *first, value_comp());
628 if (lower == middle() || value_comp()(*first, *lower)) {
629 // Insert completely new elements at the back.
630 pos_first_new = std::min(pos_first_new, std::distance(begin(), lower));
631 impl_.body_.push_back(*first);
632 } else if (lower != middle() && dupes == KEEP_LAST_OF_DUPES) {
dyaroshev 2017/05/10 17:12:09 1 - The check for (dupes == KEEP_LAST_OF_DUPES) sh
jdoerrie 2017/05/11 06:34:57 Done.
633 // Only overwrite existing elements in case of KEEP_LAST_OF_DUPES.
634 *lower = *first;
635 }
636 }
637
638 // The new elements might be unordered and contain duplicates, so post-process
639 // the just inserted elements and merge them with the rest, inserting them at
640 // the previously found spot.
641 sort_and_unique(middle(), end(), dupes);
642 std::inplace_merge(std::next(begin(), pos_first_new), middle(), end(),
643 value_comp());
dyaroshev 2017/05/10 17:12:09 Have you measured? Are you closer now to inserting
jdoerrie 2017/05/11 06:34:57 See above.
644 }
645
646 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
606 template <class... Args> 647 template <class... Args>
607 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) 648 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args)
608 -> std::pair<iterator, bool> { 649 -> std::pair<iterator, bool> {
609 return insert(value_type(std::forward<Args>(args)...)); 650 return insert(value_type(std::forward<Args>(args)...));
610 } 651 }
611 652
612 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> 653 template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
613 template <class... Args> 654 template <class... Args>
614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( 655 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint(
615 const_iterator position_hint, 656 const_iterator position_hint,
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& 809 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>&
769 container, 810 container,
770 Predicate pred) { 811 Predicate pred) {
771 container.erase(std::remove_if(container.begin(), container.end(), pred), 812 container.erase(std::remove_if(container.begin(), container.end(), pred),
772 container.end()); 813 container.end());
773 } 814 }
774 815
775 } // namespace base 816 } // namespace base
776 817
777 #endif // BASE_CONTAINERS_FLAT_TREE_H_ 818 #endif // BASE_CONTAINERS_FLAT_TREE_H_
OLDNEW
« no previous file with comments | « no previous file | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698