summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-03-22 11:50:31 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2025-03-22 11:50:31 +0000
commit9fd25e8b10b1291525a18c8b3e34256ca6151dd6 (patch)
treec483b55010f310ed60cb7381130feedd2b3980a9 /lib
parentSupport resizing the main window (diff)
downloadilt-9fd25e8b10b1291525a18c8b3e34256ca6151dd6.tar.bz2
ilt-9fd25e8b10b1291525a18c8b3e34256ca6151dd6.tar.xz
ilt-9fd25e8b10b1291525a18c8b3e34256ca6151dd6.zip
Add ManyPtr which tracks specified subclasses
This removes the need to repeated dynamic_cast the pointer. Provides interface which enforces the fastest option for the required types.
Diffstat (limited to 'lib')
-rw-r--r--lib/manyPtr.h86
-rw-r--r--lib/persistence.h3
2 files changed, 88 insertions, 1 deletions
diff --git a/lib/manyPtr.h b/lib/manyPtr.h
new file mode 100644
index 0000000..9e08452
--- /dev/null
+++ b/lib/manyPtr.h
@@ -0,0 +1,86 @@
+#pragma once
+
+#include <memory>
+#include <tuple>
+
+template<typename Primary, typename... Others> class ManyPtr : Primary {
+public:
+ using element_type = typename Primary::element_type;
+
+ template<typename... Params> ManyPtr(Params &&... params) : Primary {std::forward<Params>(params)...}
+ {
+ updatePtrs();
+ }
+
+ using Primary::operator->;
+ using Primary::operator*;
+ using Primary::operator bool;
+ using Primary::get;
+
+ template<typename... Params>
+ void
+ reset(Params &&... params)
+ {
+ Primary::reset(std::forward<Params>(params)...);
+ updatePtrs();
+ }
+
+ template<typename Other>
+ [[nodiscard]] consteval static bool
+ couldBe()
+ {
+ return (std::is_convertible_v<Others *, Other *> || ...);
+ }
+
+ template<typename Other>
+ requires(couldBe<Other>())
+ [[nodiscard]] auto
+ getAs() const
+ {
+ return std::get<idx<Other>()>(others);
+ }
+
+ template<typename Other>
+ requires(!couldBe<Other>() && requires { std::dynamic_pointer_cast<Other>(std::declval<Primary>()); })
+ [[nodiscard]] auto
+ dynamicCast() const
+ {
+ return std::dynamic_pointer_cast<Other>(*this);
+ }
+
+ template<typename Other>
+ requires(!couldBe<Other>() && !requires { std::dynamic_pointer_cast<Other>(std::declval<Primary>()); })
+ [[nodiscard]] auto
+ dynamicCast() const
+ {
+ return dynamic_cast<Other *>(get());
+ }
+
+private:
+ using OtherPtrs = std::tuple<Others *...>;
+
+ template<typename Other>
+ requires(couldBe<Other>())
+ [[nodiscard]] consteval static bool
+ idx()
+ {
+ size_t typeIdx = 0;
+ return ((typeIdx++ && std::is_convertible_v<Others *, Other *>) || ...);
+ }
+
+ void
+ updatePtrs()
+ {
+ if (*this) {
+ others = {dynamic_cast<Others *>(get())...};
+ }
+ else {
+ others = {};
+ }
+ }
+
+ OtherPtrs others;
+};
+
+template<typename Primary, typename... Others> using ManySharedPtr = ManyPtr<std::shared_ptr<Primary>, Others...>;
+template<typename Primary, typename... Others> using ManyUniquePtr = ManyPtr<std::unique_ptr<Primary>, Others...>;
diff --git a/lib/persistence.h b/lib/persistence.h
index e385b20..75bcea6 100644
--- a/lib/persistence.h
+++ b/lib/persistence.h
@@ -1,5 +1,6 @@
#pragma once
+#include "manyPtr.h"
#include <charconv>
#include <format>
#include <functional>
@@ -200,7 +201,7 @@ namespace Persistence {
}
[[nodiscard]] virtual NameActionSelection setName(const std::string_view key, SelectionFactory &&) = 0;
- virtual void selHandler() {};
+ virtual void selHandler() { };
virtual void setType(const std::string_view, const Persistable *) = 0;
SelectionPtr sel {};