You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用编译时模板实现虚基类式接口以消除虚函数?

编译时实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:05:58