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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/containers/flat_tree.h
diff --git a/base/containers/flat_tree.h b/base/containers/flat_tree.h
index 8e85f2377655f954c585be08bea9749edd79240c..78e0cb747be81b50e6fd90b73608012164598b9a 100644
--- a/base/containers/flat_tree.h
+++ b/base/containers/flat_tree.h
@@ -6,6 +6,7 @@
#define BASE_CONTAINERS_FLAT_TREE_H_
#include <algorithm>
+#include <iterator>
#include <vector>
namespace base {
@@ -187,9 +188,8 @@ class flat_tree {
// Insert operations.
//
// Assume that every operation invalidates iterators and references.
- // Insertion of one element can take O(size). See the Notes section in the
- // class comments on why we do not currently implement range insertion.
- // Capacity of flat_tree grows in an implementation-defined manner.
+ // Insertion of one element can take O(size). Capacity of flat_tree grows in
+ // an implementation-defined manner.
//
// NOTE: Prefer to build a new flat_tree from a std::vector (or similar)
// instead of calling insert() repeatedly.
@@ -200,6 +200,11 @@ class flat_tree {
iterator insert(const_iterator position_hint, const value_type& x);
iterator insert(const_iterator position_hint, value_type&& x);
+ template <class InputIterator>
+ 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.
+ InputIterator last,
+ FlatContainerDupes dupes);
+
template <class... Args>
std::pair<iterator, bool> emplace(Args&&... args);
@@ -316,9 +321,11 @@ class flat_tree {
return std::next(begin(), distance);
}
- void sort_and_unique(FlatContainerDupes dupes) {
+ void sort_and_unique(iterator first,
+ iterator last,
+ FlatContainerDupes dupes) {
// Preserve stability for the unique code below.
- std::stable_sort(begin(), end(), impl_.get_value_comp());
+ std::stable_sort(first, last, impl_.get_value_comp());
auto comparator = [this](const value_type& lhs, const value_type& rhs) {
// lhs is already <= rhs due to sort, therefore
@@ -329,13 +336,13 @@ class flat_tree {
iterator erase_after;
switch (dupes) {
case KEEP_FIRST_OF_DUPES:
- erase_after = std::unique(begin(), end(), comparator);
+ erase_after = std::unique(first, last, comparator);
break;
case KEEP_LAST_OF_DUPES:
- erase_after = LastUnique(begin(), end(), comparator);
+ erase_after = LastUnique(first, last, comparator);
break;
}
- erase(erase_after, end());
+ erase(erase_after, last);
}
// To support comparators that may not be possible to default-construct, we
@@ -377,7 +384,7 @@ flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
FlatContainerDupes dupe_handling,
const KeyCompare& comp)
: impl_(comp, first, last) {
- sort_and_unique(dupe_handling);
+ sort_and_unique(begin(), end(), dupe_handling);
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
@@ -394,7 +401,7 @@ flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
FlatContainerDupes dupe_handling,
const KeyCompare& comp)
: impl_(comp, std::move(items)) {
- sort_and_unique(dupe_handling);
+ sort_and_unique(begin(), end(), dupe_handling);
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
@@ -422,7 +429,7 @@ template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(
std::initializer_list<value_type> ilist) -> flat_tree& {
impl_.body_ = ilist;
- sort_and_unique(KEEP_FIRST_OF_DUPES);
+ sort_and_unique(begin(), end(), KEEP_FIRST_OF_DUPES);
return *this;
}
@@ -602,6 +609,40 @@ auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
return insert(std::move(val)).first;
}
+template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <class InputIterator>
+auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert(
+ InputIterator first,
+ InputIterator last,
+ FlatContainerDupes dupes) -> void {
+ // Initialize the first insertion point and provide a convenience lambda to
+ // obtain an iterator pointing past the old element. This needs to be dymanic
+ // due to possible re-allocations.
+ 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
+ auto middle = [this, pos_first_new]() {
+ return std::next(begin(), pos_first_new);
+ };
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.
+
+ for (; first != last; ++first) {
+ iterator lower = std::lower_bound(begin(), middle(), *first, value_comp());
+ if (lower == middle() || value_comp()(*first, *lower)) {
+ // Insert completely new elements at the back.
+ pos_first_new = std::min(pos_first_new, std::distance(begin(), lower));
+ impl_.body_.push_back(*first);
+ } 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.
+ // Only overwrite existing elements in case of KEEP_LAST_OF_DUPES.
+ *lower = *first;
+ }
+ }
+
+ // The new elements might be unordered and contain duplicates, so post-process
+ // the just inserted elements and merge them with the rest, inserting them at
+ // the previously found spot.
+ sort_and_unique(middle(), end(), dupes);
+ std::inplace_merge(std::next(begin(), pos_first_new), middle(), end(),
+ 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.
+}
+
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
template <class... Args>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args)
« 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