diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-23 13:00:03 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-23 13:00:03 +0000 |
commit | a53a6672b8fc89834b1ec3aa7afae150a617473f (patch) | |
tree | efd2ab5e32cd75e2e36ad53042725c91346b7cfa /lib | |
parent | Make Collections::objects protected, extend interface (diff) | |
download | ilt-a53a6672b8fc89834b1ec3aa7afae150a617473f.tar.bz2 ilt-a53a6672b8fc89834b1ec3aa7afae150a617473f.tar.xz ilt-a53a6672b8fc89834b1ec3aa7afae150a617473f.zip |
Populate typed collection of pointers
create and emplace only, so far
Diffstat (limited to 'lib')
-rw-r--r-- | lib/collection.h | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/lib/collection.h b/lib/collection.h index c843bad..e68a8db 100644 --- a/lib/collection.h +++ b/lib/collection.h @@ -6,12 +6,13 @@ #include <type_traits> #include <vector> -template<typename Ptr> class Collection { +template<typename Ptr, typename... Others> class Collection { public: virtual ~Collection() = default; using Object = Ptr::element_type; using Objects = std::vector<Ptr>; + template<typename T> using OtherObjects = std::vector<T *>; Collection & operator=(Objects && other) @@ -34,10 +35,14 @@ public: if constexpr (requires(Ptr ptr) { ptr = std::make_shared<T>(std::forward<Params>(params)...); }) { auto obj = std::make_shared<T>(std::forward<Params>(params)...); objects.emplace_back(obj); + addOthersType<T>(obj.get()); return obj; } else { - return static_cast<T *>(objects.emplace_back(std::make_unique<T>(std::forward<Params>(params)...)).get()); + auto obj = static_cast<T *>( + objects.emplace_back(std::make_unique<T>(std::forward<Params>(params)...)).get()); + addOthersType<T>(obj); + return obj; } } @@ -136,11 +141,75 @@ public: auto emplace(Ptr && ptr) { - return objects.emplace_back(std::move(ptr)); + auto object = objects.emplace_back(std::move(ptr)); + addOthersPtr(object.get()); + return object; } protected: Objects objects; + std::tuple<OtherObjects<Others>...> otherObjects; + + template<typename T> + void + addOthersType(T * obj) + { + applyToOthersType<T>( + [](auto & others, auto ptr) { + others.emplace_back(ptr); + }, + obj); + } + + void + addOthersPtr(Object * obj) + { + applyToOthersPtr( + [](auto & others, auto ptr) { + others.emplace_back(ptr); + }, + obj); + } + + template<typename T> + requires(sizeof...(Others) == 0) + void + applyToOthersType(const auto &, T *) + { + } + + void + applyToOthersPtr(const auto &, Object *) + requires(sizeof...(Others) == 0) + { + } + + template<typename T> + requires(sizeof...(Others) > 0) + void + applyToOthersType(const auto & func, T * obj) + { + ( + [&]() { + if constexpr (std::is_convertible_v<T *, Others *>) { + std::invoke(func, std::get<OtherObjects<Others>>(otherObjects), obj); + } + }(), + ...); + } + + void + applyToOthersPtr(const auto & func, Object * obj) + requires(sizeof...(Others) > 0) + { + ( + [&]() { + if (auto ptr = dynamic_cast<Others *>(obj)) { + std::invoke(func, std::get<OtherObjects<Others>>(otherObjects), ptr); + } + }(), + ...); + } template<typename T = Object, typename... Params> auto @@ -168,5 +237,5 @@ protected: } }; -template<typename T> using SharedCollection = Collection<std::shared_ptr<T>>; -template<typename T> using UniqueCollection = Collection<std::unique_ptr<T>>; +template<typename T, typename... Others> using SharedCollection = Collection<std::shared_ptr<T>, Others...>; +template<typename T, typename... Others> using UniqueCollection = Collection<std::unique_ptr<T>, Others...>; |