Comments 6
Что-то по описанию не очень понятно, в чём проблема с иерархиями наследования, что для этого потребовалось городить какие-то вспомогательные типы и наследоваться ещё и от них. Чем стандартный механизм наследования классов из C++ не подходит? Или тут шаблоны как-то мешают?
Мешает идентификация сообщений. Допустим, у нас есть Base и Derived, где Derived унаследован от Base.
Тогда typeid(Base) будет отличаться от typeid(Derived).
Когда в SObjectizer отсылается сообщение, то оно сопровождается идентификатором типа отосланного сообщения. Т.е. когда в коде написано send<Base>(...)
, то экземпляр сообщения будет сопровождать typeid(Base). И подписка будет искаться именно по typeid(Base). Поэтому если кто-то отошлет send<Derived>(...)
то подписка на Base не сработает, т.к. typeid(Base) != typeid(Derived).
Можно отослать Derived как Base. Что-то типа:
auto d = std::make_unique<Derived>(...);
so_5::message_holder_t<Base> msg{std::move(d)};
so_5::send(..., std::move(msg));
Но тогда SObjectizer будет видеть это сообщение как Base. Поэтому если кто-то сделал подписку на Derived, то такое сообщение он не получит.
Я правильно понимаю, что без дополнительных классов вы не можете пройти по иерархии наследования и подписаться одновременно на typeid(Base)
и typeid(Derived)
, чтобы получать сообщения от обеих типов. А с вашим node_t
можете?
А интересно, что будет, если иерархия в node_t
будет отличаться от реальной. Например, вы укажете, что B
наследует от C
, когда на самом деле он наследует от A
.
Я правильно понимаю, что без дополнительных классов вы не можете пройти по иерархии наследования и подписаться одновременно на typeid(Base) и typeid(Derived), чтобы получать сообщения от обеих типов.
Да, в C++ пока нет стандартной рефлексии, поэтому имея на руках тип Derived нет возможности узнать кто у него базовый класс.
А с вашим node_t можете?
Да.
А интересно, что будет, если иерархия в node_t будет отличаться от реальной. Например, вы укажете, что B наследует от C, когда на самом деле он наследует от A.
Если вы про ситуацию типа вот такой:
namespace hierarchy_ns = so_5::extra::msg_hierarchy;
struct B : public hierarchy_ns::root_t<B>
{
B() = default;
};
struct A : public hierarchy_ns::root_t<A>
{
A() = default;
};
struct D
: public A
, public hierarchy_ns::node_t< D, B >
{
D()
: hierarchy_ns::node_t< D, B >( *this )
{}
};
то будет ошибка компиляции:
Compiling ./_habr_q001.cpp ...
_habr_q001.cpp
.\so_5_extra/msg_hierarchy/pub.hpp(374): error C2607: static assertion failed
.\so_5_extra/msg_hierarchy/pub.hpp(374): note: the template instantiation context (the oldest one first) is
./_habr_q001.cpp(19): note: see reference to class template instantiation 'so_5::extra::msg_hierarchy::node_t<D,B>' being compiled
.\so_5_extra/msg_hierarchy/pub.hpp(371): note: while compiling class template member function 'so_5::extra::msg_hierarchy::node_t<D,B>::node_t(Derived &)'
with
[
Derived=D
]
./_habr_q001.cpp(22): note: see the first reference to 'so_5::extra::msg_hierarchy::node_t<D,B>::node_t' in 'D::D'
но, наверное, можно придумать что-то поизощреннее, чтобы обойти простые проверки.
Если вы про ситуацию типа вот такой:
Да, как раз про неё. Это хорошо, что ошибка компиляции, но, очевидно, над ней ещё надо работать, потому что из неё совершенно неочевидно, что она хочет, чтобы вторым параметром в node_t
был А
.
очевидно, над ней ещё надо работать, потому что из неё совершенно неочевидно, что она хочет, чтобы вторым параметром в node_t был А.
В C++17, насколько я знаю, нет нормальных возможностей сформировать в compile-time динамическую строку для static-assert-а.
Кроме того, тут имеет смысл предъявить претензии к качеству диагностики VC++, поскольку GCC более вменяем:
Compiling ./_habr_q001.cpp ...
In file included from ./_habr_q001.cpp:1:
./so_5_extra/msg_hierarchy/pub.hpp: In instantiation of 'so_5::extra::msg_hierarchy::node_t<Derived, Base>::node_t(Derived&) [with Derived = D; Base = B]':
./_habr_q001.cpp:22:42: required from here
./so_5_extra/msg_hierarchy/pub.hpp:375:54: error: static assertion failed
375 | std::is_base_of_v<Base, Derived> );
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
./so_5_extra/msg_hierarchy/pub.hpp:375:54: note: 'std::is_base_of_v<B, D>' evaluates to false
[sobjectizer] Что нового в SO-5.8.3 и so5extra-1.6.2?