Commit b8d837fc authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Add sorted_unique ctor to sorted_vector_set and sorted_vector_map

Summary: [Folly] Add `sorted_unique` ctor to `sorted_vector_set` and `sorted_vector_map`. The `presorted` ctors are used with presorted but not necessarily unique inputs, so uniquify the inputs in that ctors. The untagged ctors which take a backing container presort but do not uniquify the backing container, so switch to presorting and uniquifying.

Reviewed By: vitaut

Differential Revision: D15215677

fbshipit-source-id: bf920103cfb6c297c186e5389701c08218dbc4b9
parent 85fd07e2
......@@ -195,11 +195,43 @@ void bulk_insert(
cont.end());
}
template <typename Container, typename Compare>
bool is_sorted_unique(Container const& container, Compare const& comp) {
if (container.empty()) {
return true;
}
auto const e = container.end();
for (auto a = container.begin(), b = std::next(a); b != e; ++a, ++b) {
if (!comp(*a, *b)) {
return false;
}
}
return true;
}
template <typename Container, typename Compare>
Container&& as_sorted(Container&& container, Compare const& comp) {
std::sort(container.begin(), container.end(), comp);
return static_cast<Container&&>(container);
}
template <typename Container, typename Compare>
Container&& as_unique(Container&& container, Compare const& comp) {
container.erase(
std::unique(
container.begin(),
container.end(),
[&](auto const& a, auto const& b) {
return !comp(a, b) && !comp(b, a);
}),
container.end());
return static_cast<Container&&>(container);
}
template <typename Container, typename Compare>
Container&& as_sorted_unique(Container&& container, Compare const& comp) {
return as_unique(as_sorted(static_cast<Container&&>(container), comp), comp);
}
} // namespace detail
//////////////////////////////////////////////////////////////////////
......@@ -295,28 +327,37 @@ class sorted_vector_set : detail::growth_policy_wrapper<GrowthPolicy> {
Container&& container,
const Compare& comp = Compare())
: sorted_vector_set(
presorted,
detail::as_sorted(std::move(container), comp),
sorted_unique,
detail::as_sorted_unique(std::move(container), comp),
comp) {}
// Construct a sorted_vector_set by stealing the storage of a prefilled
// container. The container must be sorted, as presorted_t hints. Supports
// bulk construction of sorted_vector_set with zero allocations, not counting
// those performed by the caller. (The iterator range constructor performs at
// least one allocation).
// container. Its elements must be sorted and unique, as sorted_unique_t
// hints. Supports bulk construction of sorted_vector_set with zero
// allocations, not counting those performed by the caller. (The iterator
// range constructor performs at least one allocation).
//
// Note that `sorted_vector_set(presorted_t, const Container& container)` is
// not provided, since the purpose of this constructor is to avoid an extra
// Note that `sorted_vector_set(sorted_unique_t, const Container& container)`
// is not provided, since the purpose of this constructor is to avoid an extra
// copy.
sorted_vector_set(
presorted_t,
sorted_unique_t,
Container&& container,
const Compare& comp = Compare())
: m_(comp, container.get_allocator()) {
assert(std::is_sorted(container.begin(), container.end(), value_comp()));
assert(detail::is_sorted_unique(container, value_comp()));
m_.cont_.swap(container);
}
sorted_vector_set(
presorted_t,
Container&& container,
const Compare& comp = Compare())
: sorted_vector_set(
sorted_unique,
detail::as_unique(std::move(container), value_compare(comp)),
comp) {}
sorted_vector_set& operator=(std::initializer_list<value_type> ilist) {
clear();
insert(ilist.begin(), ilist.end());
......@@ -708,28 +749,38 @@ class sorted_vector_map : detail::growth_policy_wrapper<GrowthPolicy> {
Container&& container,
const Compare& comp = Compare())
: sorted_vector_map(
presorted,
detail::as_sorted(std::move(container), value_compare(comp)),
sorted_unique,
detail::as_sorted_unique(std::move(container), value_compare(comp)),
comp) {}
// Construct a sorted_vector_map by stealing the storage of a prefilled
// container. The container must be sorted, as presorted_t hints. S supports
// bulk construction of sorted_vector_map with zero allocations, not counting
// those performed by the caller. (The iterator range constructor performs at
// least one allocation).
// container. Its elements must be sorted and unique, as sorted_unique_t
// hints. Supports bulk construction of sorted_vector_map with zero
// allocations, not counting those performed by the caller. (The iterator
// range constructor performs at least one allocation).
//
// Note that `sorted_vector_map(presorted_t, const Container& container)` is
// not provided, since the purpose of this constructor is to avoid an extra
// Note that `sorted_vector_map(sorted_unique_t, const Container& container)`
// is not provided, since the purpose of this constructor is to avoid an extra
// copy.
sorted_vector_map(
presorted_t,
sorted_unique_t,
Container&& container,
const Compare& comp = Compare())
: m_(value_compare(comp), container.get_allocator()) {
assert(std::is_sorted(container.begin(), container.end(), value_comp()));
assert(detail::is_sorted_unique(container, value_comp()));
m_.cont_.swap(container);
}
sorted_vector_map(
presorted_t,
Container&& container,
const Compare& comp = Compare())
: sorted_vector_map(
sorted_unique,
detail::as_unique(std::move(container), value_compare(comp)),
comp) {}
sorted_vector_map& operator=(std::initializer_list<value_type> ilist) {
clear();
insert(ilist.begin(), ilist.end());
......
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