私はさびた C++ のスキルを磨くために小さな C++ JSON ライブラリに取り組んでいますが、初期化リストの動作を理解するのに苦労しています。
ライブラリのコアは、さまざまな JSON データ型 (null、ブール値、数値、文字列、オブジェクト、配列) のいずれかを格納するバリアント クラス ("var" という名前) です。
目標は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 foo = (array){ 1, "b", (var)(array){ 3.1, 3.2 } };
内部リストを配列にキャストした後、内部リストを var に明示的にキャストする必要があるのはなぜですか? また、この余分なキャストを回避するにはどうすればよいですか? 私が知る限り、varsの配列にコンストラクターを使用しているため、配列をvarクラスに暗黙的に変換する必要があります。
template <size_t length>
var(const var(&start)[length]) {
// internal stuff
init();
setFromArray(vector<var>(start, start + length));
}
var への明示的なキャストがなければ、初期化リストは、配列から var へのキャストから途中で何らかの形で別のものにキャストされるようです。なぜこれが起こるのか、そしてそれを回避する方法を理解しようとしています。
ここに完全なソースの要点があります。質問に関連するものを追加する必要があるかどうか教えてください。
アップデート
明らか(foo){1, "two"}
に、実際には初期化リストをキャストしません。これは複合リテラルと呼ばれる完全な式です。あなたがそれを与えない限りg ++は文句を言いませんが、それはCでのみ利用可能のようです-pedantic
.
私のオプションは次のようです:
- 公式にサポートされている別の簡潔な初期化構文を見つけてください。
- 複合リテラルを使用し、他のコンパイラで機能することを願っています。
- C++ < 11 のサポートを中止し、initializer_list を使用します。
- 簡潔な初期化構文を提供しないでください。
最初のオプションに関するヘルプは、この時点で私が探している答えのようなものです。
マクロは、もう 1 つの最後のオプションです。私は、その仕事をするものをいくつか書きましたが、それらを使用する必要はありません。