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

如何通过函数返回std::map<int, std::variant>中对应键的值?

问题描述

我希望用std::map存储不同类型的值,定义了这样的容器:

std::map<int, std::variant<int, std::string>> m ={{1,1},{2,"asd"}};

现在想设计一个函数,通过键获取对应的值,函数形式如下:

auto get(int key) {
    ...
    return value;
}

预期效果:

get(1) -> 1
get(2) -> "asd"

请问这是否可行?若可行,具体实现方案是什么?

补充说明:
该设计用于存储从配置文件读取的配置数据,读取后需要进行类型转换或数据变换。例如配置文件内容如下:

a=1
b=asd

读取后需处理为:
m["a"]=int(3)(对应配置a=1,读取后数值加2)
m["b"]=std::string("asdasd")(对应配置b=asd,读取后字符串翻倍)
因此我认为若有一个接口函数通过键获取准确值会更便捷。


可行方案实现

这完全可行,核心是利用std::variant的访问机制,结合C++的类型推导和模板特性实现。以下是几种适配不同场景的实现方式:

方式一:返回std::variant,由调用方处理类型

这是最直接的实现,返回值保留std::variant类型,让调用方根据需求处理不同类型:

#include <map>
#include <variant>
#include <string>
#include <stdexcept>

std::map<int, std::variant<int, std::string>> m = {{1, 1}, {2, "asd"}};

std::variant<int, std::string> get(int key) {
    auto it = m.find(key);
    if (it != m.end()) {
        return it->second;
    }
    // 键不存在时抛出异常,也可返回默认构造的variant
    throw std::out_of_range("Key not found in config map");
}

调用时用std::visit分支处理类型:

int main() {
    auto val = get(1);
    std::visit([](auto&& arg) {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<T, int>) {
            // 处理整数类型逻辑
        } else if constexpr (std::is_same_v<T, std::string>) {
            // 处理字符串类型逻辑
        }
    }, val);
}

方式二:模板函数,指定返回类型

如果调用方明确知道目标值的类型,可以实现模板函数,强制获取指定类型的值:

#include <map>
#include <variant>
#include <string>
#include <stdexcept>

std::map<int, std::variant<int, std::string>> m = {{1, 1}, {2, "asd"}};

template<typename T>
T get(int key) {
    auto it = m.find(key);
    if (it == m.end()) {
        throw std::out_of_range("Key not found");
    }
    // 尝试获取指定类型,失败则抛出bad_variant_access异常
    if (auto* ptr = std::get_if<T>(&it->second)) {
        return *ptr;
    }
    throw std::bad_variant_access();
}

调用示例:

int main() {
    int num = get<int>(1); // 得到int类型的1
    std::string str = get<std::string>(2); // 得到std::string类型的"asd"
}

方式三:自动推导返回类型(C++17及以上)

针对配置项类型固定的场景(每个键对应唯一类型),可以让函数自动推导返回类型,无需调用方显式指定:

#include <map>
#include <variant>
#include <string>
#include <stdexcept>

std::map<int, std::variant<int, std::string>> m = {{1, 1}, {2, "asd"}};

auto get(int key) {
    auto it = m.find(key);
    if (it == m.end()) {
        throw std::out_of_range("Key not found");
    }
    // 通过std::visit转发原始值,编译器自动推导返回类型
    return std::visit([](auto&& arg) -> decltype(auto) {
        return std::forward<decltype(arg)>(arg);
    }, it->second);
}

调用时编译器会自动匹配返回类型:

int main() {
    auto num = get(1); // num类型为int
    auto str = get(2); // str类型为std::string
}

这种方式仅适用于键与类型一一对应的场景,完全匹配你读取配置文件的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:50:38