Created
July 24, 2024 04:56
-
-
Save eao197/cbd115915408c281bdb0d4d2e85f5456 to your computer and use it in GitHub Desktop.
A dirty sketch of using root_t<T> and node_t<D, B> to traverse type hierarchy down up
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <typeindex> | |
#include <stdexcept> | |
class message_upcaster_t; | |
using upcaster_factory_t = message_upcaster_t (*)() noexcept; | |
class message_upcaster_t | |
{ | |
std::type_index m_self_type; | |
upcaster_factory_t m_parent_factory; | |
public: | |
message_upcaster_t( | |
std::type_index self_type, | |
upcaster_factory_t parent_factory ) | |
: m_self_type{ std::move(self_type) } | |
, m_parent_factory{ parent_factory } | |
{} | |
[[nodiscard]] const std::type_index & | |
self_type() const noexcept | |
{ | |
return m_self_type; | |
} | |
[[nodiscard]] bool | |
has_parent_factory() const noexcept | |
{ | |
return nullptr != m_parent_factory; | |
} | |
[[nodiscard]] message_upcaster_t | |
parent_upcaster() const | |
{ | |
if( !has_parent_factory() ) | |
throw std::runtime_error{ | |
"message_upcaster_t::parent_upcaster: " | |
"no parent upcaster_factory" | |
}; | |
return (*m_parent_factory)(); | |
} | |
}; | |
class message_t | |
{ | |
public: | |
virtual ~message_t() = default; | |
}; | |
class root_base_t : public message_t | |
{ | |
upcaster_factory_t m_factory{}; | |
public: | |
[[nodiscard]] upcaster_factory_t | |
so_message_upcaster_factory() const noexcept | |
{ | |
return m_factory; | |
} | |
void | |
so_set_message_upcaster_factory( | |
upcaster_factory_t factory) noexcept | |
{ | |
m_factory = factory; | |
} | |
}; | |
template<typename Base> | |
class root_t : public root_base_t | |
{ | |
public: | |
[[nodiscard]] static message_upcaster_t | |
so_make_upcaster_root() noexcept | |
{ | |
return { typeid(Base), nullptr }; | |
} | |
public: | |
root_t() | |
{ | |
this->so_set_message_upcaster_factory( &root_t::so_make_upcaster_root ); | |
} | |
}; | |
template< typename B, typename = std::void_t<> > | |
struct has_so_make_upcaster_method : public std::false_type {}; | |
template< typename B > | |
struct has_so_make_upcaster_method< | |
B, std::void_t< decltype(&B::so_make_upcaster) > | |
> : public std::true_type {}; | |
template<typename Derived, typename Base> | |
class node_t | |
{ | |
public: | |
[[nodiscard]] static message_upcaster_t | |
so_make_upcaster() noexcept | |
{ | |
if constexpr( has_so_make_upcaster_method<Base>::value ) | |
return { typeid(Derived), &Base::so_make_upcaster }; | |
else | |
return { typeid(Derived), &Base::so_make_upcaster_root }; | |
} | |
public: | |
node_t(Derived & derived) | |
{ | |
static_assert( | |
std::is_base_of_v<root_base_t, Derived> && | |
std::is_base_of_v<Base, Derived> ); | |
derived.so_set_message_upcaster_factory( &node_t::so_make_upcaster ); | |
} | |
}; | |
class image_base : public root_t<image_base> | |
{ | |
public: | |
image_base() = default; | |
}; | |
class image_vendor_1 | |
: public image_base | |
, public node_t<image_vendor_1, image_base> | |
{ | |
public: | |
image_vendor_1() | |
: image_base{} | |
, node_t<image_vendor_1, image_base>{ *this } | |
{} | |
}; | |
class image_vendor_2 | |
: public image_base | |
, public node_t<image_vendor_2, image_base> | |
{ | |
public: | |
image_vendor_2() | |
: image_base{} | |
, node_t<image_vendor_2, image_base>{ *this } | |
{} | |
}; | |
class special_image | |
: public image_vendor_2 | |
, public node_t<special_image, image_vendor_2> | |
{ | |
public: | |
special_image() | |
: image_vendor_2{} | |
, node_t<special_image, image_vendor_2>{ *this } | |
{} | |
}; | |
void handle(const image_base & base) | |
{ | |
auto upcaster = (base.so_message_upcaster_factory())(); | |
std::cout << "self_type: " << upcaster.self_type().name() << std::endl; | |
while( upcaster.has_parent_factory() ) | |
{ | |
upcaster = upcaster.parent_upcaster(); | |
std::cout << "base_type: " << upcaster.self_type().name() << std::endl; | |
} | |
} | |
int main() | |
{ | |
special_image img; | |
handle( img ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment