diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-28 19:04:21 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-28 19:04:21 +0000 |
commit | 508ffe80c9991cc76f4fa37dd2fa21746abe3a89 (patch) | |
tree | fe5ca4a08a246191432c304708ce76fe1c3905d6 /lib/manyPtr.h | |
parent | Create the last group in jsonParse.ll (diff) | |
parent | Fix check for bulk removal (diff) | |
download | ilt-508ffe80c9991cc76f4fa37dd2fa21746abe3a89.tar.bz2 ilt-508ffe80c9991cc76f4fa37dd2fa21746abe3a89.tar.xz ilt-508ffe80c9991cc76f4fa37dd2fa21746abe3a89.zip |
Diffstat (limited to 'lib/manyPtr.h')
-rw-r--r-- | lib/manyPtr.h | 86 |
1 files changed, 86 insertions, 0 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...>; |