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_map>
12
13// class flat_multimap
14
15// containers extract() &&;
16
17#include <algorithm>
18#include <concepts>
19#include <deque>
20#include <flat_map>
21#include <functional>
22#include <vector>
23
24#include "MinSequenceContainer.h"
25#include "../helpers.h"
26#include "test_macros.h"
27#include "min_allocator.h"
28
29template <class T>
30concept CanExtract = requires(T&& t) { std::forward<T>(t).extract(); };
31
32static_assert(CanExtract<std::flat_multimap<int, int>&&>);
33static_assert(!CanExtract<std::flat_multimap<int, int>&>);
34static_assert(!CanExtract<std::flat_multimap<int, int> const&>);
35static_assert(!CanExtract<std::flat_multimap<int, int> const&&>);
36
37template <class KeyContainer, class ValueContainer>
38void test() {
39 using M = std::flat_multimap<int, int, std::less<int>, KeyContainer, ValueContainer>;
40 M m = M({1, 2, 2, 2, 3, 3}, {4, 5, 6, 7, 8, 9});
41
42 std::same_as<typename M::containers> auto containers = std::move(m).extract();
43
44 auto expected_keys = {1, 2, 2, 2, 3, 3};
45 auto expected_values = {4, 5, 6, 7, 8, 9};
46 assert(std::ranges::equal(containers.keys, expected_keys));
47 assert(std::ranges::equal(containers.values, expected_values));
48 check_invariant(m);
49 LIBCPP_ASSERT(m.empty());
50 LIBCPP_ASSERT(m.keys().size() == 0);
51 LIBCPP_ASSERT(m.values().size() == 0);
52}
53
54int main(int, char**) {
55 test<std::vector<int>, std::vector<int>>();
56 test<std::deque<int>, std::vector<int>>();
57 test<MinSequenceContainer<int>, MinSequenceContainer<int>>();
58 test<std::vector<int, min_allocator<int>>, std::vector<int, min_allocator<int>>>();
59 {
60 // extracted object maintains invariant if one of underlying container does not clear after move
61 using M = std::flat_multimap<int, int, std::less<>, std::vector<int>, CopyOnlyVector<int>>;
62 M m = M({1, 2, 2, 2, 3, 3}, {1, 2, 3, 4, 5, 6});
63 std::same_as<M::containers> auto containers = std::move(m).extract();
64 assert(containers.keys.size() == 6);
65 assert(containers.values.size() == 6);
66 check_invariant(m);
67 LIBCPP_ASSERT(m.empty());
68 LIBCPP_ASSERT(m.keys().size() == 0);
69 LIBCPP_ASSERT(m.values().size() == 0);
70 }
71
72 {
73#ifndef TEST_HAS_NO_EXCEPTIONS
74 using KeyContainer = std::vector<int>;
75 using ValueContainer = ThrowOnMoveContainer<int>;
76 using M = std::flat_multimap<int, int, std::ranges::less, KeyContainer, ValueContainer>;
77
78 M m;
79 m.emplace(1, 1);
80 m.emplace(1, 1);
81 try {
82 auto c = std::move(m).extract();
83 assert(false);
84 } catch (int) {
85 check_invariant(m);
86 // In libc++, we try to erase the key after value emplacement failure.
87 // and after erasure failure, we clear the flat_multimap
88 LIBCPP_ASSERT(m.size() == 0);
89 }
90#endif
91 }
92 return 0;
93}
94

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