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

如何实现可直接声明的带固定初始化的模板类变体?

问题描述

开发多类编码器,核心差异在于初始化类时使用的数据结构不同。现有代码如下,希望通过rdTagEncode myEncode;的简洁形式在其他代码中声明编码器,但无法找到正确语法。

头文件代码

struct tagTypeInfo {
        uint16_t start;
        uint16_t last;
        uint16_t count;
        std::string name;
        rdwrT rdwr;
};

template <typename T>
class encodedTag
{
public:
    encodedTag(vector<tagTypeInfo> tagInfo_) : tagInfo(tagInfo_)
    {
        int start = 0;
        for(auto & tag : tagInfo)
        {
            tag.start = start;
            tag.last = start + tag.count - 1;
            start = start + tag.count;
        }
    }

    uint16_t encode(uint16_t tag, T tagType)
    {
        assert(tag<tagInfo[tagType].count);
        return( tagInfo[tagType].start + tag );
    }
    std::tuple<uint16_t, T> decode(uint16_t encodedTag)
    {
        int type = 0;
        uint16_t tag;
        // simple linear search as there are only a few entries
        for (auto it = begin(tagInfo); it != end(tagInfo); it++)
        {
            if (encodedTag >= it->start && encodedTag < it->last )
            {
                // tag is in the range
                return {encodedTag - it->start , (T)type};
            }
            type++;
        }
        assert(false);    
        return {0,(T)0};
    }
    std::string getName(T tagType) {return(tagInfo[tagType].name);}
    rdwrT getRdwr(T tagType) {return(tagInfo[tagType].rdwr);}
private:
    std::vector<tagTypeInfo> tagInfo;
};

extern std::vector<tagTypeInfo> rdTag;
extern std::vector<tagTypeInfo> wrTag;

//using rdTagEncode = encodedTag<rdTagT>(rdTag) <-- error

cpp文件代码

std::vector<tagTypeInfo> rdTag {
        {0, 0, NUM_HOSTRDTAG,        "HostRdTag",    RDWR_RD},
        {0, 0, NUM_SYSRDTAG,         "SysRdTag",     RDWR_RD},
        {0, 0, NUM_GCRDTAG,          "GCRdTag",      RDWR_RD}
    };

std::vector<tagTypeInfo> wrTag {
        {0, 0, NUM_HOSTWRTAG,        "HostWrTag",    RDWR_WR},
        {0, 0, NUM_SYSWRTAG,         "SysWrTag",     RDWR_WR},
        {0, 0, NUM_GCWRTAG,          "GCWrTag",      RDWR_WR}
    };

解决方案

using关键字仅用于定义类型别名,无法直接绑定类实例化时的构造参数,因此原写法不成立。以下两种方法可实现你的需求:

方法1:全局实例直接调用

步骤1:头文件声明全局实例

在头文件末尾添加:

extern encodedTag<rdTagT> rdTagEncoder;

步骤2:cpp文件初始化实例

在cpp文件末尾添加:

encodedTag<rdTagT> rdTagEncoder(rdTag);

使用方式

其他代码中无需声明新对象,直接调用全局实例即可:

// 编码示例
uint16_t encoded = rdTagEncoder.encode(0, rdTagT::Host);
// 解码示例
auto [tag, type] = rdTagEncoder.decode(encoded);

方法2:模板绑定数据结构,实现类别名声明

通过修改模板类,将数据结构的指针作为模板参数,从而用using定义绑定了特定数据的类型别名。

步骤1:修改模板类定义

template <typename T, const std::vector<tagTypeInfo>* TagInfoPtr>
class encodedTag
{
public:
    encodedTag() : tagInfo(*TagInfoPtr)
    {
        int start = 0;
        for(auto & tag : tagInfo)
        {
            tag.start = start;
            tag.last = start + tag.count - 1;
            start = start + tag.count;
        }
    }

    // 其余成员函数与原代码一致...
private:
    std::vector<tagTypeInfo> tagInfo;
};

步骤2:头文件定义类型别名

extern std::vector<tagTypeInfo> rdTag;
// 定义绑定rdTag的类型别名
using rdTagEncode = encodedTag<rdTagT, &rdTag>;

使用方式

现在可以通过简洁的声明创建对象:

rdTagEncode myEncode;
// 调用示例
uint16_t encoded = myEncode.encode(1, rdTagT::Sys);

额外修复提示

原decode函数的判断条件存在逻辑漏洞:encodedTag < it->last会漏掉等于last的合法标签,应修改为:

if (encodedTag >= it->start && encodedTag <= it->last )

内容的提问来源于stack exchange,提问作者Andy Tomlin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:30:56