Qt SIGNAL的体系结构,具有特定于子类的模板化参数类型

Bar*_*ark 9 c++ templates qt4 signals-slots

我正在使用Qt开发一个科学数据采集应用程序.由于我不是Qt的深度专家,我想从社区建议一些关于以下问题的建筑:

该应用程序支持多个硬件采集接口,但我想在这些接口之上提供通用API.每个接口都有一个样本数据类型和一个数据单位.所以我将每个设备的样本矢量表示std::vector为Boost.Units数量(即std::vector<boost::units::quantity<unit,sample_type> >).我想使用多播式架构,其中每个数据源将新接收的数据广播给一个或多个感兴趣的各方.Qt的信号/插槽机制非常适合这种风格.所以,我希望每个数据源发出一个信号

typedef std::vector<boost::units::quantity<unit,sample_type> > SampleVector
signals:
    void samplesAcquired(SampleVector sampleVector);
Run Code Online (Sandbox Code Playgroud)

适用于该设备的unit和sample_type.由于QObject元对象编译器不支持tempalted 子类,因此似乎没有办法为定义samplesAcquiredSignal的所有数据源都有一个(tempalted)基类.换句话说,下面将不工作:

template<T,U> //sample type and units
class DataSource : public QObject {
  Q_OBJECT
  ...
  public:
    typedef std::vector<boost::units::quantity<U,T> > SampleVector
  signals:
    void samplesAcquired(SampleVector sampleVector);
};
Run Code Online (Sandbox Code Playgroud)

我能够提出的最佳选择是双层方法:

template<T,U> //sample type and units
class IAcquiredSamples {
    public:
        typedef std::vector<boost::units::quantity<U,T> > SampleVector
        virtual shared_ptr<SampleVector> acquiredData(TimeStamp ts, unsigned long nsamples);
};

class DataSource : public QObject {
    ...
    signals:
      void samplesAcquired(TimeStamp ts, unsigned long nsamples);
};
Run Code Online (Sandbox Code Playgroud)

samplesAcquired信号现在给样本的时间戳和数量进行收购和客户端必须使用IAcquiredSamplesAPI来检索这些样品.显然,数据源必须是DataSource和IAcquiredSamples.

这种方法的缺点似乎是API中的简单性损失......如果客户端可以在连接的Slot中获取采集的样本,那将会更好.能够使用Qt的排队连接也会使线程问题更容易,而不必acquiredData在每个子类中的方法中管理它们.

另一种可能性是使用一个QVariant参数.这必然要求子类使用Q_REGISTER_METATYPE/ 来注册它们的特定样本向量类型qRegisterMetaType.没什么大不了的.但是,基类的客户端将无法知道QVariant值类型的类型,除非标签结构也与信号一起传递.我认为这个解决方案至少与上面的解决方案一样复杂,因为它强制抽象基类API的客户端处理类型系统的一些更加粗糙的方面.

那么,有没有办法实现模板化信号参数?有没有比我提出的更好的架构?

小智 2

有 QVariant 类型 - 您可以在其上创建自定义子类型
并将其用作信号中的参数(如果我理解您的权利,这就是您想要的)
http://doc.trolltech.com/qq/qq14-metatypes .html#customtypesinqvariant