Commit 68335744 authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Commit Bot

[base] Add extract() and replace() to flat_tree

This change adds an extract() and replace() API to base::flat_tree which
are inspired by the equivalently named API mentioned in the
standardization proposal of std::flat_map and std::flat_set.

References:
- https://wg21.link/p0429
- https://wg21.link/p1222

Bug: 682254
Change-Id: If517376aa7a682064d55882a0eecf4ff1ce89eef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2091352Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#747762}
parent 9d475ac5
......@@ -116,6 +116,10 @@ struct GetKeyFromValuePairFirst {
// iterator emplace_hint(const_iterator, Args&&...);
// pair<iterator, bool> try_emplace(K&&, Args&&...);
// iterator try_emplace(const_iterator hint, K&&, Args&&...);
// Underlying type functions:
// underlying_type extract() &&;
// void replace(underlying_type&&);
//
// Erase functions:
// iterator erase(iterator);
......
......@@ -95,6 +95,10 @@ namespace base {
// pair<iterator, bool> emplace(Args&&...);
// iterator emplace_hint(const_iterator, Args&&...);
//
// Underlying type functions:
// underlying_type extract() &&;
// void replace(underlying_type&&);
//
// Erase functions:
// iterator erase(iterator);
// iterator erase(const_iterator);
......
......@@ -8,6 +8,7 @@
#include <algorithm>
#include <iterator>
#include <type_traits>
#include <utility>
#include <vector>
#include "base/stl_util.h"
......@@ -198,6 +199,19 @@ class flat_tree {
template <class... Args>
iterator emplace_hint(const_iterator position_hint, Args&&... args);
// --------------------------------------------------------------------------
// Underlying type operations.
//
// Assume that either operation invalidates iterators and references.
// Extracts the underlying_type and returns it to the caller. Ensures that
// `this` is `empty()` afterwards.
underlying_type extract() &&;
// Replaces the underlying_type with `body`. Expects that `body` is sorted
// and has no repeated elements with regard to value_comp().
void replace(underlying_type&& body);
// --------------------------------------------------------------------------
// Erase operations.
//
......@@ -723,6 +737,27 @@ auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint(
return insert(position_hint, value_type(std::forward<Args>(args)...));
}
// ----------------------------------------------------------------------------
// Underlying type operations.
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::
extract() && -> underlying_type {
return std::exchange(impl_.body_, underlying_type());
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::replace(
underlying_type&& body) {
// Ensure that |body| is sorted and has no repeated elements.
DCHECK(std::is_sorted(body.begin(), body.end(), value_comp()));
DCHECK(std::adjacent_find(body.begin(), body.end(),
[this](const auto& lhs, const auto& rhs) {
return !value_comp()(lhs, rhs);
}) == body.end());
impl_.body_ = std::move(body);
}
// ----------------------------------------------------------------------------
// Erase operations.
......
......@@ -171,6 +171,7 @@ using TreeWithStrangeCompare = flat_tree<int,
NonDefaultConstructibleCompare>;
using ::testing::ElementsAre;
using ::testing::IsEmpty;
} // namespace
......@@ -814,6 +815,31 @@ TEST(FlatTree, EmplacePosition) {
}
}
// ----------------------------------------------------------------------------
// Underlying type operations.
// underlying_type extract() &&
TEST(FlatTree, Extract) {
IntTree cont;
cont.emplace(3);
cont.emplace(1);
cont.emplace(2);
cont.emplace(4);
std::vector<int> body = std::move(cont).extract();
EXPECT_THAT(cont, IsEmpty());
EXPECT_THAT(body, ElementsAre(1, 2, 3, 4));
}
// replace(underlying_type&&)
TEST(FlatTree, Replace) {
std::vector<int> body = {1, 2, 3, 4};
IntTree cont;
cont.replace(std::move(body));
EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4));
}
// ----------------------------------------------------------------------------
// Erase operations.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment