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

如何在结构体中存储模板数据类型以调用PubSub注册方法?

如何存储数据类型供后续模板方法批量调用?

我们使用一套基于模板方法的PubSub框架,需通过RegisterTopic<T>(std::string topicName)注册主题,模板参数T用于标识发布/订阅的数据类型。我希望创建主题配置列表存储主题名称与对应数据类型,最初的结构体设计如下:

struct RegistrationTopicType
{
    std::string name;
    int type;  // 需替换为可存储数据类型的机制
};

目标是生成主题列表后批量调用模板注册方法:

std::vector<RegistrationTopicType> topicList = {
    {"topic1", MyClass},
    {"topic2", MyOtherClass}, // 依此类推
};

for (auto & topic : topicList) {
  RegisterTopic<topic.type>(topic.name);
}

我尝试过用模板结构体存储类型:

template<typename T>
struct TemplatedRegistrationTopic
{
    using DataType       = T;
    std::string name;
};

但实例化后无法将DataType作为模板参数传入RegisterTopic,RegisterTopic<topic.DataType>(topic.name)和Register<topic::DataType>(topic.name)均失败。暂不考虑不同类型主题存入统一列表的问题,请问能否实现“存储数据类型供后续模板方法使用”?另外我不想用枚举+switch方案(如下),因为需维护类型与枚举的映射,违背模板初衷:

enum typelist { Type1, Type2 }; // 每个主题类型对应一个枚举值

struct EnumRegistrationTopicType
{
    std::string name;
    typelist type;
};

std::vector<EnumRegistrationTopicType> enumTopicList = {
    {"topic1", Type1},
    {"topic2", Type2}, // 依此类推
};

for (auto & topic : enumTopicList) {
  switch (topic.type) {
  case typelist::Type1:
    RegisterTopic<MyClass1>(topic.name);
    break;
  case typelist::Type2:
    RegisterTopic<MyClass2>(topic.name);
    break;
  }
}

可行方案:类型擦除+函数对象封装注册逻辑

核心思路是将“特定类型的注册调用”封装成无类型依赖的函数对象,存入列表后直接遍历执行,绕开模板参数必须为编译期常量的限制。

基础实现

直接用std::function<void()>存储封装好的注册操作:

#include <vector>
#include <functional>
#include <string>

// 假设的PubSub框架注册函数
template<typename T>
void RegisterTopic(const std::string& topicName) {
    // 框架注册逻辑...
}

class MyClass {};
class MyOtherClass {};

int main() {
    // 存储批量注册操作
    std::vector<std::function<void()>> topicRegistrations = {
        [](){ RegisterTopic<MyClass>("topic1"); },
        [](){ RegisterTopic<MyOtherClass>("topic2"); },
        // 可继续添加更多主题
    };

    // 批量执行注册
    for (auto& reg : topicRegistrations) {
        reg();
    }

    return 0;
}

进阶优化:统一管理主题名称与注册逻辑

如果需要同时保留主题名称(用于后续查询等场景),可定义结构体封装:

struct TopicRegistration
{
    std::string name;
    std::function<void()> registerFunc;
};

std::vector<TopicRegistration> topicList = {
    {"topic1", [](){ RegisterTopic<MyClass>("topic1"); }},
    {"topic2", [](){ RegisterTopic<MyOtherClass>("topic2"); }},
};

// 批量注册
for (auto& topic : topicList) {
    topic.registerFunc();
}

原方案失败原因

模板结构体TemplatedRegistrationTopic<T>的DataType是编译期绑定的类型别名,每个实例化的结构体都是独立类型(比如TemplatedRegistrationTopic<MyClass>与TemplatedRegistrationTopic<MyOtherClass>完全不同),无法存入同一vector。即便绕过存储问题,topic.DataType是运行时对象的成员类型别名,而模板参数要求是编译期可知的常量,因此无法在for循环中直接作为RegisterTopic的模板参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:55:23