C ++:嵌套映射 [英] C++: Nested map

查看:220
本文介绍了C ++:嵌套映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是定义:

struct nmap;
struct nmap:map< string,boost :: variant< string,nmap *>> {};

下面的最后一行不起作用:

The last line below doesn't work:

nmap my_map;
my_map [a] =b;
my_map [c] = new nmap;
my_map [c] [d] =e;

推荐答案

我建议你去一个小小的可读助手:

I'd suggest either going for a tiny little readable helper:

#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";
}

或者以递归变量的方式。让我草草:

Or go the recursive variant way. Let me sketch:

这是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;
}

乍一看,这可能看起来更复杂, >它实际上有很多重要的优点:

At first glance this may look more complicated, but it actually has a number of important advantages:


  • 不再继承继承的类

  • 没有更多的限制,'root'对象/必须是一个映射(它现在可以是一个字符串,所以变体更加一致)

  • >不再有内存泄漏 由于变体现在实际上负责分配实际的 nmap 实例,因此有完整的值语义出

  • 允许对树进行惯用的访问,不需要'ifs和 buts 解引用考虑我们如何能够快速,脏的执行运算符<

  • no more inheriting from classes not intended for inheritance
  • no more limitation that the 'root' object /must/ be a map (it can be a string too now, so the variant is more consistently honoured)
  • no more memory leaks Due to the fact that the variant now actually takes care of allocating the actual nmap instances, there's full value-semantics out of the box.
  • allows for idiomatic visiting of the tree, no need for 'ifs and buts dereferences', e.g. consider how we could do a quick & dirty implementation of that 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;
}


查看 Live on coliru

See it Live On coliru

输出:

# g++ -std=c++11 -Wall -pedantic -Wextra main.cpp  && ./a.out

{
    a: b
    c: {
        d: e
        f: {
            empty: {}
            most nested: leaf node
        }
    }
}

这篇关于C ++:嵌套映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆