Как заставить два параметра функции иметь один и тот же тип шаблона? - PullRequest
0 голосов
/ 09 мая 2019

Я пытаюсь создать реестр, в котором я могу зарегистрировать датчики с соответствующими этапами обработки датчиков.

TLDR: Как заставить два параметра функции иметь общий параметр шаблона / тип элемента, где оба наследуются от абстрактных классов и могут быть помещены в коллекции, которые принимают любые объекты, производные от этих абстрактных классов?

В идеале я бы хотел что-то вроде этого

// registry
map<string, Sensor> sensors;
map<string, SensorProcessing> processors;

// sensor base class
class Sensor
{
    virtual Data sense();
}

// processing base class
class SensorProcessing
{
    virtual void process(Data d);
}

// data kind base class
struct Data { string name; }

, где Sensor и SensorProcessing - абстрактные типы. В идеале, коллекция должна принимать любой производный тип датчика или обработки.

Когда я регистрирую датчик и этап обработки, я хотел бы обеспечить, чтобы объект SensorProcessing мог обрабатывать данные, полученные объектом Sensor, с которым он зарегистрирован. Например, не имеет смысла связывать этап обработки, работающий с изображениями, с датчиком, который выдает лазерное сканирование.

Как-то так для регистрации было бы неплохо:

void register_sensor(string name, Sensor s, SensorProcessing p)
{
    // enforce that p eats what s produces, in a typesafe but polymorphic manner
    static_assert(std::is_same<s::data_type, p::data_type>);
}

Но, конечно, все не так просто, потому что аргументы register_sensor() являются базовыми типами, и я не могу во время компиляции проверить, что они согласуются с типом данных, который они используют, без шаблонов. Однако я не уверен, как это сделать, а также помещать датчики и процессоры в свои собственные иерархии классов.

Ответы [ 2 ]

2 голосов
/ 09 мая 2019

Вы можете проверить тип данных во время компиляции, если создадите указатель внутри вызова функции:

template <typename TSensor, typename TProcessing, typename = std::enable_if_t<std::is_base_of_v<Sensor, TSensor> && std::is_base_of_v<SensorProcessing, TProcessing>>>
void register_sensor(std::string const& name, TSensor s, TProcessing p)
{
    // enforce that p eats what s produces, in a typesafe but polymorphic manner
    static_assert(std::is_same_v<typename TSensor::data_type, typename TProcessing::data_type>, "Data type missmatch");

    // create the pointers here and move s and p in
}

Обратите внимание, что это создаст копию объектов Sensor и SensorProcessing, которые вы передаете.

Здесь - возможная реализация. Я не уверен, что вы пытаетесь достичь с помощью контейнера, который вы описали, поэтому я выбрал тот, который имеет смысл с моей точки зрения.

0 голосов
/ 09 мая 2019

Есть несколько вариантов.

  • Использование IDispatch или что-то в этом роде, если не под Windows
  • Использование std :: any (C ++ 17)
  • Использование интерфейсов на основе COM, регистрация COM и библиотека типов для обработки всего, что уже сделано для вас.
  • Использование сериализуемых объектов в общих форматах (JSON, XML).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...