C++使用std::variant作为unordered_map值类型插入时运行挂起问题
问题成因
- 核心问题是nlohmann::json的泛型隐式转换逻辑与std::variant构造逻辑冲突:代码中直接将json对象传入vector初始化列表构造variant时,编译器无法匹配到最优的类型转换路径,会触发无限递归的类型转换尝试,最终栈溢出导致程序被系统杀死。
- 本次崩溃刚好出现在key为
t的场景,是因为该key对应的值为大整数1608008400000,刚好处于long、double两种类型的可表示范围重叠区间,进一步加剧了类型匹配的歧义性。
解决方法
完全规避隐式转换,先判断json值的实际类型,显式转换为variant对应的备选类型后再存入容器即可,修改后的代码如下:
#include <nlohmann/json.hpp> #include <unordered_map> #include <variant> #include <iostream> #include <string> #include <cstdint> using json = nlohmann::json; int main() { // 可选优化:将long替换为int64_t,适配所有平台的大整数场景,避免溢出 using ValueVariant = std::variant<double, long, std::string>; std::unordered_map<std::string, std::vector<ValueVariant>> mp; json input = "{ \"happy\": \"yes\", \"pi\": 3.141, \"t\": 1608008400000 }"_json; for(auto& el : input.items()) { if (mp.find(el.key()) != mp.end()) { continue; } std::cout << "trying insertion for key " << el.key() << std::endl; ValueVariant val; if (el.value().is_string()) { val = el.value().get<std::string>(); } else if (el.value().is_integer()) { val = static_cast<long>(el.value().get<int64_t>()); } else if (el.value().is_number_float()) { val = el.value().get<double>(); } mp.insert({ el.key(), std::vector<ValueVariant>{val} }); std::cout << "inserted " << el.key() << " successfully!" << std::endl; } return 0; }
额外优化建议
如果你的业务场景需要处理跨平台的大整数值,可直接将variant中的long替换为std::int64_t,完全避免整数溢出风险。
内容的提问来源于stack exchange,提问作者idm2114
相关产品推荐
相关产品推荐

