基于boost::variant从异构类型Map中无指定返回类型取值的问题
解决Boost Variant Visitor无法返回多类型值的问题
你的代码核心问题在于output visitor的定义不符合Boost Variant的规则:你继承了boost::static_visitor<>(默认返回void),但模板operator()却试图返回任意类型T,这会直接导致编译失败——Boost Static Visitor要求所有重载的operator()返回相同的类型,或者你需要显式指定visitor的返回类型为一个能容纳所有可能类型的变体。
下面提供两种适配你Mongo BSON场景的可行方案:
方案一:让Visitor直接处理BSON插入(推荐)
既然你的最终目的是把键值对插入BSON对象,不如直接在visitor里完成这个操作,彻底避开返回类型不统一的问题:
#include <boost/variant/static_visitor.hpp> #include <bsoncxx/builder/stream/document.hpp> // 假设b是bsoncxx::builder::stream::document类型 struct bson_append_visitor : public boost::static_visitor<> { bsoncxx::builder::stream::document& b; const std::string& key; // 构造函数传入BSON构建器和当前要插入的键 bson_append_visitor(bsoncxx::builder::stream::document& builder, const std::string& k) : b(builder), key(k) {} // 为每个可能的类型重载operator() void operator()(int val) const { b << key << val; } void operator()(double val) const { b << key << val; } void operator()(long long val) const { b << key << val; } void operator()(const std::string& val) const { b << key << val; } }; // 遍历映射时的调用方式 for(auto &x: _keyPairValue) { boost::apply_visitor(bson_append_visitor(b, x.first), x.second); }
这种方式逻辑更直接,每个类型的处理都明确对应BSON的插入操作,也避免了额外的类型转换开销。
方案二:让Visitor返回统一的变体类型
如果你确实需要先获取值再处理,可以让visitor返回你定义的boost::variant类型本身,保证返回类型统一:
#include <boost/variant.hpp> // 先定义你的变体类型别名,方便复用 using VariantType = boost::variant<int, double, long long, std::string>; struct output : public boost::static_visitor<VariantType> { template <typename T> VariantType operator()(T t) const { return t; } }; // 遍历使用时 for(auto &x: _keyPairValue) { VariantType val = boost::apply_visitor(output{}, x.second); // 这里需要你的BSON构建器支持直接接受VariantType,否则还是需要再次访问这个值 b << x.first << val; }
不过这种方式需要BSON构建器能直接处理VariantType,否则还是要二次访问变体,效率不如方案一。
额外注意事项
- 确保包含了正确的Boost头文件:
#include <boost/variant.hpp>和#include <boost/variant/apply_visitor.hpp> - 如果
_keyPairValue中后续新增了其他类型,记得同步在visitor中添加对应的operator()重载,否则编译时会报“找不到匹配的visitor调用”错误
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

