2017-08-26 51 views
1

我想定义一个地图,它将一个字符串作为关键字,但该值将是一个以字符串作为关键字的地图,但该值将会是一个地图类似的性质......,最终链中的最后一张地图将是从字符串到字符串的映射。C++:定义具有递归属性值的地图

我想实现标记的JSON数据结构的值。

为了说明,这里是我能想出的代码段:

typedef map<string, string> str2str; 
typedef map<string, str2str> str2str2str; 
... 
typedef map<string, str2map_or_str> str2map_or_str; 

是什么在C++中惯用的方法呢?

+0

看看https://stackoverflow.com/questions/23601686/shorthand-syntax-for-c-map-in-map。也许这就是你要找的。 –

+0

谢谢,但该解决方案似乎假定地图的已知水平。我不知道,它需要多少级别。 –

回答

1

一个简单的方法是使用structstring和递归map

struct ParseData; 
using MapValue = std::map<std::string, ParseData>; 

struct ParseData 
{ 
    std::string string_value; 
    MapValue map_value; 
}; 

然后,您可以使用一个ParseData对象或MapValue对象捕捉分析数据。

+0

是否需要完成“std :: map”的值类型? boost通过许多循环来完成递归定义。否则,这将是明显的做法。 – StoryTeller

+0

@StoryTeller,我不确定。似乎在https://ideone.com/gmTBWB上工作。 –

+0

@StoryTeller,推动推动,可以使用'ParseData'中的'MapValue *'作为'map_value'。 –

3

更习惯的解决方案IMO是使用允许递归类型定义的库。你基本上需要一棵树,每个叶子只是一个字符串。值得庆幸的是,boost::variant允许您定义递归变种:

using map_data = boost::make_recursive_variant< 
        std::string, 
        std::map< 
        std::string, 
        boost::recursive_variant_ 
        > 
       >::type; 

这是一个实用的功能元定义了新的变量类型。它将是一个简单的std::stringstd::mapstd::stringmap_data(标有特殊标记boost::recursive_variant_)。就是这样。没有深度限制。

那么你json_data类型只是以下别名:

using json_data = std::map<std::string, map_data>; 

你可以看到它在直播here。唯一需要注意的是,您需要重写代码才能使用boost::variant访问者模式。但这不是一件很难的练习。我敢说,定义的递归性使得逻辑几乎可以自行编写。