kblib 0.2.3
General utilities library for modern C++
direct_map.cpp
Go to the documentation of this file.
1#include "catch.hpp"
2
3#include <kblib/direct_map.h>
4
5// these tests assume char min != 0
6static_assert(std::is_signed_v<char>);
7
8TEST_CASE("direct_map") {
10 REQUIRE(map.begin() == map.end());
11 REQUIRE((map.size()) == 0); // extra parens to silence a warning
12 REQUIRE(map.empty());
13 REQUIRE_FALSE(map.contains('a'));
14 map['a'] = "42";
15 REQUIRE(map.contains('a'));
16 REQUIRE_FALSE(map.contains('b'));
17 REQUIRE(map.find('a') == map.begin());
18 REQUIRE_FALSE(map.begin() == map.end());
19 REQUIRE(map.at('a') == "42");
20 REQUIRE(map.size() == 1);
21 {
22 auto b = map.begin();
23 auto e = map.end();
24 auto n = std::next(map.begin());
25 REQUIRE_FALSE(b == n);
26 REQUIRE(n == e);
27 CHECK(b->first == 'a');
28 CHECK(b->second == "42");
29 }
30 REQUIRE(++map.begin() == map.end());
31 REQUIRE(map.begin() == --map.end());
32 REQUIRE(map.lower_bound('a') == map.find('a'));
33 REQUIRE(map.upper_bound('a') == map.end());
34 for (const auto& el : map) {
35 REQUIRE(el.first == 'a');
36 REQUIRE(el.second == "42");
37 }
38
39 const auto ZERO_V = "4567854";
40 map['\0'] = ZERO_V;
41 REQUIRE(map.contains('\0'));
42 REQUIRE(map.at('a') == "42");
43 REQUIRE(map.at('\0') == ZERO_V);
44 REQUIRE(map.size() == 2);
45 {
46 auto b = map.begin();
47 auto f = map.find('\0');
48 auto e = map.end();
49 auto n = std::next(map.begin());
50 REQUIRE(b == f);
51 REQUIRE_FALSE(b == n);
52 REQUIRE(b->second == ZERO_V);
53 REQUIRE_FALSE(n == e);
54 }
55 REQUIRE_FALSE(++map.begin() == map.end());
56 REQUIRE(std::next(map.begin(), 2) == map.end());
57 REQUIRE(std::prev(map.end(), 2) == map.begin());
58 REQUIRE(std::distance(map.begin(), map.end()) == 2);
59 REQUIRE(map.upper_bound('\t') == map.find('a'));
60
61 map[decltype(map)::min()] = "2";
62 REQUIRE(map.contains('a'));
63 REQUIRE(map.at('a') == "42");
64 REQUIRE(map.contains(map.min()));
65 REQUIRE(map.at(map.min()) == "2");
66 {
67 auto b = map.begin();
68 auto f = map.find(decltype(map)::min());
69 auto e = map.end();
70 auto n = std::next(map.begin());
71 REQUIRE(b == f);
72 REQUIRE(f->second == "2");
73 REQUIRE_FALSE(b == n);
74 REQUIRE_FALSE(b == e);
75 REQUIRE_FALSE(n == e);
76 }
77 REQUIRE(map.size() == 3);
78 REQUIRE_FALSE(++map.begin() == map.end());
79 {
80 auto b = map.begin();
81 REQUIRE_FALSE(b == map.end());
82 CHECK(b->first == decltype(map)::min());
83 ++b;
84 REQUIRE_FALSE(b == map.end());
85 CHECK(b->first == 0);
86 ++b;
87 REQUIRE_FALSE(b == map.end());
88 CHECK(b->first == 'a');
89 ++b;
90 REQUIRE(b == map.end());
91 }
92 REQUIRE(std::distance(map.begin(), map.end()) == 3);
93 REQUIRE(std::next(map.begin(), 3) == map.end());
94 REQUIRE(std::prev(map.end(), 3) == map.begin());
95 {
96 auto map2 = map;
97 REQUIRE(map == map2);
98 auto map3 = std::move(map);
99 REQUIRE(map2 == map3);
100 map2.swap(map);
101 REQUIRE(map == map3);
102 }
103}
104
105KBLIB_UNUSED static constexpr auto l(kblib::direct_map<char, int>& map,
108 -> bool {
109 using map_t = kblib::direct_map<char, int>;
110 map['a'] = 42;
111 static_cast<void>(map.contains('a'));
112 static_cast<void>(not map.contains('b'));
113 static_cast<void>(map.find('a') == map.begin());
114 static_cast<void>(map.begin() != map.end());
115 static_cast<void>(map.at('a') == 42);
116 static_cast<void>(map.size() == 1);
117 {
118 auto b = map.begin();
119 auto e = map.end();
120 auto n = b;
121 ++n;
122 static_cast<void>(b != n);
123 static_cast<void>(b->second == 42);
124 static_cast<void>(n == e);
125 }
126 static_cast<void>(map.begin() == --map.end());
127 static_cast<void>(map.lower_bound('a') == map.find('a'));
128 static_cast<void>(map.upper_bound('a') == map.end());
129 for (auto el : map) {
130 static_cast<void>(el.first == 'a');
131 static_cast<void>(el.second == 42);
132 }
133
134 const auto ZERO_V = 4567854;
135 map['\0'] = ZERO_V;
136 static_cast<void>(map.contains('\0'));
137 static_cast<void>(map.at('a') == 42);
138 static_cast<void>(map.at('\0') == ZERO_V);
139 static_cast<void>(map.size() == 2);
140 {
141 auto b = map.begin();
142 auto f = map.find('\0');
143 auto e = map.end();
144 auto n = std::next(map.begin());
145 static_cast<void>(b == f);
146 static_cast<void>(b != n);
147 static_cast<void>(b->second == ZERO_V);
148 static_cast<void>(n != e);
149 }
150 static_cast<void>(++map.begin() != map.end());
151 static_cast<void>(std::next(map.begin(), 2) == map.end());
152 static_cast<void>(std::prev(map.end(), 2) == map.begin());
153 static_cast<void>(std::distance(map.begin(), map.end()) == 2);
154 static_cast<void>(map.upper_bound('\t') == map.find('a'));
155
156 map[map_t::min()] = 2;
157 static_cast<void>(map.at('a') == 42);
158 static_cast<void>(map.at(map_t::min()) == 2);
159 {
160 auto b = map.begin();
161 auto f = map.find(map_t::min());
162 auto e = map.end();
163 auto n = std::next(map.begin());
164 static_cast<void>(f->second == 2);
165 static_cast<void>(b != n);
166 static_cast<void>(b != e);
167 static_cast<void>(n != e);
168 }
169 static_cast<void>(++map.begin() != map.end());
170 static_cast<void>(std::next(map.begin(), 3) == map.end());
171 static_cast<void>(std::prev(map.end(), 3) == map.begin());
172 static_cast<void>(std::distance(map.begin(), map.end()) == 3);
173 {
174 map2 = map;
175 static_cast<void>(map == map2);
176 map3 = std::move(map);
177 static_cast<void>(map2 == map3);
178 map2.swap(map);
179 static_cast<void>(map == map3);
180 }
181 return true;
182}
183
184TEST_CASE("direct_map<trivial>") {
186 REQUIRE(map.begin() == map.end());
187 REQUIRE((map.size()) == 0);
188 REQUIRE(map.empty());
189 REQUIRE_FALSE(map.contains('a'));
190 map['a'] = 42;
191 REQUIRE(map.contains('a'));
192 REQUIRE_FALSE(map.contains('b'));
193 REQUIRE(map.find('a') == map.begin());
194 REQUIRE_FALSE(map.begin() == map.end());
195 REQUIRE(map.at('a') == 42);
196 REQUIRE(map.size() == 1);
197 {
198 auto b = map.begin();
199 auto e = map.end();
200 auto n = std::next(map.begin());
201 REQUIRE_FALSE(b == n);
202 REQUIRE(n == e);
203 CHECK(b->first == 'a');
204 CHECK(b->second == 42);
205 }
206 REQUIRE(++map.begin() == map.end());
207 REQUIRE(map.begin() == --map.end());
208 REQUIRE(map.lower_bound('a') == map.find('a'));
209 REQUIRE(map.upper_bound('a') == map.end());
210 for (auto el : map) {
211 REQUIRE(el.first == 'a');
212 REQUIRE(el.second == 42);
213 }
214
215 const auto ZERO_V = 4567854;
216 map['\0'] = ZERO_V;
217 REQUIRE(map.contains('\0'));
218 REQUIRE(map.at('a') == 42);
219 REQUIRE(map.at('\0') == ZERO_V);
220 REQUIRE(map.size() == 2);
221 {
222 auto b = map.begin();
223 auto f = map.find('\0');
224 auto e = map.end();
225 auto n = std::next(map.begin());
226 REQUIRE(b == f);
227 REQUIRE_FALSE(b == n);
228 REQUIRE(b->second == ZERO_V);
229 REQUIRE_FALSE(n == e);
230 }
231 REQUIRE_FALSE(++map.begin() == map.end());
232 REQUIRE(std::next(map.begin(), 2) == map.end());
233 REQUIRE(std::prev(map.end(), 2) == map.begin());
234 REQUIRE(std::distance(map.begin(), map.end()) == 2);
235 REQUIRE(map.upper_bound('\t') == map.find('a'));
236
237 map[decltype(map)::min()] = 2;
238 REQUIRE(map.contains('a'));
239 REQUIRE(map.at('a') == 42);
240 REQUIRE(map.contains(map.min()));
241 REQUIRE(map.at(map.min()) == 2);
242 {
243 auto b = map.begin();
244 auto f = map.find(decltype(map)::min());
245 auto e = map.end();
246 auto n = std::next(map.begin());
247 REQUIRE(b == f);
248 REQUIRE(f->second == 2);
249 REQUIRE_FALSE(b == n);
250 REQUIRE_FALSE(b == e);
251 REQUIRE_FALSE(n == e);
252 }
253 REQUIRE(map.size() == 3);
254 REQUIRE_FALSE(++map.begin() == map.end());
255 {
256 auto b = map.begin();
257 REQUIRE_FALSE(b == map.end());
258 CHECK(b->first == decltype(map)::min());
259 ++b;
260 REQUIRE_FALSE(b == map.end());
261 CHECK(b->first == 0);
262 ++b;
263 REQUIRE_FALSE(b == map.end());
264 CHECK(b->first == 'a');
265 ++b;
266 REQUIRE(b == map.end());
267 }
268 REQUIRE(std::next(map.begin(), 3) == map.end());
269 REQUIRE(std::prev(map.end(), 3) == map.begin());
270 REQUIRE(std::distance(map.begin(), map.end()) == 3);
271 {
272 auto map2 = map;
273 REQUIRE(map == map2);
274 auto map3 = std::move(map);
275 REQUIRE(map2 == map3);
276 map2.swap(map);
277 REQUIRE(map == map3);
278 }
279}
280
281TEST_CASE("direct_map (heap)") {
282 kblib::direct_map<char, std::string,
283 std::allocator<std::pair<const char, std::string>>>
284 map;
285 REQUIRE(map.begin() == map.end());
286 REQUIRE((map.size()) == 0);
287 REQUIRE(map.empty());
288 REQUIRE_FALSE(map.contains('a'));
289 map['a'] = "42";
290 REQUIRE(map.contains('a'));
291 REQUIRE_FALSE(map.contains('b'));
292 REQUIRE(map.find('a') == map.begin());
293 REQUIRE_FALSE(map.begin() == map.end());
294 REQUIRE(map.at('a') == "42");
295 REQUIRE(map.size() == 1);
296 {
297 auto b = map.begin();
298 auto e = map.end();
299 auto n = std::next(map.begin());
300 REQUIRE_FALSE(b == n);
301 REQUIRE(n == e);
302 CHECK(b->first == 'a');
303 CHECK(b->second == "42");
304 }
305 REQUIRE(++map.begin() == map.end());
306 REQUIRE(map.begin() == --map.end());
307 REQUIRE(map.lower_bound('a') == map.find('a'));
308 REQUIRE(map.upper_bound('a') == map.end());
309 for (const auto& el : map) {
310 REQUIRE(el.first == 'a');
311 REQUIRE(el.second == "42");
312 }
313
314 const auto ZERO_V = "4567854";
315 map['\0'] = ZERO_V;
316 REQUIRE(map.contains('\0'));
317 REQUIRE(map.at('a') == "42");
318 REQUIRE(map.at('\0') == ZERO_V);
319 REQUIRE(map.size() == 2);
320 {
321 auto b = map.begin();
322 auto f = map.find('\0');
323 auto e = map.end();
324 auto n = std::next(map.begin());
325 REQUIRE(b == f);
326 REQUIRE_FALSE(b == n);
327 REQUIRE(b->second == ZERO_V);
328 REQUIRE_FALSE(n == e);
329 }
330 REQUIRE_FALSE(++map.begin() == map.end());
331 REQUIRE(std::next(map.begin(), 2) == map.end());
332 REQUIRE(std::prev(map.end(), 2) == map.begin());
333 REQUIRE(std::distance(map.begin(), map.end()) == 2);
334 REQUIRE(map.upper_bound('\t') == map.find('a'));
335
336 map[decltype(map)::min()] = "2";
337 REQUIRE(map.contains('a'));
338 REQUIRE(map.at('a') == "42");
339 REQUIRE(map.contains(map.min()));
340 REQUIRE(map.at(map.min()) == "2");
341 {
342 auto b = map.begin();
343 auto f = map.find(decltype(map)::min());
344 auto e = map.end();
345 auto n = std::next(map.begin());
346 REQUIRE(b == f);
347 REQUIRE(f->second == "2");
348 REQUIRE_FALSE(b == n);
349 REQUIRE_FALSE(b == e);
350 REQUIRE_FALSE(n == e);
351 }
352 REQUIRE(map.size() == 3);
353 REQUIRE_FALSE(++map.begin() == map.end());
354 {
355 auto b = map.begin();
356 REQUIRE_FALSE(b == map.end());
357 CHECK(b->first == decltype(map)::min());
358 ++b;
359 REQUIRE_FALSE(b == map.end());
360 CHECK(b->first == 0);
361 ++b;
362 REQUIRE_FALSE(b == map.end());
363 CHECK(b->first == 'a');
364 ++b;
365 REQUIRE(b == map.end());
366 }
367 REQUIRE(std::next(map.begin(), 3) == map.end());
368 REQUIRE(std::prev(map.end(), 3) == map.begin());
369 REQUIRE(std::distance(map.begin(), map.end()) == 3);
370 {
371 auto map2 = map;
372 REQUIRE(map == map2);
373 auto map3 = std::move(map);
374 REQUIRE(map2 == map3);
375 map2.swap(map);
376 REQUIRE(map == map3);
377 }
378}
379
380TEST_CASE("direct_map<trivial> (heap)") {
381 kblib::direct_map<char, int,
382 std::allocator<std::pair<const char, std::string>>>
383 map;
384 REQUIRE(map.begin() == map.end());
385 REQUIRE((map.size()) == 0);
386 REQUIRE(map.empty());
387 REQUIRE_FALSE(map.contains('a'));
388 map['a'] = 42;
389 REQUIRE(map.contains('a'));
390 REQUIRE_FALSE(map.contains('b'));
391 REQUIRE(map.find('a') == map.begin());
392 REQUIRE_FALSE(map.begin() == map.end());
393 REQUIRE(map.at('a') == 42);
394 REQUIRE(map.size() == 1);
395 {
396 auto b = map.begin();
397 auto e = map.end();
398 auto n = std::next(map.begin());
399 REQUIRE_FALSE(b == n);
400 REQUIRE(n == e);
401 CHECK(b->first == 'a');
402 CHECK(b->second == 42);
403 }
404 REQUIRE(++map.begin() == map.end());
405 REQUIRE(map.begin() == --map.end());
406 REQUIRE(map.lower_bound('a') == map.find('a'));
407 REQUIRE(map.upper_bound('a') == map.end());
408 for (auto el : map) {
409 REQUIRE(el.first == 'a');
410 REQUIRE(el.second == 42);
411 }
412
413 const auto ZERO_V = 4567854;
414 map['\0'] = ZERO_V;
415 REQUIRE(map.contains('\0'));
416 REQUIRE(map.at('a') == 42);
417 REQUIRE(map.at('\0') == ZERO_V);
418 REQUIRE(map.size() == 2);
419 {
420 auto b = map.begin();
421 auto f = map.find('\0');
422 auto e = map.end();
423 auto n = std::next(map.begin());
424 REQUIRE(b == f);
425 REQUIRE_FALSE(b == n);
426 REQUIRE(b->second == ZERO_V);
427 REQUIRE_FALSE(n == e);
428 }
429 REQUIRE_FALSE(++map.begin() == map.end());
430 REQUIRE(std::next(map.begin(), 2) == map.end());
431 REQUIRE(std::prev(map.end(), 2) == map.begin());
432 REQUIRE(std::distance(map.begin(), map.end()) == 2);
433 REQUIRE(map.upper_bound('\t') == map.find('a'));
434
435 map[decltype(map)::min()] = 2;
436 REQUIRE(map.contains('a'));
437 REQUIRE(map.at('a') == 42);
438 REQUIRE(map.contains(map.min()));
439 REQUIRE(map.at(map.min()) == 2);
440 {
441 auto b = map.begin();
442 auto f = map.find(decltype(map)::min());
443 auto e = map.end();
444 auto n = std::next(map.begin());
445 REQUIRE(b == f);
446 REQUIRE(f->second == 2);
447 REQUIRE_FALSE(b == n);
448 REQUIRE_FALSE(b == e);
449 REQUIRE_FALSE(n == e);
450 }
451 REQUIRE(map.size() == 3);
452 REQUIRE_FALSE(++map.begin() == map.end());
453 {
454 auto b = map.begin();
455 REQUIRE_FALSE(b == map.end());
456 CHECK(b->first == decltype(map)::min());
457 ++b;
458 REQUIRE_FALSE(b == map.end());
459 CHECK(b->first == 0);
460 ++b;
461 REQUIRE_FALSE(b == map.end());
462 CHECK(b->first == 'a');
463 ++b;
464 REQUIRE(b == map.end());
465 }
466 REQUIRE(std::next(map.begin(), 3) == map.end());
467 REQUIRE(std::prev(map.end(), 3) == map.begin());
468 REQUIRE(std::distance(map.begin(), map.end()) == 3);
469 {
470 auto map2 = map;
471 REQUIRE(map == map2);
472 auto map3 = std::move(map);
473 REQUIRE(map2 == map3);
474 map2.swap(map);
475 REQUIRE(map == map3);
476 }
477}
TEST_CASE("direct_map")
Definition: direct_map.cpp:8
Provides direct_map.
constexpr struct kblib::nums::min_t min
auto map(F f, T &&... t) noexcept(noexcept(std::tuple{ kblib::apply(f, std::forward< T >(t))...})) -> enable_if_t< not any_void< decltype(kblib::apply(f, std::forward< T >(t)))... >, decltype(std::tuple{kblib::apply(f, std::forward< T >(t))...})>
Definition: simple.h:75
constexpr auto e() -> T
Definition: stats.h:468
#define KBLIB_UNUSED
This internal macro is used to provide a fallback for [[maybe_unused]] in C++14.
Definition: tdecl.h:130