2020#include < any>
2121#include < concepts>
2222#include < functional>
23- #include < iterator>
2423#include < map>
2524#include < memory>
2625#include < optional>
2726#include < string>
28- #include < vector>
27+ #include < ranges>
28+ #include < type_traits>
2929
3030namespace o2 ::quality_control::core
3131{
3232
33- class MonitorObject ;
33+ template <typename Function, typename Result, typename ... Args>
34+ concept invocable_r = std::invocable<Function, Args...> && std::same_as<std::invoke_result_t <Function, Args...>, Result>;
3435
3536class Data
3637{
37- // change this for boost::flat_map? or do a magic and split by different keys?
38- using InternalContainer = std::map<std::string, std::any, std::less<>>;
39- using InternalContainerConstIterator = InternalContainer::const_iterator;
40-
41- 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-
7138 public:
72- template <typename T, typename IncrementalPolicy = NoPredicateIncrementPolicy<T>>
73- class Iterator
74- {
75- public:
76- using value_type = std::pair<std::reference_wrapper<const std::string>, std::reference_wrapper<const T>>;
77- using difference_type = std::ptrdiff_t ;
78- using iterator_category = std::forward_iterator_tag;
79- using reference = const value_type&;
80- using pointer = const value_type*;
81-
82- private:
83- public:
84- Iterator () = default ;
85- Iterator (const InternalContainerConstIterator& it, const InternalContainerConstIterator& end, const IncrementalPolicy& policy = {})
86- : mIt { it }, mEnd { end }, mVal { std::nullopt }
87- {
88- seek_next_valid (mIt );
89- }
90-
91- reference operator *() const
92- {
93- return mVal .value ();
94- }
95-
96- pointer operator ->() const
97- {
98- return &mVal .value ();
99- }
100-
101- Iterator& operator ++()
102- {
103- // TODO: can this check be optimised out?
104- if (mIt != mEnd ) {
105- seek_next_valid (++mIt );
106- }
107- return *this ;
108- }
109-
110- Iterator operator ++(int )
111- {
112- auto tmp = *this ;
113- ++*this ;
114- return tmp;
115- }
116-
117- bool operator ==(const Iterator& other) const
118- {
119- return mIt == other.mIt ;
120- }
121-
122- private:
123- InternalContainerConstIterator mIt ;
124- InternalContainerConstIterator mEnd ;
125- IncrementalPolicy mPolicy ;
126- std::optional<value_type> mVal ;
127-
128- void seek_next_valid (InternalContainerConstIterator& startingIt)
129- {
130- for (; startingIt != mEnd ; ++startingIt) {
131- if (mPolicy .increment (startingIt, mVal )) {
132- break ;
133- }
134- }
135- }
136- };
137-
138- template <typename T, std::predicate<const T&> P>
139- using FilteringIterator = Iterator<T, PredicateIncrementPolicy<T, P>>;
140-
141- static_assert (std::forward_iterator<Iterator<int >>);
142-
14339 Data () = default ;
144- Data (const std::map<std::string, std::shared_ptr<MonitorObject>>& moMap);
14540
14641 template <typename Result>
14742 std::optional<Result> get (std::string_view key)
@@ -154,83 +49,71 @@ class Data
15449 return std::nullopt ;
15550 }
15651
157- template <typename StoreType >
158- void insert (std::string_view key, const StoreType& value )
52+ template <typename T, typename ... Args >
53+ void emplace (std::string_view key, Args&&... args )
15954 {
160- mObjects .insert ({ std::string{ key }, value });
55+ mObjects .emplace (key, std::any{ std::in_place_type<T>, std::forward<Args>(args)... });
16156 }
16257
16358 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- };
59+ void insert (std::string_view key, const T& value)
60+ {
61+ mObjects .insert ({ std::string{ key }, value });
62+ }
17063
17164 template <typename T>
172- Range<T> iterate() const noexcept
65+ static const T* any_cast_try_shared_ptr ( const std::any& value)
17366 {
174- return {
175- .begin_it = begin<T>(),
176- .end_it = end<T>()
177- };
67+ if (auto * casted = std::any_cast<std::shared_ptr<T>>(&value); casted != nullptr ) {
68+ return casted->get ();
69+ } else {
70+ return std::any_cast<T>(&value);
71+ }
17872 }
17973
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- };
74+ template <typename T>
75+ static constexpr auto any_to_specific = std::views::transform([](const auto & pair) -> std::pair<std::string_view, const T*> { return { pair.first , any_cast_try_shared_ptr<T>(pair.second ) }; });
18776
188- template <typename Type, std::predicate<const Type&> Pred>
189- FilteredRange<Type, Pred> iterateAndFilter (Pred&& filter) const noexcept
190- {
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- };
195- }
77+ static constexpr auto filter_nullptr_in_pair = std::views::filter([](const auto & pair) { return pair.second != nullptr ; });
19678
197- size_t size ( );
79+ static constexpr auto filter_nullptr = std::views::filter([]( const auto * ptr) -> bool { return ptr != nullptr ; } );
19880
199- template <typename T>
200- Iterator<T> begin () const noexcept
201- {
202- return { mObjects .begin (), mObjects .end () };
203- }
81+ static constexpr auto pair_to_reference = std::views::transform([](const auto & pair) -> const auto & { return *pair.second ; });
20482
205- template <typename T, std::predicate<const T&> P>
206- FilteringIterator<T, P> begin (P&& filter) const noexcept
83+ static constexpr auto pointer_to_reference = std::views::transform([](const auto * ptr) -> auto & { return *ptr; });
84+
85+ template <typename T>
86+ auto iterateByType () const
20787 {
208- return { mObjects . begin (), mObjects . end (), PredicateIncrementPolicy<T, P>(filter) } ;
88+ return mObjects | any_to_specific<T> | filter_nullptr_in_pair | pair_to_reference ;
20989 }
21090
211- template <typename T>
212- Iterator<T> end ( ) const noexcept
91+ template <typename T, std::predicate< const std::pair<std::string_view, const T*>&> Pred >
92+ auto iterateByTypeAndFilter (Pred&& filter ) const
21393 {
214- return { mObjects . end (), mObjects . end () } ;
94+ return mObjects | any_to_specific<T> | filter_nullptr_in_pair | std::views::filter (filter) | pair_to_reference ;
21595 }
21696
217- template <typename T, std::predicate<const T &> P >
218- FilteringIterator<T, P> end (P && filter) const noexcept
97+ template <typename StoredType, typename ResultingType, std::predicate<const std::pair<std::string_view, const StoredType*> &> Pred, invocable_r< const ResultingType*, const StoredType*> Transform >
98+ auto iterateByTypeFilterAndTransform (Pred && filter, Transform&& transform ) const
21999 {
220- return { mObjects .end (), mObjects .end (), PredicateIncrementPolicy<T, P>(filter) };
100+ return mObjects |
101+ any_to_specific<StoredType> |
102+ filter_nullptr_in_pair |
103+ std::views::filter (filter) |
104+ std::views::transform ([](const auto & pair) { return pair.second ; }) |
105+ std::views::transform (transform) |
106+ filter_nullptr |
107+ pointer_to_reference;
221108 }
222109
223- template <typename Base, typename Derived>
224- static std::optional<Derived*> downcast (const Base* base)
110+ size_t size () const noexcept
225111 {
226- if (const auto * casted = dynamic_cast <Derived*>(base); casted != nullptr ) {
227- return { casted };
228- }
229- return std::nullopt ;
112+ return mObjects .size ();
230113 }
231114
232115 private:
233- InternalContainer mObjects ;
116+ std::map<std::string, std::any, std::less<>> mObjects ;
234117};
235118
236119} // namespace o2::quality_control::core
0 commit comments