Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions stl/inc/flat_set
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,9 @@ public:
}

_NODISCARD container_type extract() && {
// The container NEEDS to be cleared no matter what,
// which is not guaranteed by simply moving it away
// ("... valid but unspecified ...")
container_type& _Cont = _Get_cont();
_Clear_scope_guard _Guard{this};
// always clears the container (N4950 [flat.set.modifiers]/14 and [flat.multiset.modifiers]/10)
_Clear_scope_guard<_Base_flat_set> _Guard{this};
container_type _Temp = _STD move(_Cont);
return _Temp;
}
Expand Down Expand Up @@ -405,7 +403,7 @@ public:
}

private:
void inline _Assert_after_sorted_input() const {
void _Assert_after_sorted_input() const {
_STL_ASSERT(_STD is_sorted(begin(), end(), _Get_comp()), "Input was not sorted!");
if constexpr (!_Multi) {
_STL_ASSERT(_Is_unique(), "Input was not unique!");
Expand Down Expand Up @@ -624,15 +622,21 @@ public:
};

_EXPORT_STD template <class _Kty, class _Keylt, class _Container, class _Pred>
size_t erase_if(flat_set<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) {
_Clear_scope_guard _Guard{&_Val};
return _Erase_remove_if(_Val, _Pass_fn(_Predicate));
_Container::size_type erase_if(flat_set<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) {
// clears the container to maintain the invariants when an exception is thrown (N4950 [flat.set.erasure]/5)
_Clear_scope_guard<flat_set<_Kty, _Keylt, _Container>> _Guard{_STD addressof(_Val)};
const auto _Erased_count = _Erase_remove_if(_Val, _Pass_fn(_Predicate));
_Guard._Clearable = nullptr;
return _Erased_count;
}

_EXPORT_STD template <class _Kty, class _Keylt, class _Container, class _Pred>
size_t erase_if(flat_multiset<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) {
_Clear_scope_guard _Guard{&_Val};
return _Erase_remove_if(_Val, _Pass_fn(_Predicate));
_Container::size_type erase_if(flat_multiset<_Kty, _Keylt, _Container>& _Val, _Pred _Predicate) {
// clears the container to maintain the invariants when an exception is thrown (N4950 [flat.multiset.erasure]/5)
_Clear_scope_guard<flat_multiset<_Kty, _Keylt, _Container>> _Guard{_STD addressof(_Val)};
const auto _Erased_count = _Erase_remove_if(_Val, _Pass_fn(_Predicate));
_Guard._Clearable = nullptr;
return _Erased_count;
}

template <class _Kty, class _Keylt, class _Container, class _Alloc>
Expand Down
25 changes: 25 additions & 0 deletions tests/std/tests/P1222R4_flat_set/test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
#include <cassert>
#include <deque>
#include <flat_set>
Expand Down Expand Up @@ -190,6 +191,24 @@ void test_non_static_comparer() {
assert_all_requirements_and_equals(a, {9, 7, 5, -1});
}

template <class C>
void test_extract() {
constexpr int elements[]{1, 2, 3, 4};
C fs{1, 2, 3, 4};
auto cont = std::move(fs).extract();
assert(fs.empty());
assert(ranges::equal(cont, elements));
}

template <class C>
void test_erase_if() {
constexpr int erased_result[]{1, 3};
C fs{1, 2, 3, 4};
erase_if(fs, [](int n) { return n % 2 == 0; });
assert(fs.size() == 2);
assert(ranges::equal(fs, erased_result));
}

int main() {
test_spaceship_operator<flat_set<int>>();
test_spaceship_operator<flat_multiset<int>>();
Expand All @@ -205,6 +224,12 @@ int main() {

test_non_static_comparer();

test_extract<flat_set<int>>();
test_extract<flat_multiset<int>>();

test_erase_if<flat_set<int>>();
test_erase_if<flat_multiset<int>>();

assert_basic<flat_set<int>>();
assert_basic<flat_set<int, std::less<int>, deque<int>>>();

Expand Down