Sequoia
Loading...
Searching...
No Matches
RegularTestDiagnosticsUtilities.hpp
Go to the documentation of this file.
1
2// Copyright Oliver J. Rosten 2020. //
3// Distributed under the GNU GENERAL PUBLIC LICENSE, Version 3.0. //
4// (See accompanying file LICENSE.md or copy at //
5// https://www.gnu.org/licenses/gpl-3.0.en.html) //
7
8#pragma once
9
13
16
17#include <vector>
18
19namespace sequoia::testing
20{
21 template<class T=int, class Allocator=std::allocator<int>>
23 {
24 using value_type = T;
25 using allocator_type = Allocator;
26
27 perfectly_normal_beast(std::initializer_list<T> list) : x{list} {}
28
29 perfectly_normal_beast(std::initializer_list<T> list, const allocator_type& a) : x{list, a} {}
30
31 perfectly_normal_beast(const allocator_type& a) : x(a) {}
32
34
35 perfectly_normal_beast(const perfectly_normal_beast& other, const allocator_type& a) : x(other.x, a) {}
36
38
39 perfectly_normal_beast(perfectly_normal_beast&& other, const allocator_type& a) : x(std::move(other.x), a) {}
40
41 perfectly_normal_beast& operator=(const perfectly_normal_beast&) = default;
42
43 perfectly_normal_beast& operator=(perfectly_normal_beast&&) = default;
44
45 void swap(perfectly_normal_beast& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
46 {
47 std::ranges::swap(x, other.x);
48 }
49
50 friend void swap(perfectly_normal_beast& lhs, perfectly_normal_beast& rhs)
51 noexcept(noexcept(lhs.swap(rhs)))
52 {
53 lhs.swap(rhs);
54 }
55
56 using container_type = std::vector<T, Allocator>;
57
58 container_type x{};
59
60 [[nodiscard]]
61 friend bool operator==(const perfectly_normal_beast&, const perfectly_normal_beast&) noexcept = default;
62
63 template<class Stream>
64 requires serializable<T>
65 friend Stream& operator<<(Stream& s, const perfectly_normal_beast& b)
66 {
67 for(const auto& i : b.x) s << i << '\n';
68 return s;
69 }
70
71 // Only provide de-serialization in simple cases to keep life easy!
72 template<class Stream>
73 requires std::is_arithmetic_v<T>
74 friend Stream& operator>>(Stream& s, perfectly_normal_beast& b)
75 {
76 b.x.clear();
77
78 int i{};
79 while(s >> i)
80 {
81 b.x.push_back(i);
82 }
83
84 return s;
85 }
86 };
87
88 template<class T, class Allocator>
90 {
91 template<test_mode Mode>
92 static void test(equality_check_t, test_logger<Mode>& logger, const perfectly_normal_beast<T, Allocator>& obtained, const perfectly_normal_beast<T, Allocator>& prediction)
93 {
94 check(equality, "", logger, obtained.x, prediction.x);
95 }
96
97 template<class Logger>
98 static void test(weak_equivalence_check_t, Logger& logger, const perfectly_normal_beast<T, Allocator>& beast, std::initializer_list<T> prediction)
99 {
100 check(weak_equivalence, "", logger, std::begin(beast.x), std::end(beast.x), std::begin(prediction), std::end(prediction));
101 }
102
103 template<class Logger, class Advisor>
104 static void test(weak_equivalence_check_t, Logger& logger, const perfectly_normal_beast<T, Allocator>& beast, std::initializer_list<T> prediction, tutor<Advisor> advisor)
105 {
106 check(weak_equivalence, "", logger, std::begin(beast.x), std::end(beast.x), std::begin(prediction), std::end(prediction), std::move(advisor));
107 }
108 };
109
110 template<class CharT = char, class Allocator=std::allocator<CharT>>
112 {
113 using allocator_type = Allocator;
114 using string_type = std::basic_string<CharT, std::char_traits<CharT>, Allocator>;
115
116 perfectly_stringy_beast() = default;
117
118 perfectly_stringy_beast(const CharT* s) : x{s} {}
119
120 perfectly_stringy_beast(const CharT* s, const allocator_type& a) : x{s, a} {}
121
122 perfectly_stringy_beast(const allocator_type& a) : x(a) {}
123
125
126 perfectly_stringy_beast(const perfectly_stringy_beast& other, const allocator_type& a) : x(other.x, a) {}
127
129
130 perfectly_stringy_beast(perfectly_stringy_beast&& other, const allocator_type& a) : x(std::move(other.x), a) {}
131
132 perfectly_stringy_beast& operator=(const perfectly_stringy_beast&) = default;
133
134 perfectly_stringy_beast& operator=(perfectly_stringy_beast&&) noexcept = default;
135
136 void swap(perfectly_stringy_beast& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
137 {
138 std::ranges::swap(x, other.x);
139 }
140
141 friend void swap(perfectly_stringy_beast& lhs, perfectly_stringy_beast& rhs)
142 noexcept(noexcept(lhs.swap(rhs)))
143 {
144 lhs.swap(rhs);
145 }
146
147 string_type x{};
148
149 [[nodiscard]]
150 friend bool operator==(const perfectly_stringy_beast&, const perfectly_stringy_beast&) noexcept = default;
151
152 template<class Stream>
153 friend Stream& operator<<(Stream& s, const perfectly_stringy_beast& b)
154 {
155 s << b.x;
156 return s;
157 }
158
159 template<class Stream>
160 friend Stream& operator>>(Stream& s, perfectly_stringy_beast& b)
161 {
162 b.x.clear();
163
164 string_type word{};
165 while(s >> word)
166 {
167 b.x.append(word).append(" ");
168 }
169
170 if(!b.x.empty()) b.x.pop_back();
171
172 return s;
173 }
174 };
175
176 template<class T = int, class Allocator = std::allocator<int>>
178 {
179 using value_type = T;
180 using allocator_type = Allocator;
181
182 specified_moved_from_beast(std::initializer_list<T> list) : x{list} {}
183
184 specified_moved_from_beast(std::initializer_list<T> list, const allocator_type& a) : x(list, a) {}
185
186 specified_moved_from_beast(const allocator_type& a) : x(a) {}
187
189
190 specified_moved_from_beast(const specified_moved_from_beast& other, const allocator_type& a) : x(other.x, a) {}
191
193 : x{std::move(other.x)}
194 {
195 other.x.clear();
196 }
197
198 specified_moved_from_beast(specified_moved_from_beast&& other, const allocator_type& a) : x(std::move(other.x), a) {}
199
200 specified_moved_from_beast& operator=(const specified_moved_from_beast&) = default;
201
203 {
204 x = std::move(other.x);
205 other.x.clear();
206
207 return *this;
208 }
209
210 void swap(specified_moved_from_beast& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
211 {
212 std::ranges::swap(x, other.x);
213 }
214
215 friend void swap(specified_moved_from_beast& lhs, specified_moved_from_beast& rhs)
216 noexcept(noexcept(lhs.swap(rhs)))
217 {
218 lhs.swap(rhs);
219 }
220
221 std::vector<T, Allocator> x{};
222
223 [[nodiscard]]
224 friend bool operator==(const specified_moved_from_beast&, const specified_moved_from_beast&) noexcept = default;
225
226 template<class Stream>
227 friend Stream& operator<<(Stream& s, const specified_moved_from_beast& b)
228 {
229 for(const auto& i : b.x) s << i << '\n';
230 return s;
231 }
232 };
233
234 template<class T, class Allocator>
235 struct value_tester<specified_moved_from_beast<T, Allocator>> : beast_equivalence_tester<specified_moved_from_beast<T, Allocator>> {};
236
237 template<class T=int, class Handle=std::shared_ptr<T>, class Allocator=std::allocator<Handle>>
239 {
240 using product_type = Handle;
241 using allocator_type = Allocator;
242 using container_type = std::vector<product_type, allocator_type>;
243
245 {
247
248 [[nodiscard]]
249 allocator_type operator()(const perfectly_sharing_beast& beast) const
250 {
251 return beast.x.get_allocator();
252 }
253 };
254
255 explicit perfectly_sharing_beast(const allocator_type& a) : x(a)
256 {}
257
258 perfectly_sharing_beast(std::initializer_list<T> list, const allocator_type& a = allocator_type{})
259 : x(a)
260 {
261 x.reserve(list.size());
262 for(auto e : list)
263 x.emplace_back(std::make_shared<T>(e));
264 };
265
266 perfectly_sharing_beast(const perfectly_sharing_beast& other)
267 : perfectly_sharing_beast(other, other.x.get_allocator())
268 {}
269
270 perfectly_sharing_beast(const perfectly_sharing_beast& other, const allocator_type& a)
271 : x(a)
272 {
273 x.reserve(other.x.size());
274 for(auto e : other.x)
275 {
276 x.emplace_back(std::make_shared<T>(*e));
277 }
278 }
279
280 perfectly_sharing_beast(perfectly_sharing_beast&&) noexcept = default;
281
282 perfectly_sharing_beast(perfectly_sharing_beast&& other, const allocator_type& a)
283 : x(std::move(other.x), a) {}
284
285 perfectly_sharing_beast& operator=(const perfectly_sharing_beast& other)
286 {
287 assignment_helper::assign(*this, other, alloc_acquirer{});
288
289 return *this;
290 }
291
292 perfectly_sharing_beast& operator=(perfectly_sharing_beast&&) = default;
293
294 void swap(perfectly_sharing_beast& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
295 {
296 std::ranges::swap(x, other.x);
297 }
298
299 friend void swap(perfectly_sharing_beast& lhs, perfectly_sharing_beast& rhs)
300 noexcept(noexcept(lhs.swap(rhs)))
301 {
302 lhs.swap(rhs);
303 }
304
305 container_type x{};
306
307 [[nodiscard]]
308 friend bool operator==(const perfectly_sharing_beast& lhs, const perfectly_sharing_beast& rhs) noexcept
309 {
310 return std::equal(lhs.x.cbegin(), lhs.x.cend(), rhs.x.cbegin(), rhs.x.cend(), [](auto& l, auto& r){
311 return *l == *r;
312 });
313 }
314
315 [[nodiscard]]
316 friend bool operator!=(const perfectly_sharing_beast& lhs, const perfectly_sharing_beast& rhs) noexcept
317 {
318 return !(lhs == rhs);
319 }
320
321 template<class Stream>
322 friend Stream& operator<<(Stream& s, const perfectly_sharing_beast& b)
323 {
324 for(auto i : b.x) s << *i << ' ';
325 return s;
326 }
327
328 void reset(const allocator_type& a)
329 {
330 const std::vector<product_type, allocator_type> v(a);
331 x = v;
332 }
333 };
334
335 template<class T=int, class U=double, class xAllocator=std::allocator<T>, class yAllocator=std::allocator<U>>
337 {
338 using x_allocator_type = xAllocator;
339 using y_allocator_type = yAllocator;
340
341 doubly_normal_beast(std::initializer_list<T> xlist, std::initializer_list<U> ylist)
342 : x{xlist} , y{ylist}
343 {}
344
345 doubly_normal_beast(std::initializer_list<T> xlist, std::initializer_list<U> ylist, const x_allocator_type& a, const y_allocator_type& b)
346 : x(xlist, a), y(ylist,b)
347 {}
348
350
351 doubly_normal_beast(const doubly_normal_beast& other, const x_allocator_type& a, const y_allocator_type& b)
352 : x(other.x, a), y(other.y, b)
353 {}
354
355 doubly_normal_beast(doubly_normal_beast&&) noexcept = default;
356
357 doubly_normal_beast(doubly_normal_beast&& other, const x_allocator_type& a, const y_allocator_type& b)
358 : x(std::move(other.x), a), y(std::move(other.y), b)
359 {}
360
361 doubly_normal_beast& operator=(const doubly_normal_beast&) = default;
362
363 doubly_normal_beast& operator=(doubly_normal_beast&&) = default;
364
365 void swap(doubly_normal_beast& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)) && noexcept(std::ranges::swap(this->y, other.y)))
366 {
367 std::ranges::swap(x, other.x);
368 std::ranges::swap(y, other.y);
369 }
370
371 friend void swap(doubly_normal_beast& lhs, doubly_normal_beast& rhs)
372 noexcept(noexcept(lhs.swap(rhs)))
373 {
374 lhs.swap(rhs);
375 }
376
377 std::vector<T, xAllocator> x{};
378 std::vector<U, yAllocator> y{};
379
380 [[nodiscard]]
381 friend bool operator==(const doubly_normal_beast& lhs, const doubly_normal_beast& rhs) noexcept
382 {
383 return (lhs.x == rhs.x) && (rhs.x == lhs.x);
384 }
385
386 [[nodiscard]]
387 friend bool operator!=(const doubly_normal_beast& lhs, const doubly_normal_beast& rhs) noexcept
388 {
389 return !(lhs == rhs);
390 }
391
392 template<class Stream>
393 friend Stream& operator<<(Stream& s, const doubly_normal_beast& b)
394 {
395 for(auto i : b.x) s << i << ' ';
396 for(auto i : b.y) s << i << ' ';
397 return s;
398 }
399 };
400
401 template<class T=int, class Allocator=std::allocator<int>>
403 {
404 using allocator_type = Allocator;
405
406 broken_equality(std::initializer_list<T> list) : x{list} {}
407
408 broken_equality(std::initializer_list<T> list, const allocator_type& a) : x(list, a) {}
409
410 broken_equality(const broken_equality&) = default;
411
412 broken_equality(const broken_equality& other, const allocator_type& a) : x(other.x, a) {}
413
414 broken_equality(broken_equality&&) noexcept = default;
415
416 broken_equality(broken_equality&& other, const allocator_type& a) : x(std::move(other.x), a) {}
417
418 broken_equality& operator=(const broken_equality&) = default;
419
420 broken_equality& operator=(broken_equality&&) = default;
421
422 friend void swap(broken_equality& lhs, broken_equality& rhs)
423 {
424 std::ranges::swap(lhs.x, rhs.x);
425 }
426
427 std::vector<T, Allocator> x{};
428
429 [[nodiscard]]
430 friend bool operator==(const broken_equality& lhs, const broken_equality& rhs) noexcept
431 {
432 return lhs.x != rhs.x;
433 }
434
435 [[nodiscard]]
436 friend bool operator!=(const broken_equality& lhs, const broken_equality& rhs) noexcept
437 {
438 return lhs.x != rhs.x;
439 }
440
441 template<class Stream>
442 friend Stream& operator<<(Stream& s, const broken_equality& b)
443 {
444 for(auto i : b.x) s << i << ' ';
445 return s;
446 }
447 };
448
449 template<class T=int, class Allocator=std::allocator<int>>
451 {
452 using allocator_type = Allocator;
453
454 broken_inequality(std::initializer_list<T> list) : x{list} {}
455
456 broken_inequality(std::initializer_list<T> list, const allocator_type& a) : x(list, a) {}
457
458 broken_inequality(const broken_inequality&) = default;
459
460 broken_inequality(const broken_inequality& other, const allocator_type& a) : x(other.x, a) {}
461
462 broken_inequality(broken_inequality&&) noexcept = default;
463
464 broken_inequality(broken_inequality&& other, const allocator_type& a) : x(std::move(other.x), a) {}
465
466 broken_inequality& operator=(const broken_inequality&) = default;
467
468 broken_inequality& operator=(broken_inequality&&) = default;
469
470 friend void swap(broken_inequality& lhs, broken_inequality& rhs)
471 {
472 std::ranges::swap(lhs.x, rhs.x);
473 }
474
475 std::vector<T, Allocator> x{};
476
477 [[nodiscard]]
478 friend bool operator==(const broken_inequality& lhs, const broken_inequality& rhs) noexcept = default;
479
480 [[nodiscard]]
481 friend bool operator!=(const broken_inequality& lhs, const broken_inequality& rhs) noexcept
482 {
483 return lhs.x == rhs.x;
484 }
485
486 template<class Stream>
487 friend Stream& operator<<(Stream& s, const broken_inequality& b)
488 {
489 for(auto i : b.x) s << i << ' ';
490 return s;
491 }
492 };
493
494 template<class T=int, class Allocator=std::allocator<int>>
496 {
497 using allocator_type = Allocator;
498
499 broken_copy(std::initializer_list<T> list) : x{list} {}
500
501 broken_copy(std::initializer_list<T> list, const allocator_type& a) : x{list, a} {}
502
504 {
505 // Do nothing
506 }
507
508 broken_copy(const broken_copy& other, const allocator_type& a) : x(other.x, a)
509 {}
510
511 broken_copy(broken_copy&&) = default;
512
513 broken_copy(broken_copy&& other, const allocator_type& a) : x(std::move(other.x), a) {}
514
515 broken_copy& operator=(const broken_copy&) = default;
516
517 broken_copy& operator=(broken_copy&&) = default;
518
519 friend void swap(broken_copy& lhs, broken_copy& rhs)
520 {
521 std::ranges::swap(lhs.x, rhs.x);
522 }
523
524 std::vector<T, Allocator> x{};
525
526 [[nodiscard]]
527 friend bool operator==(const broken_copy& lhs, const broken_copy& rhs) noexcept
528 {
529 return lhs.x == rhs.x;
530 }
531
532 [[nodiscard]]
533 friend bool operator!=(const broken_copy& lhs, const broken_copy& rhs) noexcept
534 {
535 return !(lhs == rhs);
536 }
537
538 template<class Stream>
539 friend Stream& operator<<(Stream& s, const broken_copy& b)
540 {
541 for(auto i : b.x) s << i << ' ';
542 return s;
543 }
544 };
545
546 template<class T=int, class Allocator=std::allocator<int>>
548 {
549 using allocator_type = Allocator;
550
551 broken_para_copy(std::initializer_list<T> list) : x{list} {}
552
553 broken_para_copy(std::initializer_list<T> list, const allocator_type& a) : x(list, a) {}
554
555 broken_para_copy(const broken_para_copy&) = default;
556
557 broken_para_copy(const broken_para_copy&, const allocator_type&)
558 {
559 // do nothing
560 }
561
563
564 broken_para_copy(broken_para_copy&& other, const allocator_type& a) : x(std::move(other.x), a) {}
565
566 broken_para_copy& operator=(const broken_para_copy&) = default;
567
568 broken_para_copy& operator=(broken_para_copy&&) = default;
569
570 friend void swap(broken_para_copy& lhs, broken_para_copy& rhs)
571 {
572 std::ranges::swap(lhs.x, rhs.x);
573 }
574
575 std::vector<T, Allocator> x{};
576
577 [[nodiscard]]
578 friend bool operator==(const broken_para_copy& lhs, const broken_para_copy& rhs) noexcept
579 {
580 return lhs.x == rhs.x;
581 }
582
583 [[nodiscard]]
584 friend bool operator!=(const broken_para_copy& lhs, const broken_para_copy& rhs) noexcept
585 {
586 return !(lhs == rhs);
587 }
588
589 template<class Stream>
590 friend Stream& operator<<(Stream& s, const broken_para_copy& b)
591 {
592 for(auto i : b.x) s << i << ' ';
593 return s;
594 }
595 };
596
597 template<class T=int, class Allocator=std::allocator<int>>
599 {
600 using allocator_type = Allocator;
601
602 broken_move(std::initializer_list<T> list) : x{list} {}
603
604 broken_move(std::initializer_list<T> list, const allocator_type& a) : x(list, a) {}
605
606 broken_move(const broken_move&) = default;
607
608 broken_move(const broken_move& other, const allocator_type& a) : x(other.x, a) {}
609
610 broken_move(broken_move&&) noexcept
611 {
612 // Do nothing
613 }
614
615 broken_move(broken_move&& other, const allocator_type& a) : x(std::move(other.x), a)
616 {}
617
618 broken_move& operator=(const broken_move&) = default;
619
620 broken_move& operator=(broken_move&&) = default;
621
622 friend void swap(broken_move& lhs, broken_move& rhs)
623 {
624 std::ranges::swap(lhs.x, rhs.x);
625 }
626
627 std::vector<T, Allocator> x{};
628
629 [[nodiscard]]
630 friend bool operator==(const broken_move& lhs, const broken_move& rhs) noexcept
631 {
632 return lhs.x == rhs.x;
633 }
634
635 [[nodiscard]]
636 friend bool operator!=(const broken_move& lhs, const broken_move& rhs) noexcept
637 {
638 return !(lhs == rhs);
639 }
640
641 template<class Stream>
642 friend Stream& operator<<(Stream& s, const broken_move& b)
643 {
644 for(auto i : b.x) s << i << ' ';
645 return s;
646 }
647 };
648
649 template<class T=int, class Allocator=std::allocator<int>>
651 {
652 using allocator_type = Allocator;
653
654 broken_para_move(std::initializer_list<T> list) : x{list} {}
655
656 broken_para_move(std::initializer_list<T> list, const allocator_type& a) : x(list, a) {}
657
658 broken_para_move(const broken_para_move&) = default;
659
660 broken_para_move(const broken_para_move& other, const allocator_type& a) : x(other.x, a) {}
661
663
664 broken_para_move(broken_para_move&&, const allocator_type&)
665 {
666 // do nothing
667 }
668
669 broken_para_move& operator=(const broken_para_move&) = default;
670
671 broken_para_move& operator=(broken_para_move&&) = default;
672
673 friend void swap(broken_para_move& lhs, broken_para_move& rhs)
674 {
675 std::ranges::swap(lhs.x, rhs.x);
676 }
677
678 std::vector<T, Allocator> x{};
679
680 [[nodiscard]]
681 friend bool operator==(const broken_para_move& lhs, const broken_para_move& rhs) noexcept
682 {
683 return lhs.x == rhs.x;
684 }
685
686 [[nodiscard]]
687 friend bool operator!=(const broken_para_move& lhs, const broken_para_move& rhs) noexcept
688 {
689 return !(lhs == rhs);
690 }
691
692 template<class Stream>
693 friend Stream& operator<<(Stream& s, const broken_para_move& b)
694 {
695 for(auto i : b.x) s << i << ' ';
696 return s;
697 }
698 };
699
700 template<class T=int, class Allocator=std::allocator<int>>
702 {
703 using allocator_type = Allocator;
704
705 broken_copy_assignment(std::initializer_list<int> list) : x{list} {}
706
707 broken_copy_assignment(std::initializer_list<int> list, const allocator_type& a) : x(list, a) {}
708
710
711 broken_copy_assignment(const broken_copy_assignment& other, const allocator_type& a) : x(other.x, a) {}
712
714
715 broken_copy_assignment(broken_copy_assignment&& other, const allocator_type& a) : x(std::move(other.x), a) {}
716
718 {
719 return *this;
720 }
721
722 broken_copy_assignment& operator=(broken_copy_assignment&&) = default;
723
724 friend void swap(broken_copy_assignment& lhs, broken_copy_assignment& rhs)
725 {
726 std::ranges::swap(lhs.x, rhs.x);
727 }
728
729 std::vector<T, Allocator> x{};
730
731 [[nodiscard]]
732 friend bool operator==(const broken_copy_assignment& lhs, const broken_copy_assignment& rhs) noexcept
733 {
734 return lhs.x == rhs.x;
735 }
736
737 [[nodiscard]]
738 friend bool operator!=(const broken_copy_assignment& lhs, const broken_copy_assignment& rhs) noexcept
739 {
740 return !(lhs == rhs);
741 }
742
743 template<class Stream>
744 friend Stream& operator<<(Stream& s, const broken_copy_assignment& b)
745 {
746 for(auto i : b.x) s << i << ' ';
747 return s;
748 }
749 };
750
751 template<class T=int, class Allocator=std::allocator<int>>
753 {
754 using allocator_type = Allocator;
755
756 broken_self_copy_assignment(std::initializer_list<int> list) : x{list} {}
757
758 broken_self_copy_assignment(std::initializer_list<int> list, const allocator_type& a) : x(list, a) {}
759
761
762 broken_self_copy_assignment(const broken_self_copy_assignment& other, const allocator_type& a) : x(other.x, a) {}
763
765
766 broken_self_copy_assignment(broken_self_copy_assignment&& other, const allocator_type& a) : x(std::move(other.x), a) {}
767
769 {
770 if(&other == this)
771 {
772 x.push_back(T{});
773 }
774 else
775 {
776 x = other.x;
777 }
778
779 return *this;
780 }
781
783
785 {
786 std::ranges::swap(lhs.x, rhs.x);
787 }
788
789 std::vector<T, Allocator> x{};
790
791 [[nodiscard]]
792 friend bool operator==(const broken_self_copy_assignment& lhs, const broken_self_copy_assignment& rhs) = default;
793
794 template<class Stream>
795 friend Stream& operator<<(Stream& s, const broken_self_copy_assignment& b)
796 {
797 for(auto i : b.x) s << i << ' ';
798 return s;
799 }
800 };
801
802 template<class T=int, class Allocator=std::allocator<int>>
804 {
805 using allocator_type = Allocator;
806
807 broken_move_assignment(std::initializer_list<T> list) : x{list} {}
808
809 broken_move_assignment(std::initializer_list<T> list, const allocator_type& a) : x(list, a) {}
810
812
813 broken_move_assignment(const broken_move_assignment& other, const allocator_type& a) : x(other.x, a) {}
814
816
817 broken_move_assignment(broken_move_assignment&& other, const allocator_type& a) : x(std::move(other.x), a) {}
818
819 broken_move_assignment& operator=(const broken_move_assignment&) = default;
820
822 {
823 return *this;
824 }
825
826 friend void swap(broken_move_assignment& lhs, broken_move_assignment& rhs)
827 {
828 std::ranges::swap(lhs.x, rhs.x);
829 }
830
831 std::vector<T, Allocator> x{};
832
833 [[nodiscard]]
834 friend bool operator==(const broken_move_assignment& lhs, const broken_move_assignment& rhs) noexcept
835 {
836 return lhs.x == rhs.x;
837 }
838
839 [[nodiscard]]
840 friend bool operator!=(const broken_move_assignment& lhs, const broken_move_assignment& rhs) noexcept
841 {
842 return !(lhs == rhs);
843 }
844
845 template<class Stream>
846 friend Stream& operator<<(Stream& s, const broken_move_assignment& b)
847 {
848 for(auto i : b.x) s << i << ' ';
849 return s;
850 }
851 };
852
853 template<class T=int, class Allocator=std::allocator<int>>
855 {
856 using allocator_type = Allocator;
857
858 broken_swap(std::initializer_list<T> list) : x{list} {}
859
860 broken_swap(std::initializer_list<T> list, const allocator_type& a) : x{list, a} {}
861
862 broken_swap(const broken_swap&) = default;
863
864 broken_swap(const broken_swap& other, const allocator_type& a) : x(other.x, a) {}
865
866 broken_swap(broken_swap&&) noexcept = default;
867
868 broken_swap(broken_swap&& other, const allocator_type& a) : x(std::move(other.x), a) {}
869
870 broken_swap& operator=(const broken_swap&) = default;
871
872 broken_swap& operator=(broken_swap&&) noexcept = default;
873
874 friend void swap(broken_swap&, broken_swap&) noexcept
875 {
876 // do nothing
877 }
878
879 std::vector<T, Allocator> x{};
880
881 [[nodiscard]]
882 friend bool operator==(const broken_swap& lhs, const broken_swap& rhs) noexcept = default;
883
884 template<class Stream>
885 friend Stream& operator<<(Stream& s, const broken_swap& b)
886 {
887 for(auto i : b.x) s << i << ' ';
888 return s;
889 }
890 };
891
892 template<class T=int, class Allocator=std::allocator<int>>
894 {
895 using allocator_type = Allocator;
896
897 broken_self_swap(std::initializer_list<T> list) : x{list} {}
898
899 broken_self_swap(std::initializer_list<T> list, const allocator_type& a) : x{list, a} {}
900
901 broken_self_swap(const broken_self_swap&) = default;
902
903 broken_self_swap(const broken_self_swap& other, const allocator_type& a) : x(other.x, a) {}
904
905 broken_self_swap(broken_self_swap&&) noexcept = default;
906
907 broken_self_swap(broken_self_swap&& other, const allocator_type& a) : x(std::move(other.x), a) {}
908
909 broken_self_swap& operator=(const broken_self_swap&) = default;
910
911 broken_self_swap& operator=(broken_self_swap&&) noexcept = default;
912
913 void swap(broken_self_swap& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
914 {
915 if(&other == this)
916 {
917 x.push_back(T{});
918 }
919 else
920 {
921 std::ranges::swap(this->x, other.x);
922 }
923 }
924
925 friend void swap(broken_self_swap& lhs, broken_self_swap& rhs)
926 noexcept(noexcept(lhs.swap(rhs)))
927 {
928 lhs.swap(rhs);
929 }
930
931 std::vector<T, Allocator> x{};
932
933 [[nodiscard]]
934 friend bool operator==(const broken_self_swap& lhs, const broken_self_swap& rhs) noexcept = default;
935
936 template<class Stream>
937 friend Stream& operator<<(Stream& s, const broken_self_swap& b)
938 {
939 for(auto i : b.x) s << i << ' ';
940 return s;
941 }
942 };
943
944 template<class T=int, class Handle=std::shared_ptr<T>, class Allocator=std::allocator<Handle>>
946 {
947 using product_type = Handle;
948 using allocator_type = Allocator;
949
951 {
953
954 [[nodiscard]]
955 allocator_type operator()(const broken_copy_value_semantics& beast) const
956 {
957 return beast.x.get_allocator();
958 }
959 };
960
961 broken_copy_value_semantics(std::initializer_list<T> list, const allocator_type& a = allocator_type{})
962 : x(a)
963 {
964 x.reserve(list.size());
965 for(auto e : list)
966 x.emplace_back(std::make_shared<T>(e));
967 };
968
969 broken_copy_value_semantics(const broken_copy_value_semantics&) = default; // Broken!
970
971 broken_copy_value_semantics(const broken_copy_value_semantics& other, const allocator_type& a)
972 : x(a)
973 {
974 x.reserve(other.x.size());
975 for(auto e : other.x)
976 {
977 x.emplace_back(std::make_shared<T>(*e));
978 }
979 }
980
981 broken_copy_value_semantics(broken_copy_value_semantics&&) noexcept = default;
982
983 broken_copy_value_semantics(broken_copy_value_semantics&& other, const allocator_type& a)
984 : x(std::move(other.x), a) {}
985
986 broken_copy_value_semantics& operator=(const broken_copy_value_semantics& other)
987 {
988 auto allocGetter{
989 [](const broken_copy_value_semantics& psb) {
990 return psb.x.get_allocator();
991 }
992 };
993
994 assignment_helper::assign(*this, other, allocGetter);
995
996 return *this;
997 }
998
999 broken_copy_value_semantics& operator=(broken_copy_value_semantics&&) = default;
1000
1001 void swap(broken_copy_value_semantics& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
1002 {
1003 std::ranges::swap(x, other.x);
1004 }
1005
1006 friend void swap(broken_copy_value_semantics& lhs, broken_copy_value_semantics& rhs)
1007 noexcept(noexcept(lhs.swap(rhs)))
1008 {
1009 lhs.swap(rhs);
1010 }
1011
1012 void reset(const allocator_type& a)
1013 {
1014 const std::vector<product_type, allocator_type> v(a);
1015 x = v;
1016 }
1017
1018 std::vector<product_type, allocator_type> x{};
1019
1020 [[nodiscard]]
1021 friend bool operator==(const broken_copy_value_semantics& lhs, const broken_copy_value_semantics& rhs) noexcept
1022 {
1023 return std::equal(lhs.x.cbegin(), lhs.x.cend(), rhs.x.cbegin(), rhs.x.cend(), [](auto& l, auto& r) {
1024 return *l == *r;
1025 });
1026 }
1027
1028 [[nodiscard]]
1029 friend bool operator!=(const broken_copy_value_semantics& lhs, const broken_copy_value_semantics& rhs) noexcept
1030 {
1031 return !(lhs == rhs);
1032 }
1033
1034 template<class Stream>
1035 friend Stream& operator<<(Stream& s, const broken_copy_value_semantics& b)
1036 {
1037 for(auto i : b.x) s << *i << ' ';
1038 return s;
1039 }
1040 };
1041
1042 template<class T=int, class Handle=std::shared_ptr<T>, class Allocator=std::allocator<Handle>>
1044 {
1045 using product_type = Handle;
1046 using allocator_type = Allocator;
1047
1048 broken_copy_assignment_value_semantics(std::initializer_list<T> list, const allocator_type& a = allocator_type{})
1049 : x(a)
1050 {
1051 x.reserve(list.size());
1052 for(auto e : list)
1053 x.emplace_back(std::make_shared<T>(e));
1054 };
1055
1057 : broken_copy_assignment_value_semantics(other, other.x.get_allocator())
1058 {}
1059
1061 : x(a)
1062 {
1063 x.reserve(other.x.size());
1064 for(auto e : other.x)
1065 {
1066 x.emplace_back(std::make_shared<T>(*e));
1067 }
1068 }
1069
1071
1073 : x(std::move(other.x), a) {}
1074
1076
1078
1080 {
1081 std::ranges::swap(lhs.x, rhs.x);
1082 }
1083
1084 std::vector<product_type, allocator_type> x{};
1085
1086 [[nodiscard]]
1087 friend bool operator==(const broken_copy_assignment_value_semantics& lhs, const broken_copy_assignment_value_semantics& rhs) noexcept
1088 {
1089 return std::equal(lhs.x.cbegin(), lhs.x.cend(), rhs.x.cbegin(), rhs.x.cend(), [](auto& l, auto& r){
1090 return *l == *r;
1091 });
1092 }
1093
1094 [[nodiscard]]
1095 friend bool operator!=(const broken_copy_assignment_value_semantics& lhs, const broken_copy_assignment_value_semantics& rhs) noexcept
1096 {
1097 return !(lhs == rhs);
1098 }
1099
1100 template<class Stream>
1101 friend Stream& operator<<(Stream& s, const broken_copy_assignment_value_semantics& b)
1102 {
1103 for(auto i : b.x) s << *i << ' ';
1104 return s;
1105 }
1106 };
1107
1108 template<class T=int, class Allocator=std::allocator<int>>
1110 {
1111 using allocator_type = Allocator;
1112
1113 broken_serialization(std::initializer_list<T> list) : x{list} {}
1114
1115 broken_serialization(std::initializer_list<T> list, const allocator_type& a) : x{list, a} {}
1116
1117 broken_serialization(const allocator_type& a) : x(a) {}
1118
1120
1121 broken_serialization(const broken_serialization& other, const allocator_type& a) : x(other.x, a) {}
1122
1123 broken_serialization(broken_serialization&&) noexcept = default;
1124
1125 broken_serialization(broken_serialization&& other, const allocator_type& a) : x(std::move(other.x), a) {}
1126
1127 broken_serialization& operator=(const broken_serialization&) = default;
1128
1129 broken_serialization& operator=(broken_serialization&&) = default;
1130
1131 void swap(broken_serialization& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
1132 {
1133 std::ranges::swap(x, other.x);
1134 }
1135
1136 friend void swap(broken_serialization& lhs, broken_serialization& rhs)
1137 noexcept(noexcept(lhs.swap(rhs)))
1138 {
1139 lhs.swap(rhs);
1140 }
1141
1142 std::vector<T, Allocator> x{};
1143
1144 [[nodiscard]]
1145 friend bool operator==(const broken_serialization&, const broken_serialization&) noexcept = default;
1146
1147 template<class Stream>
1148 friend Stream& operator<<(Stream& s, const broken_serialization&)
1149 {
1150 return s;
1151 }
1152
1153 template<class Stream>
1154 friend Stream& operator>>(Stream& s, broken_serialization& b)
1155 {
1156 b.x.clear();
1157
1158 int i{};
1159 while(s >> i)
1160 {
1161 b.x.push_back(i);
1162 }
1163
1164 return s;
1165 }
1166 };
1167
1168 template<class T=int, class Allocator=std::allocator<int>>
1170 {
1171 using allocator_type = Allocator;
1172
1173 broken_deserialization(std::initializer_list<T> list) : x{list} {}
1174
1175 broken_deserialization(std::initializer_list<T> list, const allocator_type& a) : x{list, a} {}
1176
1177 broken_deserialization(const allocator_type& a) : x(a) {}
1178
1180
1181 broken_deserialization(const broken_deserialization& other, const allocator_type& a) : x(other.x, a) {}
1182
1183 broken_deserialization(broken_deserialization&&) noexcept = default;
1184
1185 broken_deserialization(broken_deserialization&& other, const allocator_type& a) : x(std::move(other.x), a) {}
1186
1187 broken_deserialization& operator=(const broken_deserialization&) = default;
1188
1189 broken_deserialization& operator=(broken_deserialization&&) = default;
1190
1191 void swap(broken_deserialization& other) noexcept(noexcept(std::ranges::swap(this->x, other.x)))
1192 {
1193 std::ranges::swap(x, other.x);
1194 }
1195
1196 friend void swap(broken_deserialization& lhs, broken_deserialization& rhs)
1197 noexcept(noexcept(lhs.swap(rhs)))
1198 {
1199 lhs.swap(rhs);
1200 }
1201
1202 std::vector<T, Allocator> x{};
1203
1204 [[nodiscard]]
1205 friend bool operator==(const broken_deserialization&, const broken_deserialization&) noexcept = default;
1206
1207 [[nodiscard]]
1208 friend bool operator!=(const broken_deserialization&, const broken_deserialization&) noexcept = default;
1209
1210 template<class Stream>
1211 friend Stream& operator<<(Stream& s, const broken_deserialization& b)
1212 {
1213 for(auto i : b.x) s << i << ' ';
1214 return s;
1215 }
1216
1217 template<class Stream>
1218 friend Stream& operator>>(Stream& s, broken_deserialization&)
1219 {
1220 return s;
1221 }
1222 };
1223
1224}
Client-facing utilities for performing allocation checks.
Helper for dealing with allocator propagation during copy assignment.
bool check(CheckType flavour, std::string description, test_logger< Mode > &logger, Iter first, Sentinel last, PredictionIter predictionFirst, PredictionSentinel predictionLast, tutor< Advisor > advisor={})
The workhorse for comparing the contents of ranges.
Definition: FreeCheckers.hpp:377
Definition: TestLogger.hpp:183
class template used to wrap function objects which proffer advice.
Definition: Advice.hpp:127
Definition: CoreInfrastructure.hpp:54
static constexpr void assign(T &to, const T &from, AllocGetters... allocGetters)
Definition: AssignmentUtilities.hpp:70
Definition: SemanticsTestDiagnosticsUtilities.hpp:20
Definition: RegularTestDiagnosticsUtilities.hpp:1044
Definition: RegularTestDiagnosticsUtilities.hpp:702
Definition: RegularTestDiagnosticsUtilities.hpp:951
Definition: RegularTestDiagnosticsUtilities.hpp:946
Definition: RegularTestDiagnosticsUtilities.hpp:496
Definition: RegularTestDiagnosticsUtilities.hpp:1170
Definition: RegularTestDiagnosticsUtilities.hpp:403
Definition: RegularTestDiagnosticsUtilities.hpp:451
Definition: RegularTestDiagnosticsUtilities.hpp:804
Definition: RegularTestDiagnosticsUtilities.hpp:599
Definition: RegularTestDiagnosticsUtilities.hpp:548
Definition: RegularTestDiagnosticsUtilities.hpp:651
Definition: RegularTestDiagnosticsUtilities.hpp:753
Definition: RegularTestDiagnosticsUtilities.hpp:894
Definition: RegularTestDiagnosticsUtilities.hpp:1110
Definition: RegularTestDiagnosticsUtilities.hpp:855
Definition: RegularTestDiagnosticsUtilities.hpp:337
Definition: FreeCheckers.hpp:82
Definition: RegularTestDiagnosticsUtilities.hpp:23
Definition: RegularTestDiagnosticsUtilities.hpp:245
Definition: RegularTestDiagnosticsUtilities.hpp:239
Definition: RegularTestDiagnosticsUtilities.hpp:112
Definition: RegularTestDiagnosticsUtilities.hpp:178
class template, specializations of which implement various comparisons for the specified type.
Definition: FreeCheckers.hpp:78