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 | // template<container-compatible-range<value_type> R> |
14 | // flat_multimap(from_range_t, R&&) |
15 | // template<container-compatible-range<value_type> R> |
16 | // flat_multimap(from_range_t, R&&, const key_compare&) |
17 | // template<container-compatible-range<value_type> R, class Alloc> |
18 | // flat_multimap(from_range_t, R&&, const Alloc&); |
19 | // template<container-compatible-range<value_type> R, class Alloc> |
20 | // flat_multimap(from_range_t, R&&, const key_compare&, const Alloc&); |
21 | |
22 | #include <algorithm> |
23 | #include <deque> |
24 | #include <flat_map> |
25 | #include <functional> |
26 | #include <string> |
27 | #include <vector> |
28 | |
29 | #include "min_allocator.h" |
30 | #include "test_allocator.h" |
31 | #include "test_iterators.h" |
32 | #include "test_macros.h" |
33 | #include "../../../test_compare.h" |
34 | |
35 | // test constraint container-compatible-range |
36 | |
37 | template <class V> |
38 | using RangeOf = std::ranges::subrange<V*>; |
39 | using Map = std::flat_multimap<int, double>; |
40 | |
41 | static_assert(std::is_constructible_v<Map, std::from_range_t, RangeOf<std::pair<int, double>>>); |
42 | static_assert(std::is_constructible_v<Map, std::from_range_t, RangeOf<std::pair<short, double>>>); |
43 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<int>>); |
44 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<double>>); |
45 | |
46 | static_assert(std::is_constructible_v<Map, std::from_range_t, RangeOf<std::pair<int, double>>, std::less<int>>); |
47 | static_assert(std::is_constructible_v<Map, std::from_range_t, RangeOf<std::pair<short, double>>, std::less<int>>); |
48 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<int>, std::less<int>>); |
49 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<double>, std::less<int>>); |
50 | |
51 | static_assert(std::is_constructible_v<Map, std::from_range_t, RangeOf<std::pair<int, double>>, std::allocator<int>>); |
52 | static_assert(std::is_constructible_v<Map, std::from_range_t, RangeOf<std::pair<short, double>>, std::allocator<int>>); |
53 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<int>, std::allocator<int>>); |
54 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<double>, std::allocator<int>>); |
55 | |
56 | static_assert(std::is_constructible_v<Map, |
57 | std::from_range_t, |
58 | RangeOf<std::pair<int, double>>, |
59 | std::less<int>, |
60 | std::allocator<int>>); |
61 | static_assert(std::is_constructible_v<Map, |
62 | std::from_range_t, |
63 | RangeOf<std::pair<short, double>>, |
64 | std::less<int>, |
65 | std::allocator<int>>); |
66 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<int>, std::less<int>, std::allocator<int>>); |
67 | static_assert(!std::is_constructible_v<Map, std::from_range_t, RangeOf<double>, std::less<int>, std::allocator<int>>); |
68 | |
69 | int main(int, char**) { |
70 | { |
71 | // The constructors in this subclause shall not participate in overload |
72 | // resolution unless uses_allocator_v<key_container_type, Alloc> is true |
73 | // and uses_allocator_v<mapped_container_type, Alloc> is true. |
74 | |
75 | using C = test_less<int>; |
76 | using A1 = test_allocator<int>; |
77 | using A2 = other_allocator<int>; |
78 | using V1 = std::vector<int, A1>; |
79 | using V2 = std::vector<int, A2>; |
80 | using M1 = std::flat_multimap<int, int, C, V1, V1>; |
81 | using M2 = std::flat_multimap<int, int, C, V1, V2>; |
82 | using M3 = std::flat_multimap<int, int, C, V2, V1>; |
83 | static_assert(std::is_constructible_v<M1, std::from_range_t, M1, const A1&>); |
84 | static_assert(!std::is_constructible_v<M1, std::from_range_t, M1, const A2&>); |
85 | static_assert(!std::is_constructible_v<M2, std::from_range_t, M2, const A2&>); |
86 | static_assert(!std::is_constructible_v<M3, std::from_range_t, M3, const A2&>); |
87 | |
88 | static_assert(std::is_constructible_v<M1, std::from_range_t, M1, const C&, const A1&>); |
89 | static_assert(!std::is_constructible_v<M1, std::from_range_t, M1, const C&, const A2&>); |
90 | static_assert(!std::is_constructible_v<M2, std::from_range_t, M2, const C&, const A2&>); |
91 | static_assert(!std::is_constructible_v<M3, std::from_range_t, M3, const C&, const A2&>); |
92 | } |
93 | { |
94 | // container-compatible-range |
95 | using C = test_less<int>; |
96 | using A1 = test_allocator<int>; |
97 | using A2 = test_allocator<std::string>; |
98 | using M = std::flat_multimap<int, std::string, C, std::vector<int, A1>, std::vector<std::string, A2>>; |
99 | using Pair = std::pair<int, std::string>; |
100 | using PairLike = std::tuple<int, std::string>; |
101 | using NonPairLike = int; |
102 | |
103 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<Pair>&>); |
104 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<PairLike>&>); |
105 | static_assert(!std::is_constructible_v<M, std::from_range_t, std::vector<NonPairLike>&>); |
106 | |
107 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<Pair>&, const C&>); |
108 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<PairLike>&, const C&>); |
109 | static_assert(!std::is_constructible_v<M, std::from_range_t, std::vector<NonPairLike>&, const C&>); |
110 | |
111 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<Pair>&, const A1&>); |
112 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<PairLike>&, const A1&>); |
113 | static_assert(!std::is_constructible_v<M, std::from_range_t, std::vector<NonPairLike>&, const A1&>); |
114 | |
115 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<Pair>&, const C&, const A1&>); |
116 | static_assert(std::is_constructible_v<M, std::from_range_t, std::vector<PairLike>&, const C&, const A1&>); |
117 | static_assert(!std::is_constructible_v<M, std::from_range_t, std::vector<NonPairLike>&, const C&, const A1&>); |
118 | } |
119 | |
120 | using P = std::pair<int, short>; |
121 | P ar[] = {{1, 1}, {1, 2}, {1, 3}, {2, 4}, {2, 5}, {3, 6}, {2, 7}, {3, 8}, {3, 9}}; |
122 | P expected[] = {{1, 1}, {1, 2}, {1, 3}, {2, 4}, {2, 5}, {2, 7}, {3, 6}, {3, 8}, {3, 9}}; |
123 | { |
124 | // flat_multimap(from_range_t, R&&) |
125 | // input_range && !common |
126 | using M = std::flat_multimap<int, short>; |
127 | using Iter = cpp20_input_iterator<const P*>; |
128 | using Sent = sentinel_wrapper<Iter>; |
129 | using R = std::ranges::subrange<Iter, Sent>; |
130 | auto m = M(std::from_range, R(Iter(ar), Sent(Iter(ar + 9)))); |
131 | assert(std::ranges::equal(m.keys(), expected | std::views::elements<0>)); |
132 | LIBCPP_ASSERT(std::ranges::equal(m, expected)); |
133 | |
134 | // explicit(false) |
135 | M m2 = {std::from_range, R(Iter(ar), Sent(Iter(ar + 9)))}; |
136 | assert(m2 == m); |
137 | } |
138 | { |
139 | // flat_multimap(from_range_t, R&&) |
140 | // greater |
141 | using M = std::flat_multimap<int, short, std::greater<int>, std::deque<int, min_allocator<int>>, std::deque<short>>; |
142 | using Iter = cpp20_input_iterator<const P*>; |
143 | using Sent = sentinel_wrapper<Iter>; |
144 | using R = std::ranges::subrange<Iter, Sent>; |
145 | auto m = M(std::from_range, R(Iter(ar), Sent(Iter(ar + 9)))); |
146 | assert((m.keys() == std::deque<int, min_allocator<int>>{3, 3, 3, 2, 2, 2, 1, 1, 1})); |
147 | LIBCPP_ASSERT((m.values() == std::deque<short>{6, 8, 9, 4, 5, 7, 1, 2, 3})); |
148 | } |
149 | { |
150 | // flat_multimap(from_range_t, R&&) |
151 | // contiguous range |
152 | using M = std::flat_multimap<int, short>; |
153 | using R = std::ranges::subrange<const P*>; |
154 | auto m = M(std::from_range, R(ar, ar + 9)); |
155 | assert(std::ranges::equal(m.keys(), expected | std::views::elements<0>)); |
156 | LIBCPP_ASSERT(std::ranges::equal(m, expected)); |
157 | } |
158 | { |
159 | // flat_multimap(from_range_t, R&&, const key_compare&) |
160 | using C = test_less<int>; |
161 | using M = std::flat_multimap<int, short, C, std::vector<int>, std::deque<short>>; |
162 | using R = std::ranges::subrange<const P*>; |
163 | auto m = M(std::from_range, R(ar, ar + 9), C(3)); |
164 | assert(std::ranges::equal(m.keys(), expected | std::views::elements<0>)); |
165 | LIBCPP_ASSERT(std::ranges::equal(m, expected)); |
166 | assert(m.key_comp() == C(3)); |
167 | |
168 | // explicit(false) |
169 | M m2 = {std::from_range, R(ar, ar + 9), C(3)}; |
170 | assert(m2 == m); |
171 | assert(m2.key_comp() == C(3)); |
172 | } |
173 | { |
174 | // flat_multimap(from_range_t, R&&, const Allocator&) |
175 | using A1 = test_allocator<int>; |
176 | using A2 = test_allocator<short>; |
177 | using M = std::flat_multimap<int, short, std::less<int>, std::vector<int, A1>, std::deque<short, A2>>; |
178 | using R = std::ranges::subrange<const P*>; |
179 | auto m = M(std::from_range, R(ar, ar + 9), A1(5)); |
180 | assert(std::ranges::equal(m.keys(), expected | std::views::elements<0>)); |
181 | LIBCPP_ASSERT(std::ranges::equal(m, expected)); |
182 | assert(m.keys().get_allocator() == A1(5)); |
183 | assert(m.values().get_allocator() == A2(5)); |
184 | } |
185 | { |
186 | // flat_multimap(from_range_t, R&&, const Allocator&) |
187 | // explicit(false) |
188 | using A1 = test_allocator<int>; |
189 | using A2 = test_allocator<short>; |
190 | using M = std::flat_multimap<int, short, std::less<int>, std::vector<int, A1>, std::deque<short, A2>>; |
191 | using R = std::ranges::subrange<const P*>; |
192 | M m = {std::from_range, R(ar, ar + 9), A1(5)}; // implicit ctor |
193 | assert(std::ranges::equal(m.keys(), expected | std::views::elements<0>)); |
194 | LIBCPP_ASSERT(std::ranges::equal(m, expected)); |
195 | assert(m.keys().get_allocator() == A1(5)); |
196 | assert(m.values().get_allocator() == A2(5)); |
197 | } |
198 | { |
199 | // flat_multimap(from_range_t, R&&, const key_compare&, const Allocator&) |
200 | using C = test_less<int>; |
201 | using A1 = test_allocator<int>; |
202 | using A2 = test_allocator<short>; |
203 | using M = std::flat_multimap<int, short, C, std::vector<int, A1>, std::deque<short, A2>>; |
204 | using R = std::ranges::subrange<const P*>; |
205 | auto m = M(std::from_range, R(ar, ar + 9), C(3), A1(5)); |
206 | assert(std::ranges::equal(m.keys(), expected | std::views::elements<0>)); |
207 | LIBCPP_ASSERT(std::ranges::equal(m, expected)); |
208 | assert(m.key_comp() == C(3)); |
209 | assert(m.keys().get_allocator() == A1(5)); |
210 | assert(m.values().get_allocator() == A2(5)); |
211 | } |
212 | { |
213 | // flat_multimap(from_range_t, R&&, const key_compare&, const Allocator&) |
214 | // explicit(false) |
215 | using A1 = test_allocator<int>; |
216 | using A2 = test_allocator<short>; |
217 | using M = std::flat_multimap<int, short, std::less<int>, std::deque<int, A1>, std::vector<short, A2>>; |
218 | using R = std::ranges::subrange<const P*>; |
219 | M m = {std::from_range, R(ar, ar + 9), {}, A2(5)}; // implicit ctor |
220 | assert(std::ranges::equal(m.keys(), expected | std::views::elements<0>)); |
221 | LIBCPP_ASSERT(std::ranges::equal(m, expected)); |
222 | assert(m.keys().get_allocator() == A1(5)); |
223 | assert(m.values().get_allocator() == A2(5)); |
224 | } |
225 | |
226 | return 0; |
227 | } |
228 | |