如何用 std::variant 打印地图 key/value?
How can I print map key/value with 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;
有人可以帮我解决这个错误吗?
std::variant
没有operator<<
,不能直接打印出来。您需要从变体中读取值(按索引或类型),例如
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 一起使用,将任何类型打印到 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';
}
这是可行的,因为所有 float
、int
、bool
和 std::string
都对输出流运算符 <<
进行了重载。对于其他类型,或者要覆盖此行为,您可以使用自定义仿函数 class 而不是 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";
实际上并不是 select 变体类型的 std::string
构造函数,因为字符串文字优先转换为 bool
而不是 std::string
(further reading)。您可以通过使用 std::string{"probe"}
或标准的 std::string
用户定义文字显式创建 std::string
来避免这种情况,如 "probe"s
.
我正在尝试打印字典中某个值的键。我这样定义我的地图:
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;
有人可以帮我解决这个错误吗?
std::variant
没有operator<<
,不能直接打印出来。您需要从变体中读取值(按索引或类型),例如
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 一起使用,将任何类型打印到 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';
}
这是可行的,因为所有 float
、int
、bool
和 std::string
都对输出流运算符 <<
进行了重载。对于其他类型,或者要覆盖此行为,您可以使用自定义仿函数 class 而不是 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";
实际上并不是 select 变体类型的 std::string
构造函数,因为字符串文字优先转换为 bool
而不是 std::string
(further reading)。您可以通过使用 std::string{"probe"}
或标准的 std::string
用户定义文字显式创建 std::string
来避免这种情况,如 "probe"s
.