2020#include < any>
2121#include < concepts>
2222#include < functional>
23- #include < iostream>
2423#include < iterator>
2524#include < map>
2625#include < memory>
2726#include < optional>
2827#include < string>
2928#include < vector>
30- #include < typeinfo>
3129
3230namespace o2 ::quality_control::core
3331{
@@ -40,8 +38,38 @@ class Data
4038 using InternalContainer = std::map<std::string, std::any, std::less<>>;
4139 using InternalContainerConstIterator = InternalContainer::const_iterator;
4240
43- public:
4441 template <typename T>
42+ using value_type = std::pair<std::reference_wrapper<const std::string>, std::reference_wrapper<const T>>;
43+
44+ template <typename T>
45+ struct NoPredicateIncrementPolicy {
46+ bool increment (const InternalContainerConstIterator& it, std::optional<value_type<T>>& val)
47+ {
48+ if (auto * casted = std::any_cast<T>(&it->second ); casted != nullptr ) {
49+ val.emplace (it->first , *casted);
50+ return true ;
51+ }
52+ return false ;
53+ }
54+ };
55+
56+ template <typename T, std::predicate<const T&> Pred>
57+ struct PredicateIncrementPolicy {
58+ Pred filter;
59+ bool increment (const InternalContainerConstIterator& it, std::optional<value_type<T>>& val)
60+ {
61+ if (auto * casted = std::any_cast<T>(&it->second ); casted != nullptr ) {
62+ if (filter (*casted)) {
63+ val.emplace (it->first , *casted);
64+ return true ;
65+ }
66+ }
67+ return false ;
68+ }
69+ };
70+
71+ public:
72+ template <typename T, typename IncrementalPolicy = NoPredicateIncrementPolicy<T>>
4573 class Iterator
4674 {
4775 public:
@@ -51,26 +79,28 @@ class Data
5179 using reference = const value_type&;
5280 using pointer = const value_type*;
5381
82+ private:
83+ public:
5484 Iterator () = default ;
55- Iterator (InternalContainerConstIterator it, InternalContainerConstIterator end)
56- : mIt { it }, mEnd { end }, val { std::nullopt }
85+ Iterator (const InternalContainerConstIterator& it, const InternalContainerConstIterator& end, const IncrementalPolicy& policy = {} )
86+ : mIt { it }, mEnd { end }, mVal { std::nullopt }
5787 {
5888 seek_next_valid (mIt );
5989 }
6090
6191 reference operator *() const
6292 {
63- return val .value ();
93+ return mVal .value ();
6494 }
6595
6696 pointer operator ->() const
6797 {
68- return &val .value ();
98+ return &mVal .value ();
6999 }
70100
71101 Iterator& operator ++()
72102 {
73- // can this be optimised out?
103+ // TODO: can this check be optimised out?
74104 if (mIt != mEnd ) {
75105 seek_next_valid (++mIt );
76106 }
@@ -92,19 +122,22 @@ class Data
92122 private:
93123 InternalContainerConstIterator mIt ;
94124 InternalContainerConstIterator mEnd ;
95- std::optional<value_type> val;
125+ IncrementalPolicy mPolicy ;
126+ std::optional<value_type> mVal ;
96127
97- void seek_next_valid (InternalContainerConstIterator startingIt)
128+ void seek_next_valid (InternalContainerConstIterator& startingIt)
98129 {
99- for (auto it = startingIt; it != mEnd ; ++it) {
100- if (auto * casted = std::any_cast<T>(&it->second ); casted != nullptr ) {
101- val.emplace (it->first , *casted);
130+ for (; startingIt != mEnd ; ++startingIt) {
131+ if (mPolicy .increment (startingIt, mVal )) {
102132 break ;
103133 }
104134 }
105135 }
106136 };
107137
138+ template <typename T, std::predicate<const T&> P>
139+ using FilteringIterator = Iterator<T, PredicateIncrementPolicy<T, P>>;
140+
108141 static_assert (std::forward_iterator<Iterator<int >>);
109142
110143 Data () = default ;
@@ -127,44 +160,75 @@ class Data
127160 mObjects .insert ({ std::string{ key }, value });
128161 }
129162
130- template <typename Type>
131- std::vector<Type> getAllOfType () const
163+ template <typename T>
164+ struct Range {
165+ Iterator<T> begin_it;
166+ Iterator<T> end_it;
167+ Iterator<T> begin () { return begin_it; }
168+ Iterator<T> end () { return end_it; }
169+ };
170+
171+ template <typename T>
172+ Range<T> iterate() const noexcept
132173 {
133- std::vector<Type> result;
134- for (const auto & [_, object] : mObjects ) {
135- if (auto * casted = std::any_cast<Type>(&object); casted != nullptr ) {
136- result.push_back (*casted);
137- }
138- }
139- return result;
174+ return {
175+ .begin_it = begin<T>(),
176+ .end_it = end<T>()
177+ };
140178 }
141179
142- template <typename Type, std::predicate<Type> Pred>
143- std::vector<Type> getAllOfTypeIf (Pred filter) const
180+ template <typename T, std::predicate<const T&> P>
181+ struct FilteredRange {
182+ FilteringIterator<T, P> begin_it;
183+ FilteringIterator<T, P> end_it;
184+ FilteringIterator<T, P> begin () { return begin_it; }
185+ FilteringIterator<T, P> end () { return end_it; }
186+ };
187+
188+ template <typename Type, std::predicate<const Type&> Pred>
189+ FilteredRange<Type, Pred> iterateAndFilter (Pred&& filter) const noexcept
144190 {
145- std::vector<Type> result;
146- for (const auto & [_, object] : mObjects ) {
147- if (auto * casted = std::any_cast<Type>(&object); casted != nullptr ) {
148- if (filter (*casted)) {
149- result.push_back (*casted);
150- }
151- }
152- }
153- return result;
191+ return FilteredRange<Type, Pred>{
192+ .begin_it = begin<Type, Pred>(std::forward<Pred>(filter)),
193+ .end_it = end<Type, Pred>(std::forward<Pred>(filter))
194+ };
154195 }
155196
197+ size_t size ();
198+
156199 template <typename T>
157- Iterator<T> begin ()
200+ Iterator<T> begin () const noexcept
158201 {
159202 return { mObjects .begin (), mObjects .end () };
160203 }
161204
205+ template <typename T, std::predicate<const T&> P>
206+ FilteringIterator<T, P> begin (P&& filter) const noexcept
207+ {
208+ return { mObjects .begin (), mObjects .end (), PredicateIncrementPolicy<T, P>(filter) };
209+ }
210+
162211 template <typename T>
163- Iterator<T> end ()
212+ Iterator<T> end () const noexcept
164213 {
165214 return { mObjects .end (), mObjects .end () };
166215 }
167216
217+ template <typename T, std::predicate<const T&> P>
218+ FilteringIterator<T, P> end (P&& filter) const noexcept
219+ {
220+ return { mObjects .end (), mObjects .end (), PredicateIncrementPolicy<T, P>(filter) };
221+ }
222+
223+ template <typename Base, typename Derived>
224+ static std::optional<Derived*> downcast (const Base* base)
225+ {
226+ if (const auto * casted = dynamic_cast <Derived*>(base); casted != nullptr ) {
227+ return { casted };
228+ }
229+ return std::nullopt ;
230+ }
231+
168232 private:
169233 InternalContainer mObjects ;
170234};
0 commit comments