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

如何向C++中存储std::variant的std::map添加键值对

解决无默认构造函数的std::variant存入std::map的问题

问题场景

想要使用std::map<std::string, std::variant<A, B>>存储对象,其中A、B类仅提供带参数的构造函数(无默认构造函数),尝试插入键值对时编译报错。简化示例代码如下:

class A {
    public:
        A(int x): x_(x) { std::cout << "A" << std::endl;}
        int x_;
        void print() {std::cout << 2 * x_ << std::endl;}
};

class B {
    public:
        B (int x): x_(x) { std::cout << "B" << std::endl;}
        int x_;
        void print() {std::cout << 5* x_ << std::endl; }
};

int main()
{
    using var_t = std::variant<A, B>;
    std::map<std::string, var_t> my_map;
    var_t v {std::in_place_type<A>, 3};
    //my_map["a"] = v; // none of these work
    //my_map.emplace("a", v);// 
    my_map.insert({"a", v});
    std::visit([](auto&& var) { var.print();}, my_map["a"]);
}

编译错误信息

usr/local/include/c++/13.1.0/tuple:2254:9: error: use of deleted function 'std::variant<_Types>::variant() [with _Types = {A, B}]'
 2254 |         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

错误原因

std::variant<A,B>没有默认构造函数——因为A和B都未定义默认构造函数,编译器会删除variant的默认构造函数。而std::map的operator[]在键不存在时,会尝试默认构造对应的值类型作为该键的默认值,这就触发了上述错误。哪怕你之前用insert或emplace插入过该键,后续误用operator[]仍可能触发这个问题。

正确实现方式

1. 替换operator[]为安全访问方法

访问已插入的元素时,改用std::map::at()方法(键不存在时抛出异常,而非尝试默认构造),或者先用find()检查键是否存在:

// 使用at()安全访问已存在的键
std::visit([](auto&& var) { var.print();}, my_map.at("a"));

// 或者用find()检查后访问
auto it = my_map.find("a");
if (it != my_map.end()) {
    std::visit([](auto&& var) { var.print();}, it->second);
}

2. 高效插入:直接在map中构造variant

不需要先构造独立的var_t对象再插入,可直接在map内部构造variant,减少不必要的拷贝:

// 直接构造A类型的variant并存入map
my_map.emplace("a", std::in_place_type<A>, 3);

// 直接构造B类型的variant并存入map
my_map.emplace("b", std::in_place_type<B>, 4);

修复后的完整代码

class A {
    public:
        A(int x): x_(x) { std::cout << "A" << std::endl;}
        int x_;
        void print() {std::cout << 2 * x_ << std::endl;}
};

class B {
    public:
        B (int x): x_(x) { std::cout << "B" << std::endl;}
        int x_;
        void print() {std::cout << 5* x_ << std::endl; }
};

int main()
{
    using var_t = std::variant<A, B>;
    std::map<std::string, var_t> my_map;

    // 直接在map内部构造variant
    my_map.emplace("a", std::in_place_type<A>, 3);
    my_map.emplace("b", std::in_place_type<B>, 4);

    // 使用at()安全访问
    std::visit([](auto&& var) { var.print();}, my_map.at("a"));
    std::visit([](auto&& var) { var.print();}, my_map.at("b"));

    // 或者用find()检查后访问
    auto it = my_map.find("a");
    if (it != my_map.end()) {
        std::visit([](auto&& var) { var.print();}, it->second);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:04:56