| 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;
|
| }
|
|
|
|
|