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

Unified Diff: base/containers/flat_tree.h

Issue 2776793002: Make flat containers stable, allow constructing from vector. (Closed)
Patch Set: Put back media log change lost in merge Created 3 years, 8 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 | « base/containers/flat_set_unittest.cc ('k') | 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 fc9482df8d476d514ae32f62f44fbf57444ad159..c3a234fa784c4f0e0e151d9711d0265b756473fd 100644
--- a/base/containers/flat_tree.h
+++ b/base/containers/flat_tree.h
@@ -9,8 +9,39 @@
#include <vector>
namespace base {
+
+enum FlatContainerDupes {
+ KEEP_FIRST_OF_DUPES,
+ KEEP_LAST_OF_DUPES,
+};
+
namespace internal {
+// This algorithm is like unique() from the standard library except it
+// selects only the last of consecutive values instead of the first.
+template <class Iterator, class BinaryPredicate>
+Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) {
+ if (first == last)
+ return last;
+
+ Iterator dest = first;
+ Iterator cur = first;
+ Iterator prev = cur;
+ while (++cur != last) {
+ if (!compare(*prev, *cur)) {
+ // Non-identical one.
+ if (dest != prev)
+ *dest = std::move(*prev);
+ ++dest;
+ }
+ prev = cur;
+ }
+
+ if (dest != prev)
+ *dest = std::move(*prev);
+ return ++dest;
+}
+
// Implementation of a sorted vector for backing flat_set and flat_map. Do not
// use directly.
//
@@ -24,7 +55,6 @@ namespace internal {
// const Key& operator()(const Value&).
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
class flat_tree {
- public:
private:
using underlying_type = std::vector<Value>;
@@ -71,21 +101,28 @@ class flat_tree {
// length).
//
// Assume that move constructors invalidate iterators and references.
+ //
+ // The constructors that take ranges, lists, and vectors do not require that
+ // the input be sorted.
flat_tree();
explicit flat_tree(const key_compare& comp);
- // Not stable in the presence of duplicates in the initializer list.
template <class InputIterator>
flat_tree(InputIterator first,
InputIterator last,
+ FlatContainerDupes dupe_handling,
const key_compare& comp = key_compare());
flat_tree(const flat_tree&);
flat_tree(flat_tree&&);
- // Not stable in the presence of duplicates in the initializer list.
+ flat_tree(std::vector<value_type> items,
+ FlatContainerDupes dupe_handling,
+ const key_compare& comp = key_compare());
+
flat_tree(std::initializer_list<value_type> ilist,
+ FlatContainerDupes dupe_handling,
const key_compare& comp = key_compare());
~flat_tree();
@@ -97,7 +134,7 @@ class flat_tree {
flat_tree& operator=(const flat_tree&);
flat_tree& operator=(flat_tree&&);
- // Not stable in the presence of duplicates in the initializer list.
+ // Takes the first if there are duplicates in the initializer list.
flat_tree& operator=(std::initializer_list<value_type> ilist);
// --------------------------------------------------------------------------
@@ -276,17 +313,26 @@ class flat_tree {
return std::next(begin(), distance);
}
- void sort_and_unique() {
- // std::set sorts elements preserving stability because it doesn't have any
- // performance wins in not doing that. We do, so we use an unstable sort.
- std::sort(begin(), end(), impl_.get_value_comp());
- erase(std::unique(begin(), end(),
- [this](const value_type& lhs, const value_type& rhs) {
- // lhs is already <= rhs due to sort, therefore
- // !(lhs < rhs) <=> lhs == rhs.
- return !impl_.get_value_comp()(lhs, rhs);
- }),
- end());
+ void sort_and_unique(FlatContainerDupes dupes) {
+ // Preserve stability for the unique code below.
+ std::stable_sort(begin(), end(), impl_.get_value_comp());
+
+ auto comparator = [this](const value_type& lhs, const value_type& rhs) {
+ // lhs is already <= rhs due to sort, therefore
+ // !(lhs < rhs) <=> lhs == rhs.
+ return !impl_.get_value_comp()(lhs, rhs);
+ };
+
+ iterator erase_after;
+ switch (dupes) {
+ case KEEP_FIRST_OF_DUPES:
+ erase_after = std::unique(begin(), end(), comparator);
+ break;
+ case KEEP_LAST_OF_DUPES:
+ erase_after = LastUnique(begin(), end(), comparator);
+ break;
+ }
+ erase(erase_after, end());
}
// To support comparators that may not be possible to default-construct, we
@@ -325,9 +371,10 @@ template <class InputIterator>
flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
InputIterator first,
InputIterator last,
+ FlatContainerDupes dupe_handling,
const KeyCompare& comp)
: impl_(comp, first, last) {
- sort_and_unique();
+ sort_and_unique(dupe_handling);
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
@@ -340,9 +387,19 @@ flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) =
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
+ std::vector<value_type> items,
+ FlatContainerDupes dupe_handling,
+ const KeyCompare& comp)
+ : impl_(comp, std::move(items)) {
+ sort_and_unique(dupe_handling);
+}
+
+template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(
std::initializer_list<value_type> ilist,
+ FlatContainerDupes dupe_handling,
const KeyCompare& comp)
- : flat_tree(std::begin(ilist), std::end(ilist), comp) {}
+ : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default;
@@ -362,7 +419,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();
+ sort_and_unique(KEEP_FIRST_OF_DUPES);
return *this;
}
« no previous file with comments | « base/containers/flat_set_unittest.cc ('k') | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698