Created
July 24, 2024 12:57
-
-
Save eao197/236ee246b4563237a65ee052871a18d4 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 with respect to message mutability
This file contains 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> | |
enum class message_mutability_t | |
{ | |
immutable_message, | |
mutable_message | |
}; | |
template< typename Msg > | |
struct mutable_msg {}; | |
class message_upcaster_t; | |
using upcaster_factory_t = | |
message_upcaster_t (*)(message_mutability_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( message_mutability_t mutability ) const | |
{ | |
if( !has_parent_factory() ) | |
throw std::runtime_error{ | |
"message_upcaster_t::parent_upcaster: " | |
"no parent upcaster_factory" | |
}; | |
return (*m_parent_factory)( mutability ); | |
} | |
}; | |
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( message_mutability_t mutability ) noexcept | |
{ | |
if( message_mutability_t::mutable_message == mutability ) | |
return { typeid(mutable_msg<Base>), nullptr }; | |
else | |
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( message_mutability_t mutability ) noexcept | |
{ | |
if constexpr( has_so_make_upcaster_method<Base>::value ) | |
{ | |
const auto upcaster = &Base::so_make_upcaster; | |
if( message_mutability_t::mutable_message == mutability ) | |
return { typeid(mutable_msg<Derived>), upcaster }; | |
else | |
return { typeid(Derived), upcaster }; | |
} | |
else | |
{ | |
const auto upcaster = &Base::so_make_upcaster_root; | |
if( message_mutability_t::mutable_message == mutability ) | |
return { typeid(mutable_msg<Derived>), upcaster }; | |
else | |
return { typeid(Derived), upcaster }; | |
} | |
} | |
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, | |
message_mutability_t mutability) | |
{ | |
auto upcaster = (base.so_message_upcaster_factory())( mutability ); | |
std::cout << "self_type: " << upcaster.self_type().name() << std::endl; | |
while( upcaster.has_parent_factory() ) | |
{ | |
upcaster = upcaster.parent_upcaster( mutability ); | |
std::cout << "base_type: " << upcaster.self_type().name() << std::endl; | |
} | |
} | |
int main() | |
{ | |
special_image img; | |
handle( img, message_mutability_t::immutable_message ); | |
handle( img, message_mutability_t::mutable_message ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment