1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10
11// <flat_set>
12
13// container_type extract() &&;
14
15#include <algorithm>
16#include <concepts>
17#include <deque>
18#include <flat_set>
19#include <functional>
20#include <vector>
21
22#include "MinSequenceContainer.h"
23#include "../helpers.h"
24#include "test_macros.h"
25#include "min_allocator.h"
26
27template <class T>
28concept CanExtract = requires(T&& t) { std::forward<T>(t).extract(); };
29
30static_assert(CanExtract<std::flat_multiset<int>&&>);
31static_assert(!CanExtract<std::flat_multiset<int>&>);
32static_assert(!CanExtract<std::flat_multiset<int> const&>);
33static_assert(!CanExtract<std::flat_multiset<int> const&&>);
34
35template <class KeyContainer>
36void test_one() {
37 using M = std::flat_multiset<int, std::less<int>, KeyContainer>;
38 {
39 M m = M({1, 1, 3});
40
41 std::same_as<KeyContainer> auto keys = std::move(m).extract();
42
43 auto expected_keys = {1, 1, 3};
44 assert(std::ranges::equal(keys, expected_keys));
45 check_invariant(m);
46 LIBCPP_ASSERT(m.empty());
47 }
48 {
49 // was empty
50 M m;
51 assert(m.empty());
52 auto keys = std::move(m).extract();
53 assert(keys.empty());
54 LIBCPP_ASSERT(m.empty());
55 }
56}
57
58void test() {
59 test_one<std::vector<int>>();
60 test_one<std::deque<int>>();
61 test_one<MinSequenceContainer<int>>();
62 test_one<std::vector<int, min_allocator<int>>>();
63
64 {
65 // extracted object maintains invariant if the underlying container does not clear after move
66 using M = std::flat_multiset<int, std::less<>, CopyOnlyVector<int>>;
67 M m = M({1, 1, 3});
68 std::same_as<M::container_type> auto keys = std::move(m).extract();
69 assert(keys.size() == 3);
70 check_invariant(m);
71 LIBCPP_ASSERT(m.empty());
72 }
73}
74
75void test_exception() {
76 {
77#ifndef TEST_HAS_NO_EXCEPTIONS
78 using KeyContainer = ThrowOnMoveContainer<int>;
79 using M = std::flat_multiset<int, std::ranges::less, KeyContainer>;
80
81 M m;
82 m.emplace(1);
83 m.emplace(2);
84 try {
85 auto c = std::move(m).extract();
86 assert(false);
87 } catch (int) {
88 check_invariant(m);
89 // In libc++, we try to erase the key after value emplacement failure.
90 // and after erasure failure, we clear the flat_multiset
91 LIBCPP_ASSERT(m.size() == 0);
92 }
93#endif
94 }
95}
96
97int main(int, char**) {
98 test();
99 test_exception();
100
101 return 0;
102}
103

source code of libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/extract.pass.cpp