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// containers 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_set<int>&&>);
31static_assert(!CanExtract<std::flat_set<int>&>);
32static_assert(!CanExtract<std::flat_set<int> const&>);
33static_assert(!CanExtract<std::flat_set<int> const&&>);
34
35template <class KeyContainer>
36constexpr void test_one() {
37 using M = std::flat_set<int, std::less<int>, KeyContainer>;
38 {
39 M m = M({1, 2, 3});
40
41 std::same_as<KeyContainer> auto keys = std::move(m).extract();
42
43 auto expected_keys = {1, 2, 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
58constexpr bool test() {
59 test_one<std::vector<int>>();
60#ifndef __cpp_lib_constexpr_deque
61 if (!TEST_IS_CONSTANT_EVALUATED)
62#endif
63 test_one<std::deque<int>>();
64 test_one<MinSequenceContainer<int>>();
65 test_one<std::vector<int, min_allocator<int>>>();
66
67 {
68 // extracted object maintains invariant if the underlying container does not clear after move
69 using M = std::flat_set<int, std::less<>, CopyOnlyVector<int>>;
70 M m = M({1, 2, 3});
71 std::same_as<M::container_type> auto keys = std::move(m).extract();
72 assert(keys.size() == 3);
73 check_invariant(m);
74 LIBCPP_ASSERT(m.empty());
75 }
76
77 return true;
78}
79
80void test_exception() {
81 {
82#ifndef TEST_HAS_NO_EXCEPTIONS
83 using KeyContainer = ThrowOnMoveContainer<int>;
84 using M = std::flat_set<int, std::ranges::less, KeyContainer>;
85
86 M m;
87 m.emplace(1);
88 m.emplace(2);
89 try {
90 auto c = std::move(m).extract();
91 assert(false);
92 } catch (int) {
93 check_invariant(m);
94 // In libc++, we try to erase the key after value emplacement failure.
95 // and after erasure failure, we clear the flat_set
96 LIBCPP_ASSERT(m.size() == 0);
97 }
98#endif
99 }
100}
101
102int main(int, char**) {
103 test();
104 test_exception();
105#if TEST_STD_VER >= 26
106 static_assert(test());
107#endif
108
109 return 0;
110}
111

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