如何使用 std::variant 打印地图键/值?



我正在尝试打印字典中某个值的键。我这样定义我的地图:

std::map<std::string, std::variant<float,int,bool,std::string>> kwargs; 
kwargs["interface"] = "probe"; 
kwargs["flag"] = true; 
kwargs["Height"] = 5; 
kwargs["length"] = 6; 

我尝试正常打印该值,但发生(没有运算符"<<"与这些操作数匹配(错误。

std::cout << kwargs["flag"] << std::endl; 

有人可以帮助我解决此错误吗?

没有operator<<std::variant,不能直接打印出来。您需要从变体中读取值(按索引或类型(,例如

std::cout << std::get<bool>(kwargs["flag"]) << std::endl; 

std::cout << std::get<2>(kwargs["flag"]) << std::endl; 

您可以为类型定义operator<<

std::ostream& operator<<(std::ostream& os, std::variant<float,int,bool,std::string> const& v) {
std::visit([&os](auto const& x) { os << x; }, v);
return os;
}

您可以概括解决方案以使用任何variant专用化:

template <class Var, class = std::variant_alternative_t<0, Var>>
std::ostream& operator<<(std::ostream& os, Var const& v) {
std::visit([&os](auto const& x) { os << x; }, v);
return os;
}

请注意,如果Var不是std::variant专用化,则存在第二个模板参数来禁用定义。

我会将std::visit与通用 lambda 一起使用,该 lambda 打印任何类型的std::cout,如下所示:

std::map<std::string, std::variant<float,int,bool,std::string>> kwargs; 
kwargs["interface"] = "probe"s;
kwargs["flag"] = true; 
kwargs["Height"] = 5; 
kwargs["length"] = 6; 
for (const auto& [k, v] : kwargs){
std::cout << k << " : ";
std::visit([](const auto& x){ std::cout << x; }, v);
std::cout << 'n';
}

这是有效的,因为所有floatintboolstd::string都有输出流运算符<<的重载。对于其他类型,或者要覆盖此行为,您可以使用自定义函子类而不是 lambda:

struct PrintVisitor {
template<typename T>
void operator()(const T& t) const {
std::cout << t;
}
// prints std::string in quotes
void operator(const std::string& s) const {
std::cout << '"' << s << '"';
}
};
[...]
std::visit(PrintVisitor{}, kwargs);

注意:不幸的是,行kwargs["interface"] = "probe";实际上并没有为变量类型选择std::string构造函数,因为字符串文本优先转换为bool而不是std::string(进一步阅读(。例如,您可以通过使用std::string{"probe"}或标准std::string用户定义的文本显式进行std::string来避免这种情况,如"probe"s中所示。

现场演示

相关内容

  • 没有找到相关文章

最新更新