嵌套变体的简明初始化语法?

时间:2012-08-19 05:28:33

标签: c++ casting initialization variant

我正在使用一个小的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 ++不会抱怨。

看起来我的选择是:

  • 找到另一种官方支持的简明初始化语法。
  • 使用复合文字并希望它们可以在其他编译器中使用。
  • 删除对C ++的支持&lt; 11并使用initializer_list。
  • 不要提供简洁的初始化语法。

对第一个选项的任何帮助都是我现在正在寻找的那种答案。

宏是另一种最后的选择,我已经写了一些可以完成这项工作,但我不想使用它们。

1 个答案:

答案 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;

他们可以轻松定义递归变体类型。