C++中auto返回多类型报错,求转换crow::json::rvalue的解决方案
问题:crow::json::rvalue转换多类型时返回值推导错误
我需要将crow::json::rvalue转换为整数、布尔值或字符串,但编译时出现以下错误:
error: inconsistent deduction for auto return type: ‘int’ and then ‘bool’
报错代码:
auto convertData(const crow::json::rvalue &data) { std::string type = get_type_str(data.t()); if(type == "Number"){ return int(data.i()); } else if(type == "True" || type == "False") { return bool(data.b()); } std::string val = data.s(); return std::string(val); }
编辑补充
现有实现
bsoncxx::document::value doc_value = builder << "id" << count << "name" << reqj["name"].s() << "type" << reqj["type"].s() << "priority" << priority << "expense_type" << reqj["expense_type"].s() << "available" << bool(reqj["available"].b()) << "life" << int(reqj["life"].i()) << "quantity" << int(reqj["quantity"].i()) << finalizer; bsoncxx::document::view docview = doc_value.view(); bsoncxx::stdx::optional<mongocxx::result::insert_one> result = collection.insert_one(docview);
期望实现
bsoncxx::builder::stream::document update_builder; for (auto it = reqj.begin(); it != reqj.end(); ++it) { if(it->key()=="id") continue; update_builder << "$set" << bsoncxx::builder::stream::open_document; update_builder << it->key() << convertData(it->value()); update_builder << bsoncxx::builder::stream::close_document; } bsoncxx::document::value update = update_builder << finalizer; bsoncxx::stdx::optional<mongocxx::result::insert_one> result = collection.insert_one(update_builder()); // The collection.insert_one updates the data in database
解决方案
C++中auto推导函数返回值时,要求所有分支返回同一种类型,你的convertData函数三个分支分别返回int、bool、std::string,类型不统一,因此触发编译错误。结合你给bsoncxx构建器传值的需求,提供两种可行方案:
方案一:直接返回bsoncxx兼容类型
返回bsoncxx::types::bson_value::view_or_value,这是bsoncxx流构建器原生支持的类型,无需额外适配:
#include <bsoncxx/types.hpp> bsoncxx::types::bson_value::view_or_value convertData(const crow::json::rvalue &data) { switch(data.t()) { case crow::json::type::Number: return bsoncxx::types::b_int32{static_cast<int32_t>(data.i())}; case crow::json::type::True: return bsoncxx::types::b_bool{true}; case crow::json::type::False: return bsoncxx::types::b_bool{false}; case crow::json::type::String: return bsoncxx::types::b_utf8{data.s()}; default: // 根据需求处理Null/Array/Object等其他类型,这里示例抛出异常 throw std::invalid_argument("Unsupported JSON type"); } }
修改后,update_builder << it->key() << convertData(it->value());可以直接正常工作。
方案二:用std::variant统一返回类型
如果不想直接依赖bsoncxx类型,可使用C++17的std::variant包装多类型,再通过std::visit适配到构建器:
#include <variant> // 定义包含所有可能类型的变体 using JsonVariant = std::variant<int, bool, std::string>; JsonVariant convertData(const crow::json::rvalue &data) { switch(data.t()) { case crow::json::type::Number: return static_cast<int>(data.i()); case crow::json::type::True: case crow::json::type::False: return data.b(); case crow::json::type::String: return data.s(); default: throw std::invalid_argument("Unsupported JSON type"); } }
在循环中处理变体:
for (auto it = reqj.begin(); it != reqj.end(); ++it) { if(it->key()=="id") continue; update_builder << "$set" << bsoncxx::builder::stream::open_document; // 用std::visit处理不同类型的变体值 std::visit([&](auto&& val) { update_builder << it->key() << val; }, convertData(it->value())); update_builder << bsoncxx::builder::stream::close_document; }
额外修正点
原期望实现中collection.insert_one(update_builder());存在错误,因为update_builder已经通过<< finalizer生成了文档实例,应改为使用已创建的update变量:
bsoncxx::stdx::optional<mongocxx::result::insert_one> result = collection.insert_one(update.view());
内容的提问来源于stack exchange,提问作者Manish Jha
相关产品推荐
相关产品推荐

