stophin 2024-06-06 12:45 采纳率: 42.9%
浏览 6

如何将模板类数据保存到一个map中

我定义了一个log收集的模板函数和一个表

template<typename T> map<const char*, T> logMap;
template<typename T>
collectLog(const char* name, T value) {
    logMap<T>[name] = value;
}

本来使用模板就是为了防止重载各种T类型的写法,但是到了将收集的log全部打出来时就出现问题了

for (auto& log : logMap) {
//print log
}

错误来自于logMap,这里logMap已经不是一个了而是多个表logMap<int>,logMap<double>等等
这样就回到了最初问题,我还是需要对各种类型重载来遍历logMap<T>以打印收集的log
请问有没有方法让这个程序只保存一张表,一次遍历达到目的?

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-06-06 12:45
    关注

    引自免费微信小程序:皆我百晓生

    为了实现一个可以存储任意类型模板数据且能在后续遍历输出的logMap,你需要稍微调整一下你的设计。首先,你需要创建一个基类(例如LogBase)来作为所有类型T的共同父类,然后为每种类型创建一个派生类。接着,使用std::variant来存储不同类型的值,并在容器中存储这些变体的指针。

    以下是修改后的代码:

    #include <iostream>
    #include <map>
    #include <string>
    #include <variant>
    
    class LogBase {};
    
    template <typename T>
    class Log final : public LogBase {
    public:
        explicit Log(const std::string& name, T value) : name(name), value(value) {}
    
        const std::string& getName() const { return name; }
        T getValue() const { return value; }
    
    private:
        std::string name;
        T value;
    };
    
    using LogVariant = std::variant<std::unique_ptr<Log<int>>, std::unique_ptr<Log<double>>, std::unique_ptr<Log<std::string>>>;
    using LogMap = std::map<const char*, LogVariant>;
    
    template <typename T>
    void collectLog(const char* name, T value) {
        auto log = std::make_unique<Log<T>>(name, value);
        logMap[name] = std::move(log);
    }
    
    void printLogs(const LogMap& logMap) {
        for (const auto& entry : logMap) {
            const auto& log = std::get<0>(entry.second); // 0对应的是std::unique_ptr<LogBase>
            std::cout << "Name: " << log.getName() << ", Value: ";
            if (std::holds_alternative<std::unique_ptr<Log<int>>>(entry.second)) {
                std::cout << std::get<std::unique_ptr<Log<int>>>(entry.second)->getValue();
            } else if (std::holds_alternative<std::unique_ptr<Log<double>>>(entry.second)) {
                std::cout << std::get<std::unique_ptr<Log<double>>>(entry.second)->getValue();
            } else if (std::holds_alternative<std::unique_ptr<Log<std::string>>>(entry.second)) {
                std::cout << std::get<std::unique_ptr<Log<std::string>>>(entry.second)->getValue();
            }
            std::cout << std::endl;
        }
    }
    
    int main() {
        collectLog("IntLog", 42);
        collectLog("DoubleLog", 3.14);
        collectLog("StringLog", "Hello, World!");
    
        printLogs(logMap);
    
        return 0;
    }
    

    在这个例子中,我们使用了C++17的std::variant来存储不同类型的数据,并通过std::unique_ptr<LogBase>来确保类型安全。在遍历logMap时,我们可以根据变体中的类型动态地访问并打印出每个日志的名称和值。当然,这只是一个基础示例,如果你需要支持更多类型,只需添加相应的派生类和变体类型即可。

    评论 编辑记录

报告相同问题?

问题事件

  • 修改了问题 6月6日
  • 创建了问题 6月6日

悬赏问题

  • ¥20 gitlab 中文路径,无法下载
  • ¥15 用动态规划算法均分纸牌
  • ¥30 udp socket,bind 0.0.0.0 ,如何自动选取用户访问的服务器IP来回复数据
  • ¥15 关于树的路径求解问题
  • ¥15 yolo在训练时候出现File "D:\yolo\yolov5-7.0\train.py"line 638,in <module>
  • ¥30 戴尔inspiron独显直连
  • ¥15 进行一项代码设计遇到问题
  • ¥15 Mutisim中关于74LS192N计数器芯片设计(计数器)
  • ¥50 fastadmin后台无法删除文件
  • ¥15 oracle查询Socket read timed out错误