Возможна ли шаблонная версия виртуального базового класса в качестве интерфейса во время компиляции? ⇐ C++
Возможна ли шаблонная версия виртуального базового класса в качестве интерфейса во время компиляции?
Я работаю над структурой для системного проектирования на основе моделей (MBSE). Здесь у меня есть конструкция под названием Bridge. Мост может отправлять Сигналы (асинхронные вызовы) и/или Операции (синхронные вызовы) с одного конца Моста на другой. Сигналы и операции также могут иметь полезную нагрузку, определенную конечным пользователем платформы (другим программистом на C++).
Мост подключен к сети, поэтому вход моста подключается к выходу моста через сетевой сокет. Чтобы это работало, необходимо сериализовать сигналы и/или операции (сокращенно SigOps), а также возможную полезную нагрузку.
У моста есть исходящая очередь, которая буферизует и сохраняет последовательность SigOp по мере их выдачи. Следовательно, эта очередь хранит SigOps, используя общие указатели SigOp. Но все равно необходимо использовать специальный сериализатор типа SigOp.
Обычный способ сделать это — использовать виртуальный базовый класс, определяющий интерфейс, а затем позволить производному классу добавить реализацию. Что-то вроде:
// Виртуальный базовый класс/интерфейс SigOp, специфичный для типа моста шаблон класс СигОпТ { публика: виртуальная пустота initSerialization (SigOpSerDes &fSerializer, SerializationBuffer &fSerializationBuffer) = 0; виртуальная пустота сериализоватьPayLoad (SigOpSerDes &fSigOpSerializer) = 0; }; шаблон класс MySigOp: public SigOpT { void initSerialization(SigOpSerDes &fSerializer, SerializationBuffer &fSerializationBuffer) переопределить окончательный вариант { // Моя реализация ... } voidserializePayLoad(SigOpSerDes &fSigOpSerializer) переопределенный финал { // Мой код сериализации, специфичный для MySigOp ... } }; На вопрос: Есть ли способ сделать то же самое во время компиляции, исключив тем самым виртуальные функции, виртуальные таблицы и т. д.?
CRTP (https://en.wikipedia.org/wiki/Curiious_ ... te_pattern) не работает, поскольку при этом будет удален общий базовый класс/тип интерфейса, который может храниться в очереди Bridge.
шаблон класс База { } Производный класс: Base { } Я также рассматривал std::variant как способ хранения различных типов SigOp в очереди, но в настоящее время я привязан к C++-14 (std::variant появился в C++-17). Кроме того, вариант std::variant, который может хранить все типы SigOp Bridge, а также их возможные полезные нагрузки, будет занимать много памяти (если я не ошибаюсь).
На данный момент у меня есть кусочки, но я не нашел способа склеить их все вместе. Шаблон моста:
шаблон класс BridgeT { // Ставим сигнал в очередь для последующей сериализации и транспортировки по сети с помощью ZMQ шаблон встроенный статический void-пост (const tSignalType &fSignal) { /** * Здесь я знаю все типы, необходимые для полного определения того, как должна выполняться сериализация. * * Таким образом: * * tBridgeDeclType — тип объявления моста. Магазины этого типа * отношения к типам ниже. * * typename tBridgeDeclType::SigOpTypes — std::tuple со списком всех типов SigOp * поддерживается мостом * * tSignalType — конкретный тип SigOp (в данном случае сигнал), который нам нужен. * для постановки в мосты исходящей очереди SigOp (см. ниже). * * Эта настройка в фоновом режиме обеспечивает безопасность типов, поэтому только SigOps * явная поддержка конкретного типа моста может быть опубликована и передана *у моста. Использование неподдерживаемого SigOps приводит к ошибке компиляции. */ // Как совместить это со специфичным для типа SigOp // SerializableSigOpT все еще может использовать // Тип слота очереди SigOp, общий для моста? // Ставим в очередь SigOp очередь.push(fSignal); } статическая очередь std::queue; }; И шаблон сериализатора SigOp, который перенаправляет на правильный код сериализации во время компиляции:
шаблон класс SerializableSigOpT: public SigOpT { публика: inline static void initSerialization(SigOpSerDes &fSigOpSerializer, const SigOpSeqNumType fSeqNumber, SerializationBuffer &fSerBuffer) { fSigOpSerializer.initSerialization(getSigOpTypeIdT::cId, fSeqNumber, fSerBuffer); } встроенная статическая сила сериализацииPayLoad (const tSigOpType &fSigOp, SigOpSerDes &fSigOpSerializer) { // Сериализуем полезную нагрузку, если она существует. Это условный шаблон, который не компилируется без кода, когда у SigOp нет полезной нагрузки. PayLoadSerDesT::serializePayLoad(fSigOp, fSigOpSerializer); } }; Можно ли это сделать, используя шаблоны C++, или это одна из тех вещей, которые на первый взгляд кажутся такими простыми, но когда вы вникаете в детали, появляется дьявол???
/Нильс
Я работаю над структурой для системного проектирования на основе моделей (MBSE). Здесь у меня есть конструкция под названием Bridge. Мост может отправлять Сигналы (асинхронные вызовы) и/или Операции (синхронные вызовы) с одного конца Моста на другой. Сигналы и операции также могут иметь полезную нагрузку, определенную конечным пользователем платформы (другим программистом на C++).
Мост подключен к сети, поэтому вход моста подключается к выходу моста через сетевой сокет. Чтобы это работало, необходимо сериализовать сигналы и/или операции (сокращенно SigOps), а также возможную полезную нагрузку.
У моста есть исходящая очередь, которая буферизует и сохраняет последовательность SigOp по мере их выдачи. Следовательно, эта очередь хранит SigOps, используя общие указатели SigOp. Но все равно необходимо использовать специальный сериализатор типа SigOp.
Обычный способ сделать это — использовать виртуальный базовый класс, определяющий интерфейс, а затем позволить производному классу добавить реализацию. Что-то вроде:
// Виртуальный базовый класс/интерфейс SigOp, специфичный для типа моста шаблон класс СигОпТ { публика: виртуальная пустота initSerialization (SigOpSerDes &fSerializer, SerializationBuffer &fSerializationBuffer) = 0; виртуальная пустота сериализоватьPayLoad (SigOpSerDes &fSigOpSerializer) = 0; }; шаблон класс MySigOp: public SigOpT { void initSerialization(SigOpSerDes &fSerializer, SerializationBuffer &fSerializationBuffer) переопределить окончательный вариант { // Моя реализация ... } voidserializePayLoad(SigOpSerDes &fSigOpSerializer) переопределенный финал { // Мой код сериализации, специфичный для MySigOp ... } }; На вопрос: Есть ли способ сделать то же самое во время компиляции, исключив тем самым виртуальные функции, виртуальные таблицы и т. д.?
CRTP (https://en.wikipedia.org/wiki/Curiious_ ... te_pattern) не работает, поскольку при этом будет удален общий базовый класс/тип интерфейса, который может храниться в очереди Bridge.
шаблон класс База { } Производный класс: Base { } Я также рассматривал std::variant как способ хранения различных типов SigOp в очереди, но в настоящее время я привязан к C++-14 (std::variant появился в C++-17). Кроме того, вариант std::variant, который может хранить все типы SigOp Bridge, а также их возможные полезные нагрузки, будет занимать много памяти (если я не ошибаюсь).
На данный момент у меня есть кусочки, но я не нашел способа склеить их все вместе. Шаблон моста:
шаблон класс BridgeT { // Ставим сигнал в очередь для последующей сериализации и транспортировки по сети с помощью ZMQ шаблон встроенный статический void-пост (const tSignalType &fSignal) { /** * Здесь я знаю все типы, необходимые для полного определения того, как должна выполняться сериализация. * * Таким образом: * * tBridgeDeclType — тип объявления моста. Магазины этого типа * отношения к типам ниже. * * typename tBridgeDeclType::SigOpTypes — std::tuple со списком всех типов SigOp * поддерживается мостом * * tSignalType — конкретный тип SigOp (в данном случае сигнал), который нам нужен. * для постановки в мосты исходящей очереди SigOp (см. ниже). * * Эта настройка в фоновом режиме обеспечивает безопасность типов, поэтому только SigOps * явная поддержка конкретного типа моста может быть опубликована и передана *у моста. Использование неподдерживаемого SigOps приводит к ошибке компиляции. */ // Как совместить это со специфичным для типа SigOp // SerializableSigOpT все еще может использовать // Тип слота очереди SigOp, общий для моста? // Ставим в очередь SigOp очередь.push(fSignal); } статическая очередь std::queue; }; И шаблон сериализатора SigOp, который перенаправляет на правильный код сериализации во время компиляции:
шаблон класс SerializableSigOpT: public SigOpT { публика: inline static void initSerialization(SigOpSerDes &fSigOpSerializer, const SigOpSeqNumType fSeqNumber, SerializationBuffer &fSerBuffer) { fSigOpSerializer.initSerialization(getSigOpTypeIdT::cId, fSeqNumber, fSerBuffer); } встроенная статическая сила сериализацииPayLoad (const tSigOpType &fSigOp, SigOpSerDes &fSigOpSerializer) { // Сериализуем полезную нагрузку, если она существует. Это условный шаблон, который не компилируется без кода, когда у SigOp нет полезной нагрузки. PayLoadSerDesT::serializePayLoad(fSigOp, fSigOpSerializer); } }; Можно ли это сделать, используя шаблоны C++, или это одна из тех вещей, которые на первый взгляд кажутся такими простыми, но когда вы вникаете в детали, появляется дьявол???
/Нильс
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Почему в C++ я не могу взять адрес функции, у которой также есть шаблонная версия?
Anonymous » » в форуме C++ - 0 Ответы
- 15 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как скрыть метод базового класса из производного класса при вызове внутри базового класса?
Anonymous » » в форуме C# - 0 Ответы
- 57 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как скрыть метод базового класса из производного класса при вызове внутри базового класса?
Anonymous » » в форуме C# - 0 Ответы
- 46 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как скрыть метод базового класса из производного класса при вызове внутри базового класса?
Anonymous » » в форуме C# - 0 Ответы
- 38 Просмотры
-
Последнее сообщение Anonymous
-