gpt4 book ai didi

c++ - 带有 boost::any 的 cout 映射

转载 作者:搜寻专家 更新时间:2023-10-31 01:37:07 24 4
gpt4 key购买 nike

我有一本“字典”std::map<std::string, boost::any> (或 std::any ,如果你愿意)可以嵌套。现在,我想显示 map 。自 boost::any显然不能很好地与 << 一起玩,事情变得有点讨厌了。到目前为止,我正在检查类型,转换它,并将转换通过管道传输到 cout :

for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";

例如打印

{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}

不幸的是,这很难扩展。我必须添加另一个 else if每种类型的子句(例如,floatsize_t、...),这就是我对解决方案不是特别满意的原因。

有没有办法将以上泛化到更多类型?

最佳答案

您可以做的一件事是减轻(但不是消除)痛苦,将类型确定逻辑分解为一个支持函数,同时使用静态多态性(特别是模板)将操作应用于值...

#include <iostream>
#include <boost/any.hpp>
#include <string>

struct Printer
{
std::ostream& os_;

template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};

template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}

int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}

(只需稍加努力,您就可以在可变参数模板参数包中为每种类型完成特定于类型的测试和分派(dispatch),从而简化该代码并减少维护列表的麻烦。或者,您可以只使用一个用于生成 if-cast/dispatch 语句的预处理器宏....)

仍然 - 如果您知道类型集,boost::variant 更合适并且已经支持类似的操作(参见 here)。

另一种选择是在创建类型时“记住”如何执行特定操作(例如打印):

#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>

struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }

std::function<void(std::ostream&, const boost::any&)> printer_;
};

int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}

如果你有很多操作并且想减少内存使用,你可以让模板构造函数创建并存储一个(抽象基类)指针,指向一个静态类型特定的类,该类派生自一个抽象接口(interface),带有你的操作想要支持:这样你只需为每个 Super_Any 对象添加一个指针。

关于c++ - 带有 boost::any 的 cout 映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34673807/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com