【问题标题】:How can I enforce two function parameters have the same template type?如何强制两个函数参数具有相同的模板类型?
【发布时间】:2019-05-09 10:40:43
【问题描述】:

我正在尝试创建一个注册表,我可以在其中注册具有相关传感器处理阶段的传感器。

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; }

其中SensorSensorProcessing 是抽象类型。 理想情况下,集合应该接受任何派生类型的传感器或处理。

当我注册传感器和处理阶段时,我想强制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() 的参数是基本类型,我无法在编译时检查它们是否同意在没有模板的情况下使用的数据类型。但是,我不确定如何执行此操作,并将传感器和处理器放入它们自己的类层次结构中。

【问题讨论】:

  • 你用的是哪个c++版本?
  • 目前 11,但我愿意接受更新版本的建议。
  • 好吧,如果您可以选择始终使用最新标准,即 c++ 17 atm。
  • 理想情况下,集合应该接受任何派生类型的传感器或处理。映射的值类型需要是基类指针才能使用多态性。 map&lt;string, std::unique_ptr&lt;Sensor&gt;&gt; sensors; 之类的东西。然后,您可以将指向从Sensor 派生的任何类型的对象的指针插入到这样的映射中。
  • 您需要一个 minimal reproducible example 来描述您想要实现的目标。为什么不能将多态参数传递给 register_sensor?对象数据类型是如何确定的?

标签: c++ templates inheritance polymorphism


【解决方案1】:

如果你在函数调用中创建指针,你可以在编译时检查数据类型:

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 对象的副本。

Here 是一种可能的实现方式。我不确定你试图用你描述的容器来实现什么,所以我选择了一个从我的角度来看是有意义的。

【讨论】:

    【解决方案2】:

    有一些选择。

    • 如果不在 Windows 下,请使用 IDispatch 或类似的东西
    • 使用std::any (C++ 17)
    • 使用基于 COM 的接口以及 COM 注册和类型库来处理已经为您完成的所有这些工作。
    • 使用通用格式(JSON、XML)的可序列化对象。

    【讨论】:

      猜你喜欢
      • 2014-11-10
      • 1970-01-01
      • 1970-01-01
      • 2020-06-13
      • 1970-01-01
      • 2011-07-30
      • 1970-01-01
      • 2019-04-15
      • 1970-01-01
      相关资源
      最近更新 更多