rippled
Loading...
Searching...
No Matches
aged_ordered_container.h
1#pragma once
2
3#include <xrpl/beast/clock/abstract_clock.h>
4#include <xrpl/beast/container/aged_container.h>
5#include <xrpl/beast/container/detail/aged_associative_container.h>
6#include <xrpl/beast/container/detail/aged_container_iterator.h>
7#include <xrpl/beast/container/detail/empty_base_optimization.h>
8
9#include <boost/intrusive/list.hpp>
10#include <boost/intrusive/set.hpp>
11#include <boost/version.hpp>
12
13#include <algorithm>
14#include <functional>
15#include <initializer_list>
16#include <memory>
17#include <type_traits>
18#include <utility>
19
20namespace beast {
21namespace detail {
22
23// Traits templates used to discern reverse_iterators, which are disallowed
24// for mutating operations.
25template <class It>
30
31template <class It>
32struct is_boost_reverse_iterator<boost::intrusive::reverse_iterator<It>> : std::true_type
33{
34 explicit is_boost_reverse_iterator() = default;
35};
36
53template <
54 bool IsMulti,
55 bool IsMap,
56 class Key,
57 class T,
58 class Clock = std::chrono::steady_clock,
59 class Compare = std::less<Key>,
60 class Allocator =
63{
64public:
68 using key_type = Key;
69 using mapped_type = T;
73
74 // Introspection (for unit tests)
78
79private:
80 static Key const&
81 extract(value_type const& value)
82 {
84 }
85
86 // VFALCO TODO hoist to remove template argument dependencies
87 struct element : boost::intrusive::set_base_hook<
88 boost::intrusive::link_mode<boost::intrusive::normal_link>>,
89 boost::intrusive::list_base_hook<
90 boost::intrusive::link_mode<boost::intrusive::normal_link>>
91 {
92 // Stash types here so the iterator doesn't
93 // need to see the container declaration.
94 struct stashed
95 {
96 explicit stashed() = default;
97
100 };
101
102 element(time_point const& when_, value_type const& value_) : value(value_), when(when_)
103 {
104 }
105
106 element(time_point const& when_, value_type&& value_)
107 : value(std::move(value_)), when(when_)
108 {
109 }
110
111 template <
112 class... Args,
113 class =
115 element(time_point const& when_, Args&&... args)
116 : value(std::forward<Args>(args)...), when(when_)
117 {
118 }
119
122 };
123
124 // VFALCO TODO This should only be enabled for maps.
125 class pair_value_compare : public Compare
126 {
127 public:
130 using result_type = bool;
131
132 bool
133 operator()(value_type const& lhs, value_type const& rhs) const
134 {
135 return Compare::operator()(lhs.first, rhs.first);
136 }
137
139 {
140 }
141
142 pair_value_compare(pair_value_compare const& other) : Compare(other)
143 {
144 }
145
146 private:
148
149 pair_value_compare(Compare const& compare) : Compare(compare)
150 {
151 }
152 };
153
154 // Compares value_type against element, used in insert_check
155 // VFALCO TODO hoist to remove template argument dependencies
156 class KeyValueCompare : public Compare
157 {
158 public:
159 using first_argument = Key;
161 using result_type = bool;
162
163 KeyValueCompare() = default;
164
165 KeyValueCompare(Compare const& compare) : Compare(compare)
166 {
167 }
168
169 bool
170 operator()(Key const& k, element const& e) const
171 {
172 return Compare::operator()(k, extract(e.value));
173 }
174
175 bool
176 operator()(element const& e, Key const& k) const
177 {
178 return Compare::operator()(extract(e.value), k);
179 }
180
181 bool
182 operator()(element const& x, element const& y) const
183 {
184 return Compare::operator()(extract(x.value), extract(y.value));
185 }
186
187 Compare&
189 {
190 return *this;
191 }
192
193 Compare const&
194 compare() const
195 {
196 return *this;
197 }
198 };
199
200 using list_type = typename boost::intrusive::
201 make_list<element, boost::intrusive::constant_time_size<false>>::type;
202
203 using cont_type = typename std::conditional<
204 IsMulti,
205 typename boost::intrusive::make_multiset<
206 element,
207 boost::intrusive::constant_time_size<true>,
208 boost::intrusive::compare<KeyValueCompare>>::type,
209 typename boost::intrusive::make_set<
210 element,
211 boost::intrusive::constant_time_size<true>,
212 boost::intrusive::compare<KeyValueCompare>>::type>::type;
213
215 typename std::allocator_traits<Allocator>::template rebind_alloc<element>;
216
218
219 class config_t : private KeyValueCompare,
220 public beast::detail::empty_base_optimization<ElementAllocator>
221 {
222 public:
223 explicit config_t(clock_type& clock_) : clock(clock_)
224 {
225 }
226
227 config_t(clock_type& clock_, Compare const& comp) : KeyValueCompare(comp), clock(clock_)
228 {
229 }
230
231 config_t(clock_type& clock_, Allocator const& alloc_)
232 : beast::detail::empty_base_optimization<ElementAllocator>(alloc_), clock(clock_)
233 {
234 }
235
236 config_t(clock_type& clock_, Compare const& comp, Allocator const& alloc_)
237 : KeyValueCompare(comp)
239 , clock(clock_)
240 {
241 }
242
243 config_t(config_t const& other)
246 ElementAllocatorTraits::select_on_container_copy_construction(other.alloc()))
247 , clock(other.clock)
248 {
249 }
250
251 config_t(config_t const& other, Allocator const& alloc)
254 , clock(other.clock)
255 {
256 }
257
259 : KeyValueCompare(std::move(other.key_compare()))
260 , beast::detail::empty_base_optimization<ElementAllocator>(std::move(other))
261 , clock(other.clock)
262 {
263 }
264
266 config_t&& other, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
267 Allocator const& alloc)
268 : KeyValueCompare(std::move(other.key_compare()))
270 , clock(other.clock)
271 {
272 }
273
274 config_t&
275 operator=(config_t const& other)
276 {
277 if (this != &other)
278 {
279 compare() = other.compare();
280 alloc() = other.alloc();
281 clock = other.clock;
282 }
283 return *this;
284 }
285
286 config_t&
288 {
289 compare() = std::move(other.compare());
290 alloc() = std::move(other.alloc());
291 clock = other.clock;
292 return *this;
293 }
294
295 Compare&
297 {
299 }
300
301 Compare const&
302 compare() const
303 {
305 }
306
309 {
310 return *this;
311 }
312
313 KeyValueCompare const&
315 {
316 return *this;
317 }
318
324
325 ElementAllocator const&
330
332 };
333
334 template <class... Args>
335 element*
336 new_element(Args&&... args)
337 {
338 struct Deleter
339 {
341 Deleter(ElementAllocator& a) : a_(a)
342 {
343 }
344
345 void
346 operator()(element* p)
347 {
348 ElementAllocatorTraits::deallocate(a_.get(), p, 1);
349 }
350 };
351
355 m_config.alloc(), p.get(), clock().now(), std::forward<Args>(args)...);
356 return p.release();
357 }
358
359 void
365
366 void
368 {
369 chronological.list.erase(chronological.list.iterator_to(*p));
370 m_cont.erase(m_cont.iterator_to(*p));
372 }
373
374public:
375 using key_compare = Compare;
377 using allocator_type = Allocator;
382
383 // A set iterator (IsMap==false) is always const
384 // because the elements of a set are immutable.
392
393 //--------------------------------------------------------------------------
394 //
395 // Chronological ordered iterators
396 //
397 // "Memberspace"
398 // http://accu.org/index.php/journals/1527
399 //
400 //--------------------------------------------------------------------------
401
403 {
404 public:
405 // A set iterator (IsMap==false) is always const
406 // because the elements of a set are immutable.
407 using iterator =
415
418 {
419 return iterator(list.begin());
420 }
421
423 begin() const
424 {
425 return const_iterator(list.begin());
426 }
427
429 cbegin() const
430 {
431 return const_iterator(list.begin());
432 }
433
436 {
437 return iterator(list.end());
438 }
439
441 end() const
442 {
443 return const_iterator(list.end());
444 }
445
447 cend() const
448 {
449 return const_iterator(list.end());
450 }
451
454 {
455 return reverse_iterator(list.rbegin());
456 }
457
459 rbegin() const
460 {
461 return const_reverse_iterator(list.rbegin());
462 }
463
465 crbegin() const
466 {
467 return const_reverse_iterator(list.rbegin());
468 }
469
472 {
473 return reverse_iterator(list.rend());
474 }
475
477 rend() const
478 {
479 return const_reverse_iterator(list.rend());
480 }
481
483 crend() const
484 {
485 return const_reverse_iterator(list.rend());
486 }
487
490 {
491 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
492 return list.iterator_to(*reinterpret_cast<element*>(
493 reinterpret_cast<uint8_t*>(&value) -
494 ((std::size_t)std::addressof(((element*)0)->member))));
495 }
496
498 iterator_to(value_type const& value) const
499 {
500 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
501 return list.iterator_to(*reinterpret_cast<element const*>(
502 reinterpret_cast<uint8_t const*>(&value) -
503 ((std::size_t)std::addressof(((element*)0)->member))));
504 }
505
506 private:
508 {
509 }
510
513
517
518 //--------------------------------------------------------------------------
519 //
520 // Construction
521 //
522 //--------------------------------------------------------------------------
523
525
527
529
530 aged_ordered_container(clock_type& clock, Allocator const& alloc);
531
532 aged_ordered_container(clock_type& clock, Compare const& comp, Allocator const& alloc);
533
534 template <class InputIt>
535 aged_ordered_container(InputIt first, InputIt last, clock_type& clock);
536
537 template <class InputIt>
538 aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Compare const& comp);
539
540 template <class InputIt>
541 aged_ordered_container(InputIt first, InputIt last, clock_type& clock, Allocator const& alloc);
542
543 template <class InputIt>
545 InputIt first,
546 InputIt last,
548 Compare const& comp,
549 Allocator const& alloc);
550
552
553 aged_ordered_container(aged_ordered_container const& other, Allocator const& alloc);
554
556
558 // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
560 Allocator const& alloc);
561
563
567 Compare const& comp);
568
572 Allocator const& alloc);
573
577 Compare const& comp,
578 Allocator const& alloc);
579
581
584
587
590
593 {
594 return m_config.alloc();
595 }
596
599 {
600 return m_config.clock;
601 }
602
603 clock_type const&
604 clock() const
605 {
606 return m_config.clock;
607 }
608
609 //--------------------------------------------------------------------------
610 //
611 // Element access (maps)
612 //
613 //--------------------------------------------------------------------------
614
615 template <
616 class K,
617 bool maybe_multi = IsMulti,
618 bool maybe_map = IsMap,
621 at(K const& k);
622
623 template <
624 class K,
625 bool maybe_multi = IsMulti,
626 bool maybe_map = IsMap,
629 at(K const& k) const;
630
631 template <
632 bool maybe_multi = IsMulti,
633 bool maybe_map = IsMap,
636 operator[](Key const& key);
637
638 template <
639 bool maybe_multi = IsMulti,
640 bool maybe_map = IsMap,
643 operator[](Key&& key);
644
645 //--------------------------------------------------------------------------
646 //
647 // Iterators
648 //
649 //--------------------------------------------------------------------------
650
653 {
654 return iterator(m_cont.begin());
655 }
656
658 begin() const
659 {
660 return const_iterator(m_cont.begin());
661 }
662
664 cbegin() const
665 {
666 return const_iterator(m_cont.begin());
667 }
668
671 {
672 return iterator(m_cont.end());
673 }
674
676 end() const
677 {
678 return const_iterator(m_cont.end());
679 }
680
682 cend() const
683 {
684 return const_iterator(m_cont.end());
685 }
686
689 {
690 return reverse_iterator(m_cont.rbegin());
691 }
692
694 rbegin() const
695 {
696 return const_reverse_iterator(m_cont.rbegin());
697 }
698
700 crbegin() const
701 {
702 return const_reverse_iterator(m_cont.rbegin());
703 }
704
707 {
708 return reverse_iterator(m_cont.rend());
709 }
710
712 rend() const
713 {
714 return const_reverse_iterator(m_cont.rend());
715 }
716
718 crend() const
719 {
720 return const_reverse_iterator(m_cont.rend());
721 }
722
725 {
726 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
727 return m_cont.iterator_to(*reinterpret_cast<element*>(
728 reinterpret_cast<uint8_t*>(&value) -
729 ((std::size_t)std::addressof(((element*)0)->member))));
730 }
731
733 iterator_to(value_type const& value) const
734 {
735 static_assert(std::is_standard_layout<element>::value, "must be standard layout");
736 return m_cont.iterator_to(*reinterpret_cast<element const*>(
737 reinterpret_cast<uint8_t const*>(&value) -
738 ((std::size_t)std::addressof(((element*)0)->member))));
739 }
740
741 //--------------------------------------------------------------------------
742 //
743 // Capacity
744 //
745 //--------------------------------------------------------------------------
746
747 bool
748 empty() const noexcept
749 {
750 return m_cont.empty();
751 }
752
754 size() const noexcept
755 {
756 return m_cont.size();
757 }
758
760 max_size() const noexcept
761 {
762 return m_config.max_size();
763 }
764
765 //--------------------------------------------------------------------------
766 //
767 // Modifiers
768 //
769 //--------------------------------------------------------------------------
770
771 void
773
774 // map, set
775 template <bool maybe_multi = IsMulti>
776 auto
777 insert(value_type const& value) ->
779
780 // multimap, multiset
781 template <bool maybe_multi = IsMulti>
782 auto
784
785 // set
786 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
787 auto
788 insert(value_type&& value) ->
790
791 // multiset
792 template <bool maybe_multi = IsMulti, bool maybe_map = IsMap>
793 auto
794 insert(value_type&& value) ->
796
797 //---
798
799 // map, set
800 template <bool maybe_multi = IsMulti>
801 auto
802 insert(const_iterator hint, value_type const& value) ->
804
805 // multimap, multiset
806 template <bool maybe_multi = IsMulti>
808 insert(const_iterator /*hint*/, value_type const& value)
809 {
810 // VFALCO TODO Figure out how to utilize 'hint'
811 return insert(value);
812 }
813
814 // map, set
815 template <bool maybe_multi = IsMulti>
816 auto
819
820 // multimap, multiset
821 template <bool maybe_multi = IsMulti>
824 {
825 // VFALCO TODO Figure out how to utilize 'hint'
826 return insert(std::move(value));
827 }
828
829 // map, multimap
830 template <class P, bool maybe_map = IsMap>
831 typename std::enable_if<
834 insert(P&& value)
835 {
836 return emplace(std::forward<P>(value));
837 }
838
839 // map, multimap
840 template <class P, bool maybe_map = IsMap>
841 typename std::enable_if<
844 insert(const_iterator hint, P&& value)
845 {
846 return emplace_hint(hint, std::forward<P>(value));
847 }
848
849 template <class InputIt>
850 void
851 insert(InputIt first, InputIt last)
852 {
853 for (; first != last; ++first)
854 insert(cend(), *first);
855 }
856
857 void
859 {
860 insert(init.begin(), init.end());
861 }
862
863 // map, set
864 template <bool maybe_multi = IsMulti, class... Args>
865 auto
866 emplace(Args&&... args) ->
868
869 // multiset, multimap
870 template <bool maybe_multi = IsMulti, class... Args>
871 auto
873
874 // map, set
875 template <bool maybe_multi = IsMulti, class... Args>
876 auto
877 emplace_hint(const_iterator hint, Args&&... args) ->
879
880 // multiset, multimap
881 template <bool maybe_multi = IsMulti, class... Args>
883 emplace_hint(const_iterator /*hint*/, Args&&... args)
884 {
885 // VFALCO TODO Figure out how to utilize 'hint'
886 return emplace<maybe_multi>(std::forward<Args>(args)...);
887 }
888
889 // enable_if prevents erase (reverse_iterator pos) from compiling
890 template <
891 bool is_const,
892 class Iterator,
896
897 // enable_if prevents erase (reverse_iterator first, reverse_iterator last)
898 // from compiling
899 template <
900 bool is_const,
901 class Iterator,
907
908 template <class K>
909 auto
910 erase(K const& k) -> size_type;
911
912 void
913 swap(aged_ordered_container& other) noexcept;
914
915 //--------------------------------------------------------------------------
916
917 // enable_if prevents touch (reverse_iterator pos) from compiling
918 template <
919 bool is_const,
920 class Iterator,
922 void
927
928 template <class K>
930 touch(K const& k);
931
932 //--------------------------------------------------------------------------
933 //
934 // Lookup
935 //
936 //--------------------------------------------------------------------------
937
938 // VFALCO TODO Respect is_transparent (c++14)
939 template <class K>
941 count(K const& k) const
942 {
943 return m_cont.count(k, std::cref(m_config.key_compare()));
944 }
945
946 // VFALCO TODO Respect is_transparent (c++14)
947 template <class K>
949 find(K const& k)
950 {
951 return iterator(m_cont.find(k, std::cref(m_config.key_compare())));
952 }
953
954 // VFALCO TODO Respect is_transparent (c++14)
955 template <class K>
957 find(K const& k) const
958 {
960 }
961
962 // VFALCO TODO Respect is_transparent (c++14)
963 template <class K>
965 equal_range(K const& k)
966 {
967 auto const r(m_cont.equal_range(k, std::cref(m_config.key_compare())));
968 return std::make_pair(iterator(r.first), iterator(r.second));
969 }
970
971 // VFALCO TODO Respect is_transparent (c++14)
972 template <class K>
974 equal_range(K const& k) const
975 {
976 auto const r(m_cont.equal_range(k, std::cref(m_config.key_compare())));
977 return std::make_pair(const_iterator(r.first), const_iterator(r.second));
978 }
979
980 // VFALCO TODO Respect is_transparent (c++14)
981 template <class K>
983 lower_bound(K const& k)
984 {
985 return iterator(m_cont.lower_bound(k, std::cref(m_config.key_compare())));
986 }
987
988 // VFALCO TODO Respect is_transparent (c++14)
989 template <class K>
991 lower_bound(K const& k) const
992 {
993 return const_iterator(m_cont.lower_bound(k, std::cref(m_config.key_compare())));
994 }
995
996 // VFALCO TODO Respect is_transparent (c++14)
997 template <class K>
999 upper_bound(K const& k)
1000 {
1001 return iterator(m_cont.upper_bound(k, std::cref(m_config.key_compare())));
1002 }
1003
1004 // VFALCO TODO Respect is_transparent (c++14)
1005 template <class K>
1007 upper_bound(K const& k) const
1008 {
1009 return const_iterator(m_cont.upper_bound(k, std::cref(m_config.key_compare())));
1010 }
1011
1012 //--------------------------------------------------------------------------
1013 //
1014 // Observers
1015 //
1016 //--------------------------------------------------------------------------
1017
1019 key_comp() const
1020 {
1021 return m_config.compare();
1022 }
1023
1024 // VFALCO TODO Should this return const reference for set?
1027 {
1028 return value_compare(m_config.compare());
1029 }
1030
1031 //--------------------------------------------------------------------------
1032 //
1033 // Comparison
1034 //
1035 //--------------------------------------------------------------------------
1036
1037 // This differs from the standard in that the comparison
1038 // is only done on the key portion of the value type, ignoring
1039 // the mapped type.
1040 //
1041 template <
1042 bool OtherIsMulti,
1043 bool OtherIsMap,
1044 class OtherT,
1045 class OtherDuration,
1046 class OtherAllocator>
1047 bool
1049 OtherIsMulti,
1050 OtherIsMap,
1051 Key,
1052 OtherT,
1053 OtherDuration,
1054 Compare,
1055 OtherAllocator> const& other) const;
1056
1057 template <
1058 bool OtherIsMulti,
1059 bool OtherIsMap,
1060 class OtherT,
1061 class OtherDuration,
1062 class OtherAllocator>
1063 bool
1065 OtherIsMulti,
1066 OtherIsMap,
1067 Key,
1068 OtherT,
1069 OtherDuration,
1070 Compare,
1071 OtherAllocator> const& other) const
1072 {
1073 return !(this->operator==(other));
1074 }
1075
1076 template <
1077 bool OtherIsMulti,
1078 bool OtherIsMap,
1079 class OtherT,
1080 class OtherDuration,
1081 class OtherAllocator>
1082 bool
1084 OtherIsMulti,
1085 OtherIsMap,
1086 Key,
1087 OtherT,
1088 OtherDuration,
1089 Compare,
1090 OtherAllocator> const& other) const
1091 {
1092 value_compare const comp(value_comp());
1093 return std::lexicographical_compare(cbegin(), cend(), other.cbegin(), other.cend(), comp);
1094 }
1095
1096 template <
1097 bool OtherIsMulti,
1098 bool OtherIsMap,
1099 class OtherT,
1100 class OtherDuration,
1101 class OtherAllocator>
1102 bool
1104 OtherIsMulti,
1105 OtherIsMap,
1106 Key,
1107 OtherT,
1108 OtherDuration,
1109 Compare,
1110 OtherAllocator> const& other) const
1111 {
1112 return !(other < *this);
1113 }
1114
1115 template <
1116 bool OtherIsMulti,
1117 bool OtherIsMap,
1118 class OtherT,
1119 class OtherDuration,
1120 class OtherAllocator>
1121 bool
1123 OtherIsMulti,
1124 OtherIsMap,
1125 Key,
1126 OtherT,
1127 OtherDuration,
1128 Compare,
1129 OtherAllocator> const& other) const
1130 {
1131 return other < *this;
1132 }
1133
1134 template <
1135 bool OtherIsMulti,
1136 bool OtherIsMap,
1137 class OtherT,
1138 class OtherDuration,
1139 class OtherAllocator>
1140 bool
1142 OtherIsMulti,
1143 OtherIsMap,
1144 Key,
1145 OtherT,
1146 OtherDuration,
1147 Compare,
1148 OtherAllocator> const& other) const
1149 {
1150 return !(*this < other);
1151 }
1152
1153private:
1154 // enable_if prevents erase (reverse_iterator pos, now) from compiling
1155 template <
1156 bool is_const,
1157 class Iterator,
1159 void
1162 typename clock_type::time_point const& now);
1163
1164 template <
1168
1169 template <
1173
1174private:
1177};
1178
1179//------------------------------------------------------------------------------
1180
1181template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1187
1188template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1190 clock_type& clock,
1191 Compare const& comp)
1192 : m_config(clock, comp), m_cont(comp)
1193{
1194}
1195
1196template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1198 clock_type& clock,
1199 Allocator const& alloc)
1200 : m_config(clock, alloc)
1201{
1202}
1203
1204template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1206 clock_type& clock,
1207 Compare const& comp,
1208 Allocator const& alloc)
1209 : m_config(clock, comp, alloc), m_cont(comp)
1210{
1211}
1212
1213template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1214template <class InputIt>
1216 InputIt first,
1217 InputIt last,
1218 clock_type& clock)
1219 : m_config(clock)
1220{
1221 insert(first, last);
1222}
1223
1224template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1225template <class InputIt>
1227 InputIt first,
1228 InputIt last,
1229 clock_type& clock,
1230 Compare const& comp)
1231 : m_config(clock, comp), m_cont(comp)
1232{
1233 insert(first, last);
1234}
1235
1236template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1237template <class InputIt>
1239 InputIt first,
1240 InputIt last,
1241 clock_type& clock,
1242 Allocator const& alloc)
1243 : m_config(clock, alloc)
1244{
1245 insert(first, last);
1246}
1247
1248template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1249template <class InputIt>
1251 InputIt first,
1252 InputIt last,
1253 clock_type& clock,
1254 Compare const& comp,
1255 Allocator const& alloc)
1256 : m_config(clock, comp, alloc), m_cont(comp)
1257{
1258 insert(first, last);
1259}
1260
1261template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1263 aged_ordered_container const& other)
1264 : m_config(other.m_config)
1265#if BOOST_VERSION >= 108000
1266 , m_cont(other.m_cont.get_comp())
1267#else
1268 , m_cont(other.m_cont.comp())
1269#endif
1270{
1271 insert(other.cbegin(), other.cend());
1272}
1273
1274template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1276 aged_ordered_container const& other,
1277 Allocator const& alloc)
1278 : m_config(other.m_config, alloc)
1279#if BOOST_VERSION >= 108000
1280 , m_cont(other.m_cont.get_comp())
1281#else
1282 , m_cont(other.m_cont.comp())
1283#endif
1284{
1285 insert(other.cbegin(), other.cend());
1286}
1287
1288template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1290 aged_ordered_container&& other)
1291 : m_config(std::move(other.m_config)), m_cont(std::move(other.m_cont))
1292{
1293 chronological.list = std::move(other.chronological.list);
1294}
1295
1296template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1298 aged_ordered_container&& other, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
1299 Allocator const& alloc)
1300 : m_config(std::move(other.m_config), alloc)
1301#if BOOST_VERSION >= 108000
1302 , m_cont(std::move(other.m_cont.get_comp()))
1303#else
1304 , m_cont(std::move(other.m_cont.comp()))
1305#endif
1306
1307{
1308 insert(other.cbegin(), other.cend());
1309 other.clear();
1310}
1311
1312template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1320
1321template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1324 clock_type& clock,
1325 Compare const& comp)
1326 : m_config(clock, comp), m_cont(comp)
1327{
1328 insert(init.begin(), init.end());
1329}
1330
1331template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1334 clock_type& clock,
1335 Allocator const& alloc)
1336 : m_config(clock, alloc)
1337{
1338 insert(init.begin(), init.end());
1339}
1340
1341template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1344 clock_type& clock,
1345 Compare const& comp,
1346 Allocator const& alloc)
1347 : m_config(clock, comp, alloc), m_cont(comp)
1348{
1349 insert(init.begin(), init.end());
1350}
1351
1352template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1357
1358template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1359auto
1362{
1363 if (this != &other)
1364 {
1365 clear();
1366 this->m_config = other.m_config;
1367 insert(other.begin(), other.end());
1368 }
1369 return *this;
1370}
1371
1372template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1373auto
1376{
1377 clear();
1378 this->m_config = std::move(other.m_config);
1379 insert(other.begin(), other.end());
1380 other.clear();
1381 return *this;
1382}
1383
1384template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1385auto
1393
1394//------------------------------------------------------------------------------
1395
1396template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1397template <class K, bool maybe_multi, bool maybe_map, class>
1400{
1401 auto const iter(m_cont.find(k, std::cref(m_config.key_compare())));
1402 if (iter == m_cont.end())
1403 throw std::out_of_range("key not found");
1404 return iter->value.second;
1405}
1406
1407template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1408template <class K, bool maybe_multi, bool maybe_map, class>
1411{
1412 auto const iter(m_cont.find(k, std::cref(m_config.key_compare())));
1413 if (iter == m_cont.end())
1414 throw std::out_of_range("key not found");
1415 return iter->value.second;
1416}
1417
1418template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1419template <bool maybe_multi, bool maybe_map, class>
1422 Key const& key)
1423{
1424 typename cont_type::insert_commit_data d;
1425 auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d));
1426 if (result.second)
1427 {
1428 element* const p(new_element(
1430 m_cont.insert_commit(*p, d);
1431 chronological.list.push_back(*p);
1432 return p->value.second;
1433 }
1434 return result.first->value.second;
1435}
1436
1437template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1438template <bool maybe_multi, bool maybe_map, class>
1441{
1442 typename cont_type::insert_commit_data d;
1443 auto const result(m_cont.insert_check(key, std::cref(m_config.key_compare()), d));
1444 if (result.second)
1445 {
1446 element* const p(new_element(
1448 std::forward_as_tuple(std::move(key)),
1450 m_cont.insert_commit(*p, d);
1451 chronological.list.push_back(*p);
1452 return p->value.second;
1453 }
1454 return result.first->value.second;
1455}
1456
1457//------------------------------------------------------------------------------
1458
1459template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1460void
1462{
1463 for (auto iter(chronological.list.begin()); iter != chronological.list.end();)
1464 delete_element(&*iter++);
1465 chronological.list.clear();
1466 m_cont.clear();
1467}
1468
1469// map, set
1470template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1471template <bool maybe_multi>
1472auto
1474 value_type const& value) ->
1476{
1477 typename cont_type::insert_commit_data d;
1478 auto const result(m_cont.insert_check(extract(value), std::cref(m_config.key_compare()), d));
1479 if (result.second)
1480 {
1481 element* const p(new_element(value));
1482 auto const iter(m_cont.insert_commit(*p, d));
1483 chronological.list.push_back(*p);
1484 return std::make_pair(iterator(iter), true);
1485 }
1486 return std::make_pair(iterator(result.first), false);
1487}
1488
1489// multimap, multiset
1490template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1491template <bool maybe_multi>
1492auto
1494 value_type const& value) -> typename std::enable_if<maybe_multi, iterator>::type
1495{
1496 auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare())));
1497 element* const p(new_element(value));
1498 chronological.list.push_back(*p);
1499 auto const iter(m_cont.insert_before(before, *p));
1500 return iterator(iter);
1501}
1502
1503// set
1504template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1505template <bool maybe_multi, bool maybe_map>
1506auto
1508 value_type&& value) ->
1510{
1511 typename cont_type::insert_commit_data d;
1512 auto const result(m_cont.insert_check(extract(value), std::cref(m_config.key_compare()), d));
1513 if (result.second)
1514 {
1515 element* const p(new_element(std::move(value)));
1516 auto const iter(m_cont.insert_commit(*p, d));
1517 chronological.list.push_back(*p);
1518 return std::make_pair(iterator(iter), true);
1519 }
1520 return std::make_pair(iterator(result.first), false);
1521}
1522
1523// multiset
1524template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1525template <bool maybe_multi, bool maybe_map>
1526auto
1528 value_type&& value) -> typename std::enable_if<maybe_multi && !maybe_map, iterator>::type
1529{
1530 auto const before(m_cont.upper_bound(extract(value), std::cref(m_config.key_compare())));
1531 element* const p(new_element(std::move(value)));
1532 chronological.list.push_back(*p);
1533 auto const iter(m_cont.insert_before(before, *p));
1534 return iterator(iter);
1535}
1536
1537//---
1538
1539// map, set
1540template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1541template <bool maybe_multi>
1542auto
1544 const_iterator hint,
1546{
1547 typename cont_type::insert_commit_data d;
1548 auto const result(
1549 m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d));
1550 if (result.second)
1551 {
1552 element* const p(new_element(value));
1553 auto const iter(m_cont.insert_commit(*p, d));
1554 chronological.list.push_back(*p);
1555 return iterator(iter);
1556 }
1557 return iterator(result.first);
1558}
1559
1560// map, set
1561template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1562template <bool maybe_multi>
1563auto
1565 const_iterator hint,
1567{
1568 typename cont_type::insert_commit_data d;
1569 auto const result(
1570 m_cont.insert_check(hint.iterator(), extract(value), std::cref(m_config.key_compare()), d));
1571 if (result.second)
1572 {
1573 element* const p(new_element(std::move(value)));
1574 auto const iter(m_cont.insert_commit(*p, d));
1575 chronological.list.push_back(*p);
1576 return iterator(iter);
1577 }
1578 return iterator(result.first);
1579}
1580
1581// map, set
1582template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1583template <bool maybe_multi, class... Args>
1584auto
1587{
1588 // VFALCO NOTE Its unfortunate that we need to
1589 // construct element here
1590 element* const p(new_element(std::forward<Args>(args)...));
1591 typename cont_type::insert_commit_data d;
1592 auto const result(m_cont.insert_check(extract(p->value), std::cref(m_config.key_compare()), d));
1593 if (result.second)
1594 {
1595 auto const iter(m_cont.insert_commit(*p, d));
1596 chronological.list.push_back(*p);
1597 return std::make_pair(iterator(iter), true);
1598 }
1599 delete_element(p);
1600 return std::make_pair(iterator(result.first), false);
1601}
1602
1603// multiset, multimap
1604template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1605template <bool maybe_multi, class... Args>
1606auto
1609{
1610 element* const p(new_element(std::forward<Args>(args)...));
1611 auto const before(m_cont.upper_bound(extract(p->value), std::cref(m_config.key_compare())));
1612 chronological.list.push_back(*p);
1613 auto const iter(m_cont.insert_before(before, *p));
1614 return iterator(iter);
1615}
1616
1617// map, set
1618template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1619template <bool maybe_multi, class... Args>
1620auto
1622 const_iterator hint,
1623 Args&&... args) -> typename std::enable_if<!maybe_multi, std::pair<iterator, bool>>::type
1624{
1625 // VFALCO NOTE Its unfortunate that we need to
1626 // construct element here
1627 element* const p(new_element(std::forward<Args>(args)...));
1628 typename cont_type::insert_commit_data d;
1629 auto const result(m_cont.insert_check(
1630 hint.iterator(), extract(p->value), std::cref(m_config.key_compare()), d));
1631 if (result.second)
1632 {
1633 auto const iter(m_cont.insert_commit(*p, d));
1634 chronological.list.push_back(*p);
1635 return std::make_pair(iterator(iter), true);
1636 }
1637 delete_element(p);
1638 return std::make_pair(iterator(result.first), false);
1639}
1640
1641template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1642template <bool is_const, class Iterator, class>
1650
1651template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1652template <bool is_const, class Iterator, class>
1663
1664template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1665template <class K>
1666auto
1668 -> size_type
1669{
1670 auto iter(m_cont.find(k, std::cref(m_config.key_compare())));
1671 if (iter == m_cont.end())
1672 return 0;
1673 size_type n(0);
1674 for (;;)
1675 {
1676 auto p(&*iter++);
1677 bool const done(m_config(*p, extract(iter->value)));
1678 unlink_and_delete_element(p);
1679 ++n;
1680 if (done)
1681 break;
1682 }
1683 return n;
1684}
1685
1686template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1687void
1689 aged_ordered_container& other) noexcept
1690{
1691 swap_data(other);
1692 std::swap(chronological, other.chronological);
1693 std::swap(m_cont, other.m_cont);
1694}
1695
1696//------------------------------------------------------------------------------
1697
1698template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1699template <class K>
1700auto
1702 -> size_type
1703{
1704 auto const now(clock().now());
1705 size_type n(0);
1706 auto const range(equal_range(k));
1707 for (auto iter : range)
1708 {
1709 touch(iter, now);
1710 ++n;
1711 }
1712 return n;
1713}
1714
1715//------------------------------------------------------------------------------
1716
1717template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1718template <
1719 bool OtherIsMulti,
1720 bool OtherIsMap,
1721 class OtherT,
1722 class OtherDuration,
1723 class OtherAllocator>
1724bool
1727 OtherIsMulti,
1728 OtherIsMap,
1729 Key,
1730 OtherT,
1731 OtherDuration,
1732 Compare,
1733 OtherAllocator> const& other) const
1734{
1735 using Other = aged_ordered_container<
1736 OtherIsMulti,
1737 OtherIsMap,
1738 Key,
1739 OtherT,
1740 OtherDuration,
1741 Compare,
1742 OtherAllocator>;
1743 if (size() != other.size())
1744 return false;
1746 return std::equal(
1747 cbegin(),
1748 cend(),
1749 other.cbegin(),
1750 other.cend(),
1751 [&eq, &other](value_type const& lhs, typename Other::value_type const& rhs) {
1752 return eq(extract(lhs), other.extract(rhs));
1753 });
1754}
1755
1756//------------------------------------------------------------------------------
1757
1758template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1759template <bool is_const, class Iterator, class>
1760void
1763 typename clock_type::time_point const& now)
1764{
1765 auto& e(*pos.iterator());
1766 e.when = now;
1767 chronological.list.erase(chronological.list.iterator_to(e));
1768 chronological.list.push_back(e);
1769}
1770
1771template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1772template <bool maybe_propagate>
1775 aged_ordered_container& other) noexcept
1776{
1777 std::swap(m_config.key_compare(), other.m_config.key_compare());
1778 std::swap(m_config.alloc(), other.m_config.alloc());
1779 std::swap(m_config.clock, other.m_config.clock);
1780}
1781
1782template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1783template <bool maybe_propagate>
1786 aged_ordered_container& other) noexcept
1787{
1788 std::swap(m_config.key_compare(), other.m_config.key_compare());
1789 std::swap(m_config.clock, other.m_config.clock);
1790}
1791
1792} // namespace detail
1793
1794//------------------------------------------------------------------------------
1795
1796template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1798 beast::detail::aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>>
1800{
1801 explicit is_aged_container() = default;
1802};
1803
1804// Free functions
1805
1806template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
1807void
1815
1817template <
1818 bool IsMulti,
1819 bool IsMap,
1820 class Key,
1821 class T,
1822 class Clock,
1823 class Compare,
1824 class Allocator,
1825 class Rep,
1826 class Period>
1831{
1832 std::size_t n(0);
1833 auto const expired(c.clock().now() - age);
1834 for (auto iter(c.chronological.cbegin());
1835 iter != c.chronological.cend() && iter.when() <= expired;)
1836 {
1837 iter = c.erase(iter);
1838 ++n;
1839 }
1840 return n;
1841}
1842
1843} // namespace beast
T addressof(T... args)
T allocate(T... args)
Abstract interface to a clock.
typename Clock::time_point time_point
virtual time_point now() const =0
Returns the current time.
typename Clock::duration duration
bool operator()(element const &e, Key const &k) const
bool operator()(element const &x, element const &y) const
bool operator()(Key const &k, element const &e) const
const_iterator iterator_to(value_type const &value) const
beast::detail::aged_container_iterator< true, typename list_type::reverse_iterator > const_reverse_iterator
beast::detail::aged_container_iterator<!IsMap, typename list_type::reverse_iterator > reverse_iterator
beast::detail::aged_container_iterator<!IsMap, typename list_type::iterator > iterator
beast::detail::aged_container_iterator< true, typename list_type::iterator > const_iterator
config_t(config_t const &other, Allocator const &alloc)
config_t(clock_type &clock_, Allocator const &alloc_)
config_t(clock_type &clock_, Compare const &comp, Allocator const &alloc_)
config_t(config_t &&other, Allocator const &alloc)
config_t(clock_type &clock_, Compare const &comp)
bool operator()(value_type const &lhs, value_type const &rhs) const
Associative container where each element is also indexed by time.
std::conditional< IsMap, T, void * >::type & operator[](Key const &key)
aged_ordered_container(aged_ordered_container &&other, Allocator const &alloc)
std::enable_if< maybe_multi, iterator >::type emplace_hint(const_iterator, Args &&... args)
typename std::allocator_traits< Allocator >::const_pointer const_pointer
aged_ordered_container(aged_ordered_container &&other)
auto insert(const_iterator hint, value_type const &value) -> typename std::enable_if<!maybe_multi, iterator >::type
std::conditional< IsMap, T, void * >::type & at(K const &k)
typename std::allocator_traits< Allocator >::pointer pointer
aged_ordered_container & operator=(std::initializer_list< value_type > init)
typename std::allocator_traits< Allocator >::template rebind_alloc< element > ElementAllocator
auto insert(value_type const &value) -> typename std::enable_if< maybe_multi, iterator >::type
const_iterator find(K const &k) const
beast::detail::aged_container_iterator< true, typename cont_type::reverse_iterator > const_reverse_iterator
typename std::conditional< IsMap, pair_value_compare, Compare >::type value_compare
void swap(aged_ordered_container &other) noexcept
beast::detail::aged_container_iterator< false, Iterator > erase(beast::detail::aged_container_iterator< is_const, Iterator > pos)
auto insert(value_type &&value) -> typename std::enable_if<!maybe_multi &&!maybe_map, std::pair< iterator, bool > >::type
aged_ordered_container(clock_type &clock, Compare const &comp)
aged_ordered_container(aged_ordered_container const &other, Allocator const &alloc)
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock, Compare const &comp, Allocator const &alloc)
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock, Allocator const &alloc)
bool operator<=(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock)
aged_ordered_container & operator=(aged_ordered_container const &other)
aged_ordered_container(InputIt first, InputIt last, clock_type &clock, Allocator const &alloc)
bool operator>(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
void insert(InputIt first, InputIt last)
std::pair< iterator, iterator > equal_range(K const &k)
bool operator==(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
aged_ordered_container(clock_type &clock, Compare const &comp, Allocator const &alloc)
std::enable_if< maybe_map &&std::is_constructible< value_type, P && >::value, typenamestd::conditional< IsMulti, iterator, std::pair< iterator, bool > >::type >::type insert(P &&value)
void insert(std::initializer_list< value_type > init)
aged_ordered_container(aged_ordered_container const &other)
beast::detail::aged_container_iterator<!IsMap, typename cont_type::iterator > iterator
aged_ordered_container(std::initializer_list< value_type > init, clock_type &clock, Compare const &comp)
std::enable_if< maybe_map &&std::is_constructible< value_type, P && >::value, typenamestd::conditional< IsMulti, iterator, std::pair< iterator, bool > >::type >::type insert(const_iterator hint, P &&value)
const_iterator lower_bound(K const &k) const
typename std::conditional< IsMulti, typename boost::intrusive::make_multiset< element, boost::intrusive::constant_time_size< true >, boost::intrusive::compare< KeyValueCompare > >::type, typename boost::intrusive::make_set< element, boost::intrusive::constant_time_size< true >, boost::intrusive::compare< KeyValueCompare > >::type >::type cont_type
const_iterator upper_bound(K const &k) const
bool operator!=(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
const_iterator iterator_to(value_type const &value) const
std::enable_if< maybe_propagate >::type swap_data(aged_ordered_container &other) noexcept
auto insert(value_type &&value) -> typename std::enable_if< maybe_multi &&!maybe_map, iterator >::type
auto insert(value_type const &value) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
beast::detail::aged_container_iterator< false, Iterator > erase(beast::detail::aged_container_iterator< is_const, Iterator > first, beast::detail::aged_container_iterator< is_const, Iterator > last)
std::enable_if< maybe_multi, iterator >::type insert(const_iterator, value_type const &value)
auto emplace(Args &&... args) -> typename std::enable_if< maybe_multi, iterator >::type
bool operator<(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
auto insert(const_iterator hint, value_type &&value) -> typename std::enable_if<!maybe_multi, iterator >::type
void touch(beast::detail::aged_container_iterator< is_const, Iterator > pos, typename clock_type::time_point const &now)
void touch(beast::detail::aged_container_iterator< is_const, Iterator > pos)
class beast::detail::aged_ordered_container::chronological_t chronological
aged_ordered_container(clock_type &clock, Allocator const &alloc)
aged_ordered_container(InputIt first, InputIt last, clock_type &clock, Compare const &comp)
beast::detail::aged_container_iterator<!IsMap, typename cont_type::reverse_iterator > reverse_iterator
aged_ordered_container(InputIt first, InputIt last, clock_type &clock, Compare const &comp, Allocator const &alloc)
aged_ordered_container & operator=(aged_ordered_container &&other)
std::enable_if< maybe_multi, iterator >::type insert(const_iterator, value_type &&value)
beast::detail::aged_container_iterator< true, typename cont_type::iterator > const_iterator
bool operator>=(aged_ordered_container< OtherIsMulti, OtherIsMap, Key, OtherT, OtherDuration, Compare, OtherAllocator > const &other) const
typename boost::intrusive::make_list< element, boost::intrusive::constant_time_size< false > >::type list_type
auto emplace_hint(const_iterator hint, Args &&... args) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
std::conditional< IsMap, T, void * >::type const & at(K const &k) const
aged_ordered_container(InputIt first, InputIt last, clock_type &clock)
typename std::conditional< IsMap, std::pair< Key const, T >, Key >::type value_type
auto emplace(Args &&... args) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool > >::type
std::conditional< IsMap, T, void * >::type & operator[](Key &&key)
static Key const & extract(value_type const &value)
std::pair< const_iterator, const_iterator > equal_range(K const &k) const
typename clock_type::time_point time_point
T construct(T... args)
T deallocate(T... args)
T destroy(T... args)
T equal(T... args)
T forward_as_tuple(T... args)
T is_same_v
T lexicographical_compare(T... args)
T make_pair(T... args)
int compare(SemanticVersion const &lhs, SemanticVersion const &rhs)
Compare two SemanticVersions against each other.
std::enable_if< is_aged_container< AgedContainer >::value, std::size_t >::type expire(AgedContainer &c, std::chrono::duration< Rep, Period > const &age)
Expire aged container items past the specified age.
void swap(beast::detail::aged_ordered_container< IsMulti, IsMap, Key, T, Clock, Compare, Allocator > &lhs, beast::detail::aged_ordered_container< IsMulti, IsMap, Key, T, Clock, Compare, Allocator > &rhs) noexcept
STL namespace.
T piecewise_construct
T cref(T... args)
T release(T... args)
typename aged_ordered_container::time_point time_point
typename aged_ordered_container::value_type value_type
element(time_point const &when_, value_type const &value_)
element(time_point const &when_, value_type &&value_)
element(time_point const &when_, Args &&... args)
T swap(T... args)