この回答は、一般的に異なるアプローチを対象としています。
任意にネストされた動的なサイズの配列をサポートするには(つまり、コンパイル時にネストされた配列の深さが制限されないように)、次のようなものを使用する必要があります。
スクリプト言語の変数のタイプは、次のいずれかである必要があります。
- 整数
- 浮く
- (...サポートしたい他のプリミティブ型...)
- これらのタイプの配列(配列を含む)
- (...サポートしたい場合は連想マップなどの他のコンテナタイプ...)
これは通常、QtのBoostVariantやQVariantなどの「バリアント」タイプを使用して行われます。バリアント型は基本的に、型のセット(つまり、それらの1つ)と、実際に含まれている型を示す型記述子の和集合です。
したがって、この「任意のタイプ」が再び配列である場合にも、任意のタイプの配列を表すことができます。したがって、ネストされた配列の動的な深さをサポートできます。
「任意の型の配列」は、実際にはこのバリアント型のベクトルである必要があることに注意してください。Boost Variantの問題は、テンプレート引数として保持できるタイプを明示的にリストする必要があることです。これにより、再帰が発生します。
boost::variant<int, float, ..., std::vector<boost::variant<..., ...> > >
^^^^^^^^^^^^^^^^^^^^^^^^
recursion
Qtには、基本的にQtでサポートされているすべてのタイプを保持できるタイプQVariantがあります。QVariantはテンプレートクラスではないため、その型にはそのような再帰は含まれていません。同等のブーストタイプがあるかどうかはわかりませんが、疑わしいです。
スクリプトの実行中に配列のサイズを変更できない場合(または、サイズを変更する必要がある場合は、新しい配列を割り当てて内容をコピーできます)、より簡単な解決策があります。配列を1次元のベクトルに格納するだけでなく、スクリプト言語の配列の次元も別のベクトルに格納します。次に、次のようなインデックスメソッドを使用できます。
class ScriptArray {
vector<int> dim;
vector<int> elements;
int getIndex(vector<int> indexList) const {
int multiplicator = 1;
int index = 0;
for (int i = 0; i < dim.size(); ++i) {
index = multiplicator * indexList[i];
multiplicator *= dim[i];
}
return index;
}
};
これは基本的に次の考え方の一般化です。1次元配列(10000要素)として表現する2次元配列(100 x 100要素)について考えてみます。元の配列()の任意のインデックスについて、x, y
これを内部配列()の1次元インデックスにマップできますx + 100 * y
。3次元配列の場合、これには別の乗算(x + 100 * y + 100*100 * z
)などが含まれます。
このソリューションと配列のサイズ変更の問題は、次元のサイズが変更されたときに要素が配列内で「移動」することです(特別な場合:この次元は「最も外側の」次元であるため、最後の次元)。したがって、サイズ変更時に配列が無効になるという事実に耐えることができるか、新しいサイズで新しい配列の内容をコピーするか、スペースを慎重に挿入/配列内のいくつかの要素を削除する複雑なサイズ変更メソッドを実装します。正しい場所。