能否用编译时模板实现虚基类式接口以消除虚函数?
编译时实现MBSE框架Bridge组件的SigOp序列化逻辑(消除虚函数开销)
我正在开发基于模型的系统工程(MBSE)框架,其中包含名为Bridge的组件。Bridge可通过网络套接字异步发送Signal、同步发送Operation(二者合称SigOp),且SigOp可携带由C++开发者定义的载荷,需要进行序列化处理。
Bridge的输出队列需要存储通用SigOp指针以保留发送顺序,但仍需调用SigOp类型专属的序列化逻辑。常规方案是用虚基类定义接口,派生类实现具体逻辑:
// 特定Bridge类型的SigOp虚基类/接口 template <class tBridgeDeclType> class SigOpT { public: virtual void initSerialization(SigOpSerDes &fSerializer, SerializationBuffer &fSerializationBuffer) = 0; virtual void serializePayLoad(SigOpSerDes &fSigOpSerializer) = 0; }; template <class tBridgeDeclType> class MySigOp : public SigOpT<tBridgeDeclType> { void initSerialization(SigOpSerDes &fSerializer, SerializationBuffer &fSerializationBuffer) override final { // 自定义实现 ... } void serializePayLoad(SigOpSerDes &fSigOpSerializer) override final { // MySigOp<tBridgeDeclType>专属的序列化代码 ... } };
核心问题:能否在编译时实现相同逻辑,从而消除虚函数、虚表等运行时开销?
我尝试过奇异递归模板模式(CRTP),但它无法提供可存入Bridge队列的通用基类类型,因此不可行:
template <typename tDerived> class Base { }; class Derived : Base<Derived> { };
我也曾考虑用std::variant存储不同SigOp类型,但受限于C14标准(std::variant在C17中才引入),且担心存储所有SigOp类型及载荷会占用大量内存(若我的理解有误请指正)。
目前我已实现了相关组件模板,但无法将它们整合起来:
Bridge模板
template <class tBridgeDeclType> class BridgeT { // 将Signal加入队列,后续通过ZMQ序列化并网络传输 template <class tSignalType> inline static void post(const tSignalType &fSignal) { /** * 此处我已掌握序列化所需的全部类型信息: * * tBridgeDeclType - Bridge声明类型,存储了与以下类型的关联关系 * * typename tBridgeDeclType::SigOpTypes - 一个std::tuple<>,列出该Bridge支持的所有SigOp类型 * * tSignalType - 要加入Bridge输出队列的特定SigOp类型(此处为Signal) * * 这套机制在后台提供了类型安全:只有该Bridge明确支持的SigOp才能被提交和传输, * 使用不支持的SigOp会触发编译错误。 */ // 如何将其与SigOp类型专属的SerializableSigOpT<tBridgeDeclType, tSigOpType>结合, // 同时仍能使用Bridge通用的SigOp队列槽位类型? // 将SigOp加入队列 queue.push(fSignal); } static std::queue<SigOpT<tBridgeDeclType>> queue; };
编译时重定向至对应序列化逻辑的SigOp序列化器模板
template <class tBridgeDeclType, class tSigOpType> class SerializableSigOpT : public SigOpT<tBridgeDeclType> { public: inline static void initSerialization(SigOpSerDes &fSigOpSerializer, const SigOpSeqNumType fSeqNumber, SerializationBuffer &fSerBuffer) { fSigOpSerializer.initSerialization(getSigOpTypeIdT<typename tBridgeDeclType::SigOpTypes, tSigOpType>::cId, fSeqNumber, fSerBuffer); } inline static void serializePayLoad(const tSigOpType &fSigOp, SigOpSerDes &fSigOpSerializer) { // 当SigOp存在载荷时序列化载荷。这是一个条件模板,无载荷时会编译为空代码。 PayLoadSerDesT<tBridgeDeclType, tSigOpType, tSigOpType::hasPayLoad()>::serializePayLoad(fSigOp, fSigOpSerializer); } };
请问能否通过C++模板实现该需求,还是看似简单实则存在难以解决的细节问题?
内容的提问来源于stack exchange,提问作者Nilsie
相关产品推荐
相关产品推荐

