#pragma once #include #include template class ManyPtr : Primary { public: using element_type = typename Primary::element_type; template ManyPtr(Params &&... params) : Primary {std::forward(params)...} { updatePtrs(); } using Primary::operator->; using Primary::operator*; using Primary::operator bool; using Primary::get; template void reset(Params &&... params) { Primary::reset(std::forward(params)...); updatePtrs(); } template [[nodiscard]] consteval static bool couldBe() { return (std::is_convertible_v || ...); } template requires(couldBe()) [[nodiscard]] auto getAs() const { return std::get()>(others); } template requires(!couldBe() && requires { std::dynamic_pointer_cast(std::declval()); }) [[nodiscard]] auto dynamicCast() const { return std::dynamic_pointer_cast(*this); } template requires(!couldBe() && !requires { std::dynamic_pointer_cast(std::declval()); }) [[nodiscard]] auto dynamicCast() const { return dynamic_cast(get()); } private: using OtherPtrs = std::tuple; template requires(couldBe()) [[nodiscard]] consteval static bool idx() { size_t typeIdx = 0; return ((typeIdx++ && std::is_convertible_v) || ...); } void updatePtrs() { if (*this) { others = {dynamic_cast(get())...}; } else { others = {}; } } OtherPtrs others; }; template using ManySharedPtr = ManyPtr, Others...>; template using ManyUniquePtr = ManyPtr, Others...>;