xrpld
Loading...
Searching...
No Matches
aged_associative_container_test.cpp
1#include <xrpl/beast/clock/manual_clock.h>
2#include <xrpl/beast/container/aged_map.h> // IWYU pragma: keep
3#include <xrpl/beast/container/aged_multimap.h> // IWYU pragma: keep
4#include <xrpl/beast/container/aged_multiset.h> // IWYU pragma: keep
5#include <xrpl/beast/container/aged_set.h> // IWYU pragma: keep
6#include <xrpl/beast/container/aged_unordered_map.h> // IWYU pragma: keep
7#include <xrpl/beast/container/aged_unordered_multimap.h> // IWYU pragma: keep
8#include <xrpl/beast/container/aged_unordered_multiset.h> // IWYU pragma: keep
9#include <xrpl/beast/container/aged_unordered_set.h> // IWYU pragma: keep
10#include <xrpl/beast/container/detail/aged_ordered_container.h>
11#include <xrpl/beast/container/detail/aged_unordered_container.h>
12#include <xrpl/beast/unit_test/suite.h>
13
14#include <algorithm>
15#include <chrono>
16#include <cstddef>
17#include <functional>
18#include <memory>
19#include <stdexcept>
20#include <string>
21#include <type_traits> // IWYU pragma: keep
22#include <utility>
23#include <vector> // IWYU pragma: keep
24
25#ifndef BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR
26#ifdef _MSC_VER
27#define BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR 0
28#else
29#define BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR 1
30#endif
31#endif
32
33#ifndef BEAST_CONTAINER_EXTRACT_NOREF
34#ifdef _MSC_VER
35#define BEAST_CONTAINER_EXTRACT_NOREF 1
36#else
37#define BEAST_CONTAINER_EXTRACT_NOREF 1
38#endif
39#endif
40
41namespace beast {
42
44{
45public:
46 template <class T>
47 struct CompT
48 {
49 CompT() = delete;
50
51 explicit CompT(int)
52 {
53 }
54
55 CompT(CompT const&)
56 {
57 }
58
59 bool
60 operator()(T const& lhs, T const& rhs) const
61 {
62 return less_(lhs, rhs);
63 }
64
65 private:
67 };
68
69 template <class T>
70 class HashT
71 {
72 public:
73 HashT() = delete;
74
75 explicit HashT(int)
76 {
77 }
78
80 operator()(T const& t) const
81 {
82 return hash_(t);
83 }
84
85 private:
87 };
88
89 template <class T>
90 struct EqualT
91 {
92 public:
93 EqualT() = delete;
94
95 explicit EqualT(int)
96 {
97 }
98
99 bool
100 operator()(T const& lhs, T const& rhs) const
101 {
102 return eq_(lhs, rhs);
103 }
104
105 private:
107 };
108
109 template <class T>
110 struct AllocT
111 {
112 using value_type = T;
113
114 // using std::true_type::type = propagate_on_container_swap :;
115
116 template <class U>
117 struct Rebind
118 {
120 };
121
122 explicit AllocT(int)
123 {
124 }
125
126 AllocT(AllocT const&) = default;
127
128 template <class U>
130 {
131 }
132
133 template <class U>
134 bool
135 operator==(AllocT<U> const&) const
136 {
137 return true;
138 }
139
140 template <class U>
141 bool
142 operator!=(AllocT<U> const& o) const
143 {
144 return !(*this == o);
145 }
146
147 T*
148 allocate(std::size_t n, T const* = nullptr)
149 {
150 return static_cast<T*>(::operator new(n * sizeof(T)));
151 }
152
153 void
155 {
156 ::operator delete(p);
157 }
158
159#if !BEAST_AGED_UNORDERED_NO_ALLOC_DEFAULTCTOR
161 {
162 }
163#else
164 AllocT() = delete;
165#endif
166 };
167
168 //--------------------------------------------------------------------------
169
170 // ordered
171 template <class Base, bool IsUnordered>
172 class MaybeUnordered : public Base
173 {
174 public:
177
178 protected:
179 static std::string
181 {
182 return "";
183 }
184 };
185
186 // unordered
187 template <class Base>
188 class MaybeUnordered<Base, true> : public Base
189 {
190 public:
195
196 protected:
197 static std::string
199 {
200 return "unordered_";
201 }
202 };
203
204 // unique
205 template <class Base, bool IsMulti>
206 class MaybeMulti : public Base
207 {
208 public:
209 protected:
210 static std::string
212 {
213 return "";
214 }
215 };
216
217 // multi
218 template <class Base>
219 class MaybeMulti<Base, true> : public Base
220 {
221 public:
222 protected:
223 static std::string
225 {
226 return "multi";
227 }
228 };
229
230 // set
231 template <class Base, bool IsMap>
232 class MaybeMap : public Base
233 {
234 public:
235 using T = void;
236 using Value = Base::Key;
238
239 static Base::Key const&
240 extract(Value const& value)
241 {
242 return value; // NOLINT(bugprone-return-const-ref-from-parameter)
243 }
244
245 static Values
247 {
248 Values v{
249 "apple",
250 "banana",
251 "cherry",
252 "grape",
253 "orange",
254 };
255 return v;
256 }
257
258 protected:
259 static std::string
261 {
262 return "set";
263 }
264 };
265
266 // map
267 template <class Base>
268 class MaybeMap<Base, true> : public Base
269 {
270 public:
271 using T = int;
274
275 static Base::Key const&
276 extract(Value const& value)
277 {
278 return value.first;
279 }
280
281 static Values
283 {
284 Values v{
285 std::make_pair("apple", 1),
286 std::make_pair("banana", 2),
287 std::make_pair("cherry", 3),
288 std::make_pair("grape", 4),
289 std::make_pair("orange", 5)};
290 return v;
291 }
292
293 protected:
294 static std::string
296 {
297 return "map";
298 }
299 };
300
301 //--------------------------------------------------------------------------
302
303 // ordered
304 template <class Base, bool IsUnordered = Base::is_unordered::value>
305 struct ContType
306 {
307 template <
308 class Compare = std::less<typename Base::Key>,
309 class Allocator = std::allocator<typename Base::Value>>
311 Base::is_multi::value,
312 Base::is_map::value,
313 typename Base::Key,
314 typename Base::T,
315 typename Base::Clock,
316 Compare,
317 Allocator>;
318 };
319
320 // unordered
321 template <class Base>
322 struct ContType<Base, true>
323 {
324 template <
326 class KeyEqual = std::equal_to<typename Base::Key>,
327 class Allocator = std::allocator<typename Base::Value>>
329 Base::is_multi::value,
330 Base::is_map::value,
331 typename Base::Key,
332 typename Base::T,
333 typename Base::Clock,
334 Hash,
335 KeyEqual,
336 Allocator>;
337 };
338
339 //--------------------------------------------------------------------------
340
347
348 template <bool IsUnordered, bool IsMulti, bool IsMap>
350 : MaybeUnordered<MaybeMulti<MaybeMap<TestTraitsBase, IsMap>, IsMulti>, IsUnordered>
351 {
352 private:
353 using Base =
355
356 public:
357 using typename Base::Key;
358
362
365
366 static std::string
368 {
369 return std::string("aged_") + Base::name_ordered_part() + Base::name_multi_part() +
370 Base::name_map_part();
371 }
372 };
373
374 template <bool IsUnordered, bool IsMulti, bool IsMap>
375 struct TestTraits : TestTraitsHelper<IsUnordered, IsMulti, IsMap>,
376 ContType<TestTraitsHelper<IsUnordered, IsMulti, IsMap>>
377 {
378 };
379
380 template <class Cont>
381 static std::string
386
387 template <class Traits>
389 {
390 bool
391 operator()(Traits::Value const& lhs, Traits::Value const& rhs)
392 {
393 return Traits::extract(lhs) == Traits::extract(rhs);
394 }
395 };
396
397 template <class Cont>
399 makeList(Cont const& c)
400 {
401 return std::vector<typename Cont::value_type>(c.begin(), c.end());
402 }
403
404 //--------------------------------------------------------------------------
405
406 template <class Container, class Values>
407 void
408 checkMapContents(Container& c, Values const& v)
409 requires(Container::is_map::value && !Container::is_multi::value);
410
411 template <class Container, class Values>
412 void
413 checkMapContents(Container, Values const&)
414 requires(!(Container::is_map::value && !Container::is_multi::value))
415 {
416 }
417
418 // unordered
419 template <class C, class Values>
420 void
421 checkUnorderedContentsRefRef(C&& c, Values const& v)
423
424 template <class C, class Values>
425 void
430
431 template <class C, class Values>
432 void
433 checkContentsRefRef(C&& c, Values const& v);
434
435 template <class Cont, class Values>
436 void
437 checkContents(Cont& c, Values const& v);
438
439 template <class Cont>
440 void
441 checkContents(Cont& c);
442
443 //--------------------------------------------------------------------------
444
445 // ordered
446 template <bool IsUnordered, bool IsMulti, bool IsMap>
447 void
449 requires(!IsUnordered);
450
451 // unordered
452 template <bool IsUnordered, bool IsMulti, bool IsMap>
453 void
455 requires IsUnordered;
456
457 // ordered
458 template <bool IsUnordered, bool IsMulti, bool IsMap>
459 void
461 requires(!IsUnordered);
462
463 // unordered
464 template <bool IsUnordered, bool IsMulti, bool IsMap>
465 void
467 requires IsUnordered;
468
469 // ordered
470 template <bool IsUnordered, bool IsMulti, bool IsMap>
471 void
473 requires(!IsUnordered);
474
475 // unordered
476 template <bool IsUnordered, bool IsMulti, bool IsMap>
477 void
479 requires IsUnordered;
480
481 //--------------------------------------------------------------------------
482
483 template <bool IsUnordered, bool IsMulti, bool IsMap>
484 void
485 testCopyMove();
486
487 //--------------------------------------------------------------------------
488
489 template <bool IsUnordered, bool IsMulti, bool IsMap>
490 void
491 testIterator();
492
493 // Unordered containers don't have reverse iterators
494 template <bool IsUnordered, bool IsMulti, bool IsMap>
495 void
497 requires(!IsUnordered);
498
499 template <bool IsUnordered, bool IsMulti, bool IsMap>
500 void
502 requires IsUnordered
503 {
504 }
505
506 //--------------------------------------------------------------------------
507
508 template <class Container, class Values>
509 void
510 checkInsertCopy(Container& c, Values const& v);
511
512 template <class Container, class Values>
513 void
514 checkInsertMove(Container& c, Values const& v);
515
516 template <class Container, class Values>
517 void
518 checkInsertHintCopy(Container& c, Values const& v);
519
520 template <class Container, class Values>
521 void
522 checkInsertHintMove(Container& c, Values const& v);
523
524 template <class Container, class Values>
525 void
526 checkEmplace(Container& c, Values const& v);
527
528 template <class Container, class Values>
529 void
530 checkEmplaceHint(Container& c, Values const& v);
531
532 template <bool IsUnordered, bool IsMulti, bool IsMap>
533 void
535
536 //--------------------------------------------------------------------------
537
538 template <bool IsUnordered, bool IsMulti, bool IsMap>
539 void
541
542 //--------------------------------------------------------------------------
543
544 // map, unordered_map
545 template <bool IsUnordered, bool IsMulti, bool IsMap>
546 void
548 requires(IsMap && !IsMulti);
549
550 template <bool IsUnordered, bool IsMulti, bool IsMap>
551 void
553 requires(!IsMap || IsMulti)
554 {
555 }
556
557 //--------------------------------------------------------------------------
558
559 // Helpers for erase tests
560 template <class Container, class Values>
561 void
562 reverseFillAgedContainer(Container& c, Values const& v);
563
564 template <class Iter>
565 Iter
566 nextToEndIter(Iter const beginIter, Iter const endItr);
567
568 //--------------------------------------------------------------------------
569
570 template <class Container, class Iter>
571 bool
572 doElementErase(Container& c, Iter const beginItr, Iter const endItr);
573
574 template <bool IsUnordered, bool IsMulti, bool IsMap>
575 void
577
578 //--------------------------------------------------------------------------
579
580 template <class Container, class BeginEndSrc>
581 void
582 doRangeErase(Container& c, BeginEndSrc const& beginEndSrc);
583
584 template <bool IsUnordered, bool IsMulti, bool IsMap>
585 void
587
588 //--------------------------------------------------------------------------
589
590 // ordered
591 template <bool IsUnordered, bool IsMulti, bool IsMap>
592 void
594 requires(!IsUnordered);
595
596 template <bool IsUnordered, bool IsMulti, bool IsMap>
597 void
599 requires IsUnordered
600 {
601 }
602
603 //--------------------------------------------------------------------------
604
605 // ordered
606 template <bool IsUnordered, bool IsMulti, bool IsMap>
607 void
609 requires(!IsUnordered);
610
611 // unordered
612 template <bool IsUnordered, bool IsMulti, bool IsMap>
613 void
615 requires IsUnordered;
616
617 //--------------------------------------------------------------------------
618
619 template <bool IsUnordered, bool IsMulti, bool IsMap>
620 void
622
623 template <bool IsUnordered, bool IsMulti>
624 void
626
627 template <bool IsUnordered>
628 void
630};
631
632//------------------------------------------------------------------------------
633
634// Check contents via at() and operator[]
635// map, unordered_map
636template <class Container, class Values>
637void
639 requires(Container::is_map::value && !Container::is_multi::value)
640{
641 if (v.empty())
642 {
643 BEAST_EXPECT(c.empty());
644 BEAST_EXPECT(c.size() == 0);
645 return;
646 }
647
648 try
649 {
650 // Make sure no exception is thrown
651 for (auto const& e : v)
652 c.at(e.first);
653 for (auto const& e : v)
654 BEAST_EXPECT(c.operator[](e.first) == e.second);
655 }
656 catch (std::out_of_range const&)
657 {
658 fail("caught exception");
659 }
660}
661
662// unordered
663template <class C, class Values>
664void
667{
668 using Cont = std::remove_reference_t<C>;
669 using Traits =
671 using size_type = Cont::size_type;
672 auto const hash(c.hashFunction());
673 auto const keyEq(c.keyEq());
674 for (size_type i(0); i < c.bucketCount(); ++i)
675 {
676 auto const last(c.end(i));
677 for (auto iter(c.begin(i)); iter != last; ++iter)
678 {
679 auto const match(std::ranges::find_if(v, [iter](Values::value_type const& e) {
680 return Traits::extract(*iter) == Traits::extract(e);
681 }));
682 BEAST_EXPECT(match != v.end());
683 BEAST_EXPECT(keyEq(Traits::extract(*iter), Traits::extract(*match)));
684 BEAST_EXPECT(hash(Traits::extract(*iter)) == hash(Traits::extract(*match)));
685 }
686 }
687}
688
689template <class C, class Values>
690void
692{
693 using Cont = std::remove_reference_t<C>;
694 using size_type = Cont::size_type;
695
696 BEAST_EXPECT(c.size() == v.size());
697 BEAST_EXPECT(size_type(std::distance(c.begin(), c.end())) == v.size());
698 BEAST_EXPECT(size_type(std::distance(c.cbegin(), c.cend())) == v.size());
699 BEAST_EXPECT(
700 size_type(std::distance(c.chronological.begin(), c.chronological.end())) == v.size());
701 BEAST_EXPECT(
702 size_type(std::distance(c.chronological.cbegin(), c.chronological.cend())) == v.size());
703 BEAST_EXPECT(
704 size_type(std::distance(c.chronological.rbegin(), c.chronological.rend())) == v.size());
705 BEAST_EXPECT(
706 size_type(std::distance(c.chronological.crbegin(), c.chronological.crend())) == v.size());
707
709}
710
711template <class Cont, class Values>
712void
714{
716 checkContentsRefRef(const_cast<Cont const&>(c), v);
717 checkMapContents(c, v);
718}
719
720template <class Cont>
721void
723{
724 using Traits =
726 using Values = Traits::Values;
727 checkContents(c, Values());
728}
729
730//------------------------------------------------------------------------------
731//
732// Construction
733//
734//------------------------------------------------------------------------------
735
736// ordered
737template <bool IsUnordered, bool IsMulti, bool IsMap>
738void
740 requires(!IsUnordered)
741{
743 using Comp = Traits::Comp;
744 using Alloc = Traits::Alloc;
745 using MyComp = Traits::MyComp;
746 using MyAlloc = Traits::MyAlloc;
747 typename Traits::ManualClock clock;
748
749 // testcase (Traits::name() + " empty");
750 testcase("empty");
751
752 {
753 typename Traits::template Cont<Comp, Alloc> c(clock);
754 checkContents(c);
755 }
756
757 {
758 typename Traits::template Cont<MyComp, Alloc> c(clock, MyComp(1));
759 checkContents(c);
760 }
761
762 {
763 typename Traits::template Cont<Comp, MyAlloc> c(clock, MyAlloc(1));
764 checkContents(c);
765 }
766
767 {
768 typename Traits::template Cont<MyComp, MyAlloc> c(clock, MyComp(1), MyAlloc(1));
769 checkContents(c);
770 }
771}
772
773// unordered
774template <bool IsUnordered, bool IsMulti, bool IsMap>
775void
777 requires IsUnordered
778{
779 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
780 using Hash = Traits::Hash;
781 using Equal = Traits::Equal;
782 using Alloc = Traits::Alloc;
783 using MyHash = Traits::MyHash;
784 using MyEqual = Traits::MyEqual;
785 using MyAlloc = Traits::MyAlloc;
786 typename Traits::ManualClock clock;
787
788 // testcase (Traits::name() + " empty");
789 testcase("empty");
790 {
791 typename Traits::template Cont<Hash, Equal, Alloc> c(clock);
792 checkContents(c);
793 }
794
795 {
796 typename Traits::template Cont<MyHash, Equal, Alloc> c(clock, MyHash(1));
797 checkContents(c);
798 }
799
800 {
801 typename Traits::template Cont<Hash, MyEqual, Alloc> c(clock, MyEqual(1));
802 checkContents(c);
803 }
804
805 {
806 typename Traits::template Cont<Hash, Equal, MyAlloc> c(clock, MyAlloc(1));
807 checkContents(c);
808 }
809
810 {
811 typename Traits::template Cont<MyHash, MyEqual, Alloc> c(clock, MyHash(1), MyEqual(1));
812 checkContents(c);
813 }
814
815 {
816 typename Traits::template Cont<MyHash, Equal, MyAlloc> c(clock, MyHash(1), MyAlloc(1));
817 checkContents(c);
818 }
819
820 {
821 typename Traits::template Cont<Hash, MyEqual, MyAlloc> c(clock, MyEqual(1), MyAlloc(1));
822 checkContents(c);
823 }
824
825 {
826 typename Traits::template Cont<MyHash, MyEqual, MyAlloc> c(
827 clock, MyHash(1), MyEqual(1), MyAlloc(1));
828 checkContents(c);
829 }
830}
831
832// ordered
833template <bool IsUnordered, bool IsMulti, bool IsMap>
834void
836 requires(!IsUnordered)
837{
839 using Comp = Traits::Comp;
840 using Alloc = Traits::Alloc;
841 using MyComp = Traits::MyComp;
842 using MyAlloc = Traits::MyAlloc;
843 typename Traits::ManualClock clock;
844 auto const v(Traits::values());
845
846 // testcase (Traits::name() + " range");
847 testcase("range");
848
849 {
850 typename Traits::template Cont<Comp, Alloc> c(v.begin(), v.end(), clock);
851 checkContents(c, v);
852 }
853
854 {
855 typename Traits::template Cont<MyComp, Alloc> c(v.begin(), v.end(), clock, MyComp(1));
856 checkContents(c, v);
857 }
858
859 {
860 typename Traits::template Cont<Comp, MyAlloc> c(v.begin(), v.end(), clock, MyAlloc(1));
861 checkContents(c, v);
862 }
863
864 {
865 typename Traits::template Cont<MyComp, MyAlloc> c(
866 v.begin(), v.end(), clock, MyComp(1), MyAlloc(1));
867 checkContents(c, v);
868 }
869
870 // swap
871
872 {
873 typename Traits::template Cont<Comp, Alloc> c1(v.begin(), v.end(), clock);
874 typename Traits::template Cont<Comp, Alloc> c2(clock);
875 std::swap(c1, c2);
876 checkContents(c2, v);
877 }
878}
879
880// unordered
881template <bool IsUnordered, bool IsMulti, bool IsMap>
882void
884 requires IsUnordered
885{
886 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
887 using Hash = Traits::Hash;
888 using Equal = Traits::Equal;
889 using Alloc = Traits::Alloc;
890 using MyHash = Traits::MyHash;
891 using MyEqual = Traits::MyEqual;
892 using MyAlloc = Traits::MyAlloc;
893 typename Traits::ManualClock clock;
894 auto const v(Traits::values());
895
896 // testcase (Traits::name() + " range");
897 testcase("range");
898
899 {
900 typename Traits::template Cont<Hash, Equal, Alloc> c(v.begin(), v.end(), clock);
901 checkContents(c, v);
902 }
903
904 {
905 typename Traits::template Cont<MyHash, Equal, Alloc> c(
906 v.begin(), v.end(), clock, MyHash(1));
907 checkContents(c, v);
908 }
909
910 {
911 typename Traits::template Cont<Hash, MyEqual, Alloc> c(
912 v.begin(), v.end(), clock, MyEqual(1));
913 checkContents(c, v);
914 }
915
916 {
917 typename Traits::template Cont<Hash, Equal, MyAlloc> c(
918 v.begin(), v.end(), clock, MyAlloc(1));
919 checkContents(c, v);
920 }
921
922 {
923 typename Traits::template Cont<MyHash, MyEqual, Alloc> c(
924 v.begin(), v.end(), clock, MyHash(1), MyEqual(1));
925 checkContents(c, v);
926 }
927
928 {
929 typename Traits::template Cont<MyHash, Equal, MyAlloc> c(
930 v.begin(), v.end(), clock, MyHash(1), MyAlloc(1));
931 checkContents(c, v);
932 }
933
934 {
935 typename Traits::template Cont<Hash, MyEqual, MyAlloc> c(
936 v.begin(), v.end(), clock, MyEqual(1), MyAlloc(1));
937 checkContents(c, v);
938 }
939
940 {
941 typename Traits::template Cont<MyHash, MyEqual, MyAlloc> c(
942 v.begin(), v.end(), clock, MyHash(1), MyEqual(1), MyAlloc(1));
943 checkContents(c, v);
944 }
945}
946
947// ordered
948template <bool IsUnordered, bool IsMulti, bool IsMap>
949void
951 requires(!IsUnordered)
952{
954 typename Traits::ManualClock const clock;
955
956 // testcase (Traits::name() + " init-list");
957 testcase("init-list");
958
959 // VFALCO TODO
960
961 pass();
962}
963
964// unordered
965template <bool IsUnordered, bool IsMulti, bool IsMap>
966void
968 requires IsUnordered
969{
970 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
971 typename Traits::ManualClock const clock;
972
973 // testcase (Traits::name() + " init-list");
974 testcase("init-list");
975
976 // VFALCO TODO
977 pass();
978}
979
980//------------------------------------------------------------------------------
981//
982// Copy/Move construction and assign
983//
984//------------------------------------------------------------------------------
985
986template <bool IsUnordered, bool IsMulti, bool IsMap>
987void
989{
991 using Alloc = Traits::Alloc;
992 typename Traits::ManualClock clock;
993 auto const v(Traits::values());
994
995 // testcase (Traits::name() + " copy/move");
996 testcase("copy/move");
997
998 // copy
999
1000 {
1001 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1002 typename Traits::template Cont<> c2(c);
1003 checkContents(c, v);
1004 checkContents(c2, v);
1005 BEAST_EXPECT(c == c2);
1006 unexpected(c != c2);
1007 }
1008
1009 {
1010 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1011 typename Traits::template Cont<> c2(c, Alloc());
1012 checkContents(c, v);
1013 checkContents(c2, v);
1014 BEAST_EXPECT(c == c2);
1015 unexpected(c != c2);
1016 }
1017
1018 {
1019 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1020 typename Traits::template Cont<> c2(clock);
1021 c2 = c;
1022 checkContents(c, v);
1023 checkContents(c2, v);
1024 BEAST_EXPECT(c == c2);
1025 unexpected(c != c2);
1026 }
1027
1028 // move
1029
1030 {
1031 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1032 typename Traits::template Cont<> c2(std::move(c));
1033 checkContents(c2, v);
1034 }
1035
1036 {
1037 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1038 typename Traits::template Cont<> c2(std::move(c), Alloc());
1039 checkContents(c2, v);
1040 }
1041
1042 {
1043 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1044 typename Traits::template Cont<> c2(clock);
1045 c2 = std::move(c);
1046 checkContents(c2, v);
1047 }
1048}
1049
1050//------------------------------------------------------------------------------
1051//
1052// Iterator construction and assignment
1053//
1054//------------------------------------------------------------------------------
1055
1056template <bool IsUnordered, bool IsMulti, bool IsMap>
1057void
1059{
1061 typename Traits::ManualClock clock;
1062 auto const v(Traits::values());
1063
1064 // testcase (Traits::name() + " iterators");
1065 testcase("iterator");
1066
1067 typename Traits::template Cont<> c{clock};
1068
1069 using iterator = decltype(c.begin());
1070 using const_iterator = decltype(c.cbegin());
1071
1072 // Should be able to construct or assign an iterator from an iterator.
1073 iterator const nnIt0{c.begin()};
1074 iterator const nnIt1{nnIt0};
1075 BEAST_EXPECT(nnIt0 == nnIt1);
1076 iterator nnIt2;
1077 nnIt2 = nnIt1;
1078 BEAST_EXPECT(nnIt1 == nnIt2);
1079
1080 // Should be able to construct or assign a const_iterator from a
1081 // const_iterator.
1082 const_iterator const ccIt0{c.cbegin()};
1083 const_iterator const ccIt1{ccIt0};
1084 BEAST_EXPECT(ccIt0 == ccIt1);
1085 const_iterator ccIt2;
1086 ccIt2 = ccIt1;
1087 BEAST_EXPECT(ccIt1 == ccIt2);
1088
1089 // Comparison between iterator and const_iterator is okay
1090 BEAST_EXPECT(nnIt0 == ccIt0);
1091 BEAST_EXPECT(ccIt1 == nnIt1);
1092
1093 // Should be able to construct a const_iterator from an iterator.
1094 const_iterator const ncIt3{c.begin()};
1095 const_iterator const ncIt4{nnIt0};
1096 BEAST_EXPECT(ncIt3 == ncIt4);
1097 const_iterator ncIt5;
1098 ncIt5 = nnIt2;
1099 BEAST_EXPECT(ncIt5 == ncIt4);
1100
1101 // None of these should compile because they construct or assign to a
1102 // non-const iterator with a const_iterator.
1103
1104 // iterator cnIt_0 {c.cbegin()};
1105
1106 // iterator cnIt_1 {ccIt_0};
1107
1108 // iterator cnIt_2;
1109 // cnIt_2 = ccIt_2;
1110}
1111
1112template <bool IsUnordered, bool IsMulti, bool IsMap>
1113void
1115 requires(!IsUnordered)
1116{
1118 typename Traits::ManualClock clock;
1119 auto const v(Traits::values());
1120
1121 // testcase (Traits::name() + " reverse_iterators");
1122 testcase("reverse_iterator");
1123
1124 typename Traits::template Cont<> c{clock};
1125
1126 using iterator = decltype(c.begin());
1127 using reverse_iterator = decltype(c.rbegin());
1128 using const_reverse_iterator = decltype(c.crbegin());
1129
1130 // Naming decoder ring
1131 // constructed from ------+ +----- constructed type
1132 // /\/\ -- character pairs
1133 // xAyBit
1134 // r (reverse) or f (forward)--^-^
1135 // ^-^------ C (const) or N (non-const)
1136
1137 // Should be able to construct or assign a reverse_iterator from a
1138 // reverse_iterator.
1139 reverse_iterator const rNrNit0{c.rbegin()};
1140 reverse_iterator const rNrNit1{rNrNit0};
1141 BEAST_EXPECT(rNrNit0 == rNrNit1);
1142 reverse_iterator xXrNit2;
1143 xXrNit2 = rNrNit1;
1144 BEAST_EXPECT(rNrNit1 == xXrNit2);
1145
1146 // Should be able to construct or assign a const_reverse_iterator from a
1147 // const_reverse_iterator
1148 const_reverse_iterator const rCrCit0{c.crbegin()};
1149 const_reverse_iterator const rCrCit1{rCrCit0};
1150 BEAST_EXPECT(rCrCit0 == rCrCit1);
1151 const_reverse_iterator xXrCit2;
1152 xXrCit2 = rCrCit1;
1153 BEAST_EXPECT(rCrCit1 == xXrCit2);
1154
1155 // Comparison between reverse_iterator and const_reverse_iterator is okay
1156 BEAST_EXPECT(rNrNit0 == rCrCit0);
1157 BEAST_EXPECT(rCrCit1 == rNrNit1);
1158
1159 // Should be able to construct or assign a const_reverse_iterator from a
1160 // reverse_iterator
1161 const_reverse_iterator const rNrCit0{c.rbegin()};
1162 const_reverse_iterator const rNrCit1{rNrNit0};
1163 BEAST_EXPECT(rNrCit0 == rNrCit1);
1164 xXrCit2 = rNrNit1;
1165 BEAST_EXPECT(rNrCit1 == xXrCit2);
1166
1167 // The standard allows these conversions:
1168 // o reverse_iterator is explicitly constructible from iterator.
1169 // o const_reverse_iterator is explicitly constructible from
1170 // const_iterator.
1171 // Should be able to construct or assign reverse_iterators from
1172 // non-reverse iterators.
1173 reverse_iterator const fNrNit0{c.begin()};
1174 const_reverse_iterator const fNrCit0{c.begin()};
1175 BEAST_EXPECT(fNrNit0 == fNrCit0);
1176 const_reverse_iterator const fCrCit0{c.cbegin()};
1177 BEAST_EXPECT(fNrCit0 == fCrCit0);
1178
1179 // None of these should compile because they construct a non-reverse
1180 // iterator from a reverse_iterator.
1181 // iterator rNfNit_0 {c.rbegin()};
1182 // const_iterator rNfCit_0 {c.rbegin()};
1183 // const_iterator rCfCit_0 {c.crbegin()};
1184
1185 // You should not be able to assign an iterator to a reverse_iterator or
1186 // vise-versa. So the following lines should not compile.
1187 iterator const xXfNit0;
1188 // xXfNit_0 = xXrNit_2;
1189 // xXrNit_2 = xXfNit_0;
1190}
1191
1192//------------------------------------------------------------------------------
1193//
1194// Modifiers
1195//
1196//------------------------------------------------------------------------------
1197
1198template <class Container, class Values>
1199void
1201{
1202 for (auto const& e : v)
1203 c.insert(e);
1204 checkContents(c, v);
1205}
1206
1207template <class Container, class Values>
1208void
1210{
1211 Values v2(v);
1212 for (auto& e : v2)
1213 c.insert(std::move(e));
1214 checkContents(c, v);
1215}
1216
1217template <class Container, class Values>
1218void
1220{
1221 for (auto const& e : v)
1222 c.insert(c.cend(), e);
1223 checkContents(c, v);
1224}
1225
1226template <class Container, class Values>
1227void
1229{
1230 Values v2(v);
1231 for (auto& e : v2)
1232 c.insert(c.cend(), std::move(e));
1233 checkContents(c, v);
1234}
1235
1236template <class Container, class Values>
1237void
1239{
1240 for (auto const& e : v)
1241 c.emplace(e);
1242 checkContents(c, v);
1243}
1244
1245template <class Container, class Values>
1246void
1248{
1249 for (auto const& e : v)
1250 c.emplace_hint(c.cend(), e);
1251 checkContents(c, v);
1252}
1253
1254template <bool IsUnordered, bool IsMulti, bool IsMap>
1255void
1257{
1259 typename Traits::ManualClock clock;
1260 auto const v(Traits::values());
1261 auto const l(makeList(v));
1262
1263 // testcase (Traits::name() + " modify");
1264 testcase("modify");
1265
1266 {
1267 typename Traits::template Cont<> c(clock);
1268 checkInsertCopy(c, v);
1269 }
1270
1271 {
1272 typename Traits::template Cont<> c(clock);
1273 checkInsertCopy(c, l);
1274 }
1275
1276 {
1277 typename Traits::template Cont<> c(clock);
1278 checkInsertMove(c, v);
1279 }
1280
1281 {
1282 typename Traits::template Cont<> c(clock);
1283 checkInsertMove(c, l);
1284 }
1285
1286 {
1287 typename Traits::template Cont<> c(clock);
1288 checkInsertHintCopy(c, v);
1289 }
1290
1291 {
1292 typename Traits::template Cont<> c(clock);
1293 checkInsertHintCopy(c, l);
1294 }
1295
1296 {
1297 typename Traits::template Cont<> c(clock);
1298 checkInsertHintMove(c, v);
1299 }
1300
1301 {
1302 typename Traits::template Cont<> c(clock);
1303 checkInsertHintMove(c, l);
1304 }
1305}
1306
1307//------------------------------------------------------------------------------
1308//
1309// Chronological ordering
1310//
1311//------------------------------------------------------------------------------
1312
1313template <bool IsUnordered, bool IsMulti, bool IsMap>
1314void
1316{
1318 typename Traits::ManualClock clock;
1319 auto const v(Traits::values());
1320
1321 // testcase (Traits::name() + " chronological");
1322 testcase("chronological");
1323
1324 typename Traits::template Cont<> c(v.begin(), v.end(), clock);
1325
1326 BEAST_EXPECT(std::ranges::equal(c.chronological, v, EqualValue<Traits>()));
1327
1328 // Test touch() with a non-const iterator.
1329 for (auto iter(v.crbegin()); iter != v.crend(); ++iter)
1330 {
1331 using iterator = decltype(c)::iterator;
1332 iterator const found(c.find(Traits::extract(*iter)));
1333
1334 BEAST_EXPECT(found != c.cend());
1335 if (found == c.cend())
1336 return;
1337 c.touch(found);
1338 }
1339
1340 BEAST_EXPECT(
1341 std::equal(
1342 c.chronological.cbegin(),
1343 c.chronological.cend(),
1344 v.crbegin(),
1345 v.crend(),
1347
1348 // Test touch() with a const_iterator
1349 for (auto iter(v.cbegin()); iter != v.cend(); ++iter)
1350 {
1351 using const_iterator = decltype(c)::const_iterator;
1352 const_iterator const found(c.find(Traits::extract(*iter)));
1353
1354 BEAST_EXPECT(found != c.cend());
1355 if (found == c.cend())
1356 return;
1357 c.touch(found);
1358 }
1359
1360 BEAST_EXPECT(std::ranges::equal(c.chronological, v, EqualValue<Traits>()));
1361
1362 {
1363 // Because touch (reverse_iterator pos) is not allowed, the following
1364 // lines should not compile for any aged_container type.
1365 // c.touch (c.rbegin());
1366 // c.touch (c.crbegin());
1367 }
1368}
1369
1370//------------------------------------------------------------------------------
1371//
1372// Element creation via operator[]
1373//
1374//------------------------------------------------------------------------------
1375
1376// map, unordered_map
1377template <bool IsUnordered, bool IsMulti, bool IsMap>
1378void
1380 requires(IsMap && !IsMulti)
1381{
1383 typename Traits::ManualClock clock;
1384 auto v(Traits::values());
1385
1386 // testcase (Traits::name() + " array create");
1387 testcase("array create");
1388
1389 {
1390 // Copy construct key
1391 typename Traits::template Cont<> c(clock);
1392 for (auto const& e : v)
1393 c[e.first] = e.second;
1394 checkContents(c, v);
1395 }
1396
1397 {
1398 // Move construct key
1399 typename Traits::template Cont<> c(clock);
1400 for (auto e : v)
1401 c[std::move(e.first)] = e.second;
1402 checkContents(c, v);
1403 }
1404}
1405
1406//------------------------------------------------------------------------------
1407//
1408// Helpers for erase tests
1409//
1410//------------------------------------------------------------------------------
1411
1412template <class Container, class Values>
1413void
1415{
1416 // Just in case the passed in container was not empty.
1417 c.clear();
1418
1419 // c.clock() returns an abstract_clock, so dynamic_cast to ManualClock.
1420 // VFALCO NOTE This is sketchy
1422 auto& clk = dynamic_cast<ManualClock&>(c.clock());
1423 clk.set(0);
1424
1425 Values rev(values);
1426 std::ranges::sort(rev);
1428 for (auto& v : rev)
1429 {
1430 // Add values in reverse order so they are reversed chronologically.
1431 ++clk;
1432 c.insert(v);
1433 }
1434}
1435
1436// Get one iterator before endIter. We have to use operator++ because you
1437// cannot use operator-- with unordered container iterators.
1438template <class Iter>
1439Iter
1440AgedAssociativeContainerTestBase::nextToEndIter(Iter beginIter, Iter const endIter)
1441{
1442 if (beginIter == endIter)
1443 {
1444 fail("Internal test failure. Cannot advance beginIter");
1445 return beginIter;
1446 }
1447
1448 //
1449 Iter nextToEnd = beginIter;
1450 do
1451 {
1452 nextToEnd = beginIter++;
1453 } while (beginIter != endIter);
1454 return nextToEnd;
1455}
1456
1457// Implementation for the element erase tests
1458//
1459// This test accepts:
1460// o the container from which we will erase elements
1461// o iterators into that container defining the range of the erase
1462//
1463// This implementation does not declare a pass, since it wants to allow
1464// the caller to examine the size of the container and the returned iterator
1465//
1466// Note that this test works on the aged_associative containers because an
1467// erase only invalidates references and iterators to the erased element
1468// (see 23.2.4/13). Therefore the passed-in end iterator stays valid through
1469// the whole test.
1470template <class Container, class Iter>
1471bool
1473 Container& c,
1474 Iter const beginItr,
1475 Iter const endItr)
1476{
1477 auto it(beginItr);
1478 size_t count = c.size();
1479 while (it != endItr)
1480 {
1481 auto expectIt = it;
1482 ++expectIt;
1483 it = c.erase(it);
1484
1485 if (it != expectIt)
1486 {
1487 fail("Unexpected returned iterator from element erase");
1488 return false;
1489 }
1490
1491 --count;
1492 if (count != c.size())
1493 {
1494 fail("Failed to erase element");
1495 return false;
1496 }
1497
1498 if (c.empty())
1499 {
1500 if (it != endItr)
1501 {
1502 fail("Erase of last element didn't produce end");
1503 return false;
1504 }
1505 }
1506 }
1507 return true;
1508}
1509
1510//------------------------------------------------------------------------------
1511//
1512// Erase of individual elements
1513//
1514//------------------------------------------------------------------------------
1515
1516template <bool IsUnordered, bool IsMulti, bool IsMap>
1517void
1519{
1521
1522 // testcase (Traits::name() + " element erase"
1523 testcase("element erase");
1524
1525 // Make and fill the container
1526 typename Traits::ManualClock clock;
1527 typename Traits::template Cont<> c{clock};
1528 reverseFillAgedContainer(c, Traits::values());
1529
1530 {
1531 // Test standard iterators
1532 auto tempContainer(c);
1533 if (!doElementErase(tempContainer, tempContainer.cbegin(), tempContainer.cend()))
1534 return; // Test failed
1535
1536 BEAST_EXPECT(tempContainer.empty());
1537 pass();
1538 }
1539 {
1540 // Test chronological iterators
1541 auto tempContainer(c);
1542 auto& chron(tempContainer.chronological);
1543 if (!doElementErase(tempContainer, chron.begin(), chron.end()))
1544 return; // Test failed
1545
1546 BEAST_EXPECT(tempContainer.empty());
1547 pass();
1548 }
1549 {
1550 // Test standard iterator partial erase
1551 auto tempContainer(c);
1552 BEAST_EXPECT(tempContainer.size() > 2);
1553 if (!doElementErase(
1554 tempContainer,
1555 ++tempContainer.begin(),
1556 nextToEndIter(tempContainer.begin(), tempContainer.end())))
1557 return; // Test failed
1558
1559 BEAST_EXPECT(tempContainer.size() == 2);
1560 pass();
1561 }
1562 {
1563 // Test chronological iterator partial erase
1564 auto tempContainer(c);
1565 BEAST_EXPECT(tempContainer.size() > 2);
1566 auto& chron(tempContainer.chronological);
1567 if (!doElementErase(
1568 tempContainer, ++chron.begin(), nextToEndIter(chron.begin(), chron.end())))
1569 return; // Test failed
1570
1571 BEAST_EXPECT(tempContainer.size() == 2);
1572 pass();
1573 }
1574 {
1575 auto tempContainer(c);
1576 BEAST_EXPECT(tempContainer.size() > 4);
1577 // erase(reverse_iterator) is not allowed. None of the following
1578 // should compile for any aged_container type.
1579 // c.erase (c.rbegin());
1580 // c.erase (c.crbegin());
1581 // c.erase(c.rbegin(), ++c.rbegin());
1582 // c.erase(c.crbegin(), ++c.crbegin());
1583 }
1584}
1585
1586// Implementation for the range erase tests
1587//
1588// This test accepts:
1589//
1590// o A container with more than 2 elements and
1591// o An object to ask for begin() and end() iterators in the passed container
1592//
1593// This peculiar interface allows either the container itself to be passed as
1594// the second argument or the container's "chronological" element. Both
1595// sources of iterators need to be tested on the container.
1596//
1597// The test locates iterators such that a range-based delete leaves the first
1598// and last elements in the container. It then validates that the container
1599// ended up with the expected contents.
1600//
1601template <class Container, class BeginEndSrc>
1602void
1603AgedAssociativeContainerTestBase::doRangeErase(Container& c, BeginEndSrc const& beginEndSrc)
1604{
1605 BEAST_EXPECT(c.size() > 2);
1606 auto itBeginPlusOne(beginEndSrc.begin());
1607 auto const valueFront = *itBeginPlusOne;
1608 ++itBeginPlusOne;
1609
1610 // Get one iterator before end()
1611 auto itBack(nextToEndIter(itBeginPlusOne, beginEndSrc.end()));
1612 auto const valueBack = *itBack;
1613
1614 // Erase all elements but first and last
1615 auto const retIter = c.erase(itBeginPlusOne, itBack);
1616
1617 BEAST_EXPECT(c.size() == 2);
1618 BEAST_EXPECT(valueFront == *(beginEndSrc.begin()));
1619 BEAST_EXPECT(valueBack == *(++beginEndSrc.begin()));
1620 BEAST_EXPECT(retIter == (++beginEndSrc.begin()));
1621}
1622
1623//------------------------------------------------------------------------------
1624//
1625// Erase range of elements
1626//
1627//------------------------------------------------------------------------------
1628
1629template <bool IsUnordered, bool IsMulti, bool IsMap>
1630void
1632{
1634
1635 // testcase (Traits::name() + " element erase"
1636 testcase("range erase");
1637
1638 // Make and fill the container
1639 typename Traits::ManualClock clock;
1640 typename Traits::template Cont<> c{clock};
1641 reverseFillAgedContainer(c, Traits::values());
1642
1643 // Not bothering to test range erase with reverse iterators.
1644 {
1645 auto tempContainer(c);
1646 doRangeErase(tempContainer, tempContainer);
1647 }
1648 {
1649 auto tempContainer(c);
1650 doRangeErase(tempContainer, tempContainer.chronological);
1651 }
1652}
1653
1654//------------------------------------------------------------------------------
1655//
1656// Container-wide comparison
1657//
1658//------------------------------------------------------------------------------
1659
1660// ordered
1661template <bool IsUnordered, bool IsMulti, bool IsMap>
1662void
1664 requires(!IsUnordered)
1665{
1667 typename Traits::ManualClock clock;
1668 auto const v(Traits::values());
1669
1670 // testcase (Traits::name() + " array create");
1671 testcase("array create");
1672
1673 typename Traits::template Cont<> const c1(v.begin(), v.end(), clock);
1674
1675 typename Traits::template Cont<> c2(v.begin(), v.end(), clock);
1676 c2.erase(c2.cbegin());
1677
1678 expect(c1 != c2);
1679 unexpected(c1 == c2);
1680 expect(c1 < c2);
1681 expect(c1 <= c2);
1682 unexpected(c1 > c2);
1683 unexpected(c1 >= c2);
1684}
1685
1686//------------------------------------------------------------------------------
1687//
1688// Observers
1689//
1690//------------------------------------------------------------------------------
1691
1692// ordered
1693template <bool IsUnordered, bool IsMulti, bool IsMap>
1694void
1696 requires(!IsUnordered)
1697{
1699 typename Traits::ManualClock clock;
1700
1701 // testcase (Traits::name() + " observers");
1702 testcase("observers");
1703
1704 typename Traits::template Cont<> const c(clock);
1705 c.keyComp();
1706 c.valueComp();
1707
1708 pass();
1709}
1710
1711// unordered
1712template <bool IsUnordered, bool IsMulti, bool IsMap>
1713void
1715 requires IsUnordered
1716{
1717 using Traits = TestTraits<IsUnordered, IsMulti, IsMap>;
1718 typename Traits::ManualClock clock;
1719
1720 // testcase (Traits::name() + " observers");
1721 testcase("observers");
1722
1723 typename Traits::template Cont<> const c(clock);
1724 c.hashFunction();
1725 c.keyEq();
1726
1727 pass();
1728}
1729
1730//------------------------------------------------------------------------------
1731//
1732// Matrix
1733//
1734//------------------------------------------------------------------------------
1735
1736template <bool IsUnordered, bool IsMulti, bool IsMap>
1737void
1754
1755//------------------------------------------------------------------------------
1756
1758{
1759public:
1760 // Compile time checks
1761
1763 using T = int;
1764
1765 static_assert(
1767 "bad alias: aged_set");
1768
1769 static_assert(
1771 "bad alias: aged_multiset");
1772
1773 static_assert(
1775 "bad alias: aged_map");
1776
1777 static_assert(
1779 "bad alias: aged_multimap");
1780
1781 static_assert(
1785 "bad alias: aged_unordered_set");
1786
1787 static_assert(
1791 "bad alias: aged_unordered_multiset");
1792
1793 static_assert(
1797 "bad alias: aged_unordered_map");
1798
1799 static_assert(
1803 "bad alias: aged_unordered_multimap");
1804
1805 void
1810};
1811
1813{
1814public:
1815 void
1816 run() override
1817 {
1819 }
1820};
1821
1823{
1824public:
1825 void
1826 run() override
1827 {
1829 }
1830};
1831
1833{
1834public:
1835 void
1836 run() override
1837 {
1839 }
1840};
1841
1843{
1844public:
1845 void
1846 run() override
1847 {
1849 }
1850};
1851
1853{
1854public:
1855 void
1856 run() override
1857 {
1859 }
1860};
1861
1863{
1864public:
1865 void
1866 run() override
1867 {
1869 }
1870};
1871
1873{
1874public:
1875 void
1876 run() override
1877 {
1879 }
1880};
1881
1890
1891} // namespace beast
void reverseFillAgedContainer(Container &c, Values const &v)
bool doElementErase(Container &c, Iter const beginItr, Iter const endItr)
void doRangeErase(Container &c, BeginEndSrc const &beginEndSrc)
static std::vector< typename Cont::value_type > makeList(Cont const &c)
Iter nextToEndIter(Iter const beginIter, Iter const endItr)
Manual clock implementation.
void set(time_point const &when)
Set the current time of the manual clock.
void run() override
Runs the suite.
void run() override
Runs the suite.
Associative container where each element is also indexed by time.
Associative container where each element is also indexed by time.
A testsuite class.
Definition suite.h:52
bool unexpected(Condition shouldBeFalse, String const &reason)
DEPRECATED.
Definition suite.h:516
void pass()
Record a successful test condition.
Definition suite.h:532
bool expect(Condition const &shouldBeTrue)
Evaluate a test condition.
Definition suite.h:235
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:554
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:155
T distance(T... args)
T equal(T... args)
T find_if(T... args)
T is_same_v
T make_pair(T... args)
detail::AgedOrderedContainer< false, false, Key, void, Clock, Compare, Allocator > aged_set
Definition aged_set.h:16
detail::AgedUnorderedContainer< true, true, Key, T, Clock, Hash, KeyEqual, Allocator > aged_unordered_multimap
detail::AgedUnorderedContainer< false, false, Key, void, Clock, Hash, KeyEqual, Allocator > aged_unordered_set
detail::AgedUnorderedContainer< true, false, Key, void, Clock, Hash, KeyEqual, Allocator > aged_unordered_multiset
detail::AgedOrderedContainer< true, true, Key, T, Clock, Compare, Allocator > aged_multimap
detail::AgedUnorderedContainer< false, true, Key, T, Clock, Hash, KeyEqual, Allocator > aged_unordered_map
detail::AgedOrderedContainer< true, false, Key, void, Clock, Compare, Allocator > aged_multiset
BEAST_DEFINE_TESTSUITE(aged_set, beast, beast)
detail::AgedOrderedContainer< false, true, Key, T, Clock, Compare, Allocator > aged_map
Definition aged_map.h:18
T reverse(T... args)
T sort(T... args)
detail::AgedUnorderedContainer< Base::is_multi::value, Base::is_map::value, typename Base::Key, typename Base::T, typename Base::Clock, Hash, KeyEqual, Allocator > Cont
detail::AgedOrderedContainer< Base::is_multi::value, Base::is_map::value, typename Base::Key, typename Base::T, typename Base::Clock, Compare, Allocator > Cont
bool operator()(Traits::Value const &lhs, Traits::Value const &rhs)
MaybeUnordered< MaybeMulti< MaybeMap< TestTraitsBase, IsMap >, IsMulti >, IsUnordered > Base
T swap(T... args)