我正在使用一个小型 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 类,因为它使用的是 var 数组的构造函数:
template <size_t length>
var(const var(&start)[length]) {
// internal stuff
init();
setFromArray(vector<var>(start, start + length));
}
似乎如果没有显式转换为 var,初始化列表在从数组转换为 var 的过程中会以某种方式转换为其他东西。我试图了解为什么会发生这种情况,以及如何避免它。
这是完整来源的要点。让我知道是否应该添加与该问题相关的任何内容。
更新
显然(foo){1, "two"}
并没有实际投射初始化列表;它是一个完整的表达式,称为复合文字。似乎它只在 C 中可用,尽管 g++ 不会抱怨,除非你给它-pedantic
。
看起来我的选择是:
- 找到另一种官方支持的简洁初始化语法。
- 使用复合文字并希望它们在其他编译器中工作。
- 放弃对 C++ < 11 的支持并使用 initializer_list。
- 不要提供简洁的初始化语法。
第一个选项的任何帮助都是我目前正在寻找的答案。
宏是另一种最后的选择,我已经写了一些可以完成这项工作,但我不想使用它们。