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// size_type erase(K&& k);
14
15#include <compare>
16#include <concepts>
17#include <deque>
18#include <flat_map>
19#include <functional>
20#include <string>
21#include <utility>
22#include <vector>
23
24#include "MinSequenceContainer.h"
25#include "../helpers.h"
26#include "test_macros.h"
27#include "min_allocator.h"
28
29// Constraints: The qualified-id Compare::is_transparent is valid and denotes a type.
30template <class M>
31concept CanErase = requires(M m, Transparent<int> k) { m.erase(k); };
32using TransparentMap = std::flat_map<int, double, TransparentComparator>;
33using NonTransparentMap = std::flat_map<int, double, NonTransparentComparator>;
34static_assert(CanErase<TransparentMap>);
35static_assert(!CanErase<const TransparentMap>);
36static_assert(!CanErase<NonTransparentMap>);
37static_assert(!CanErase<const NonTransparentMap>);
38
39template <class Key, class It>
40struct HeterogeneousKey {
41 explicit HeterogeneousKey(Key key, It it) : key_(key), it_(it) {}
42 operator It() && { return it_; }
43 auto operator<=>(Key key) const { return key_ <=> key; }
44 friend bool operator<(const HeterogeneousKey&, const HeterogeneousKey&) {
45 assert(false);
46 return false;
47 }
48 Key key_;
49 It it_;
50};
51
52template <class KeyContainer, class ValueContainer>
53void test_simple() {
54 using Key = typename KeyContainer::value_type;
55 using Value = typename ValueContainer::value_type;
56 using M = std::flat_map<Key, Value, std::less<Key>, KeyContainer, ValueContainer>;
57
58 M m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}};
59 ASSERT_SAME_TYPE(decltype(m.erase(9)), typename M::size_type);
60 auto n = m.erase(3); // erase(K&&) [with K=int]
61 assert(n == 1);
62 assert((m == M{{1, 1}, {2, 2}, {4, 4}}));
63 typename M::key_type lvalue = 2;
64 n = m.erase(lvalue); // erase(K&&) [with K=int&]
65 assert(n == 1);
66 assert((m == M{{1, 1}, {4, 4}}));
67 const typename M::key_type const_lvalue = 1;
68 n = m.erase(const_lvalue); // erase(const key_type&)
69 assert(n == 1);
70 assert((m == M{{4, 4}}));
71}
72
73template <class KeyContainer, class ValueContainer>
74void test_transparent_comparator() {
75 using M = std::flat_map<std::string, int, TransparentComparator, KeyContainer, ValueContainer>;
76 M m = {{"alpha", 1}, {"beta", 2}, {"epsilon", 3}, {"eta", 4}, {"gamma", 5}};
77 ASSERT_SAME_TYPE(decltype(m.erase(Transparent<std::string>{"abc"})), typename M::size_type);
78
79 auto n = m.erase(Transparent<std::string>{.t: "epsilon"});
80 assert(n == 1);
81
82 M expected = {{"alpha", 1}, {"beta", 2}, {"eta", 4}, {"gamma", 5}};
83 assert(m == expected);
84
85 auto n2 = m.erase(Transparent<std::string>{.t: "aaa"});
86 assert(n2 == 0);
87 assert(m == expected);
88}
89
90int main(int, char**) {
91 test_simple<std::vector<int>, std::vector<double>>();
92 test_simple<std::deque<int>, std::vector<double>>();
93 test_simple<MinSequenceContainer<int>, MinSequenceContainer<double>>();
94 test_simple<std::vector<int, min_allocator<int>>, std::vector<double, min_allocator<double>>>();
95
96 test_transparent_comparator<std::vector<std::string>, std::vector<int>>();
97 test_transparent_comparator<std::deque<std::string>, std::vector<int>>();
98 test_transparent_comparator<MinSequenceContainer<std::string>, MinSequenceContainer<int>>();
99 test_transparent_comparator<std::vector<std::string, min_allocator<std::string>>,
100 std::vector<int, min_allocator<int>>>();
101
102 {
103 // P2077's HeterogeneousKey example
104 using M = std::flat_map<int, int, std::less<>>;
105 M m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7}, {8, 8}};
106 auto h1 = HeterogeneousKey<int, M::iterator>(8, m.begin());
107 std::same_as<M::size_type> auto n = m.erase(h1); // lvalue is not convertible to It; erase(K&&) is the best match
108 assert(n == 1);
109 assert((m == M{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7}}));
110 std::same_as<M::iterator> auto it = m.erase(std::move(h1)); // rvalue is convertible to It; erase(K&&) drops out
111 assert(it == m.begin());
112 assert((m == M{{2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7}}));
113 }
114 {
115 using M = std::flat_map<int, int, std::less<>>;
116 M m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7}, {8, 8}};
117 auto h1 = HeterogeneousKey<int, M::const_iterator>(8, m.begin());
118 std::same_as<M::size_type> auto n = m.erase(h1); // lvalue is not convertible to It; erase(K&&) is the best match
119 assert(n == 1);
120 assert((m == M{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7}}));
121 std::same_as<M::iterator> auto it = m.erase(std::move(h1)); // rvalue is convertible to It; erase(K&&) drops out
122 assert(it == m.begin());
123 assert((m == M{{2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {7, 7}}));
124 }
125 {
126 bool transparent_used = false;
127 TransparentComparator c(transparent_used);
128 std::flat_map<int, int, TransparentComparator> m(std::sorted_unique, {{1, 1}, {2, 2}, {3, 3}}, c);
129 assert(!transparent_used);
130 auto n = m.erase(Transparent<int>{3});
131 assert(n == 1);
132 assert(transparent_used);
133 }
134 {
135 auto erase_transparent = [](auto& m, auto key_arg) {
136 using Map = std::decay_t<decltype(m)>;
137 using Key = typename Map::key_type;
138 m.erase(Transparent<Key>{key_arg});
139 };
140 test_erase_exception_guarantee(erase_function&: erase_transparent);
141 }
142 {
143 // LWG4239 std::string and C string literal
144 using M = std::flat_map<std::string, int, std::less<>>;
145 M m{{"alpha", 1}, {"beta", 2}, {"epsilon", 1}, {"eta", 3}, {"gamma", 3}};
146 auto n = m.erase("beta");
147 assert(n == 1);
148 }
149
150 return 0;
151}
152

source code of libcxx/test/std/containers/container.adaptors/flat.map/flat.map.modifiers/erase_key_transparent.pass.cpp