我正在使用一个小的C ++ JSON库来帮助提高我生锈的C ++技能,而且我无法理解初始化列表中的某些行为。
库的核心是一个变体类(名为“var”),它存储任何各种JSON数据类型(null,boolean,number,string,object,array)。
目标是让var
尽可能接近JavaScript变量,因此会有很多运算符重载。原始数据类型很容易处理......
var fee = "something";
var fie = 123.45;
var foe = false;
问题在于对象(地图)和数组(向量)。
为了获得接近JavaScript对象和数组文字语法的东西,我正在使用初始化列表。它看起来像这样:
// in my headers
typedef var object[][2];
typedef var array[];
// in user code
var foo = (array){ 1, "b", true };
var bar = (object){ { "name", "Bob" }, { "age", 42 } };
这很好用。问题出在嵌套列表中。
var foo = (array){ 1, "b", (array){ 3.1, 3.2 } };
由于某种原因,我的变体类将嵌套的“数组”解释为布尔值,给出:
[1, "b", true]
而不是:
[1, "b", [3.1, 3.2]]
如果我明确地将内部列表强制转换为var,它可以工作:
var foo = (array){ 1, "b", (var)(array){ 3.1, 3.2 } };
为什么在将内部列表强制转换为数组后,必须将内部列表显式地转换为var,以及如何绕过这个额外的转换?据我所知,它应该隐式地将数组转换为我的var类,因为它正在使用构造函数来获取变量数组:
template <size_t length>
var(const var(&start)[length]) {
// internal stuff
init();
setFromArray(vector<var>(start, start + length));
}
似乎没有显式强制转换为var,初始化列表会以某种方式被转换为从数组转换为var的方式。我试图理解为什么会发生这种情况,以及如何避免它。
这是a gist的完整来源。如果我应该添加与该问题相关的任何内容,请告诉我。
更新
显然(foo){1, "two"}
实际上没有投出初始化列表;它是一个名为compound literal的完整表达式。它似乎只在C中可用,虽然除非你给它-pedantic
,否则g ++不会抱怨。
看起来我的选择是:
对第一个选项的任何帮助都是我现在正在寻找的那种答案。
宏是另一种最后的选择,我已经写了一些可以完成这项工作,但我不想使用它们。
答案 0 :(得分:1)
您需要使用Boost为您提供的设施。
typedef boost::optional<boost::make_recursive_variant<
float, int, bool, //.. etc
std::unordered_map<std::string, boost::optional<boost::recursive_variant_>>,
std::vector<boost::recursive_variant_>
> JSONType;
他们可以轻松定义递归变体类型。