Я работаю над анализатором протокола 9p. Протокол имеет кучу сообщений. Я хочу иметь простой интерфейс типа auto message = parser.pares(bytesStream);
Какого типа message
, если я хочу, чтобы мой протокол был расширяемым?
В настоящее время я использую variant<Protocol messages>
. В простом случае - где я знаю все возможные версии - это просто. Но я бы хотел поддерживать разные версии протокола (расширения: 9p2000.e, 9p2000.u, 9p2000.l и т. Д.), И каждая из них может добавлять дополнительные типы сообщений. Протокол имеет фиксированный размер заголовка Length-Type-Value вида. Так что я всегда знаю тип сообщения с учетом заголовка. Но в зависимости от согласованной версии протокола - тип сообщений означает немного другое.
Каковы альтернативы использованию наследования при реализации анализаторов расширяемого протокола?
То есть янужна функция формы:
parser.parse(header, byteStream) -> Message;
Проблема здесь в том, что тип сообщения зависит от версии. Обычно это можно решить с помощью наследования типов:
struct IMessage {};
struct p2000::Open : public IMessage {...};
struct p2000e::Open : public IMessage {...};
struct p2000l::Open : public IMessage {...};
И parse () -> unique_ptr;// или что-то в этом роде
Проблема в том, что я хотел бы избежать выделения памяти. Таким образом, хотелось бы не использовать make_unique (...);
Текущая реализация просто возвращает:
parse(...) -> variant<p2000::Open, p2000e::Open, p2000l::Open, ...>;
Это работает нормально, пока я не хочу иметь большемодульный дизайн библиотеки. То есть, когда версия согласовывается (читайте предоставленное пользователем значение во время выполнения), мне нужно переключиться между версиями:
selectParser(version: String) -> versionedParser;
Без сохранения строки current_version
способ реализовать - это сохранить переходtable: messgetype -> *parserFunc
;Это таблица указателей на функцию парсера сообщений. Только выдача каждой функции, возвращаемый тип должен быть одинаковым. Что означает, что я не могу реализовать их независимо от другой версии. То есть: parse_p92000l_open()
должен быть «осведомлен» о типах сообщений p92000e, потому что тип возвращаемого варианта должен будет перечислять все возможные типы сообщений. Который пропускает знания о сообщениях из независимой версии протокола.
Так что, в сущности, я хочу найти лучший способ выразить: Наследование - это базовый класс зла понятия.
Кто-нибудь решал эту проблему раньше?