Search
Write a publication
Pull to refresh

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
Sign up to leave a comment.

Articles