定义如下:
struct nmap;
struct nmap: map<string, boost::variant<string, nmap*>>{};
下面的最后一行不起作用:
nmap my_map;
my_map["a"] = "b";
my_map["c"] = new nmap;
my_map["c"]["d"] = "e";
我需要添加什么才能使其正常工作?
最佳答案
我建议要么找一个小巧的可读助手:
#include <boost/variant.hpp>
#include <map>
using std::map;
struct nmap;
struct nmap: map<std::string, boost::variant<std::string, nmap*>>
{
typedef boost::variant<std::string, nmap*> Variant;
typedef map<std::string, Variant> base;
friend nmap& as_map(Variant& v) { return *boost::get<nmap*>(v); }
friend nmap const& as_map(Variant const& v) { return *boost::get<nmap*>(v); }
friend std::string& as_string(Variant& v) { return boost::get<std::string>(v); }
friend std::string const& as_string(Variant const& v) { return boost::get<std::string>(v); }
};
int main()
{
nmap my_map;
my_map["a"] = "b";
my_map["c"] = new nmap;
as_map(my_map["c"])["d"] = "e";
}
或者采用递归变体方式。让我素描:
递归变体树
这是 IMO 更优雅的:
#include <boost/variant.hpp>
#include <map>
using nmap = boost::make_recursive_variant<std::string, std::map<std::string, boost::recursive_variant_> >::type;
using map_t = std::map<std::string, nmap>;
#include <iostream>
static std::ostream& operator<<(std::ostream& os, nmap const& map);
int main()
{
nmap my_map = map_t
{
{ "a", "b" },
{ "c", map_t
{
{ "d", "e" },
{ "f", map_t
{
{ "most nested", "leaf node" },
{ "empty", map_t { } },
} },
} },
};
std::cout << my_map;
}
乍一看这可能看起来更复杂,但它实际上有许多重要的优点:
- 不再继承不适合继承的类
- 不再限制“根”对象/必须/是一个映射(它现在也可以是一个字符串,所以变体更一致地得到尊重)
- 不再有内存泄漏 由于变体现在实际上负责分配实际的
nmap
。在实例中,有开箱即用的完整值语义。 允许对树进行惯用访问,不需要“ifs and
butsdereferences”,例如考虑一下我们如何能够快速而肮脏地实现operator<<
:static std::ostream& operator<<(std::ostream& os, nmap const& map) { struct print : boost::static_visitor<void> { print(std::ostream& os, int indent = 0) : os(os), indent(indent) { } void operator()(map_t const& map) const { os << "{"; for(auto& item : map) { os << "\n"; do_indent(); os << " " << item.first << ": "; boost::apply_visitor(print(os, indent+4), item.second); } if (!map.empty()) { os << "\n"; do_indent(); }; os << "}"; } void operator()(std::string const& str) const { os << str; } private: std::ostream& os; void do_indent() const { for (int n = indent; n>0; --n) os << ' '; } int indent = 0; }; boost::apply_visitor(print(os), map); return os; }
输出:
# g++ -std=c++11 -Wall -pedantic -Wextra main.cpp && ./a.out
{
a: b
c: {
d: e
f: {
empty: {}
most nested: leaf node
}
}
}
关于C++:嵌套映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22274705/