そのため、std::array と boost::array (これらはほぼ同じであり、以降、あいまいに単に「配列」と呼ぶことにします) は、配列のコンテナー オブジェクトを提供するように設計されました。配列は動的にサイズを変更しません。ただし、どちらもコンストラクターのパラメーターとしてではなく、テンプレートの引数として配列サイズを取得することによって設計されています。結果: vector により、オブジェクトの作成後に動的にサイズ変更できます。array では、コンパイル時にサイズがわかっている必要があります。
私が見る限り、オブジェクトの作成時にサイズがわかっているがコンパイル時にはわからない配列がある場合、唯一のオプションは、1) vector を使用して余分なオーバーヘッドを不必要に発生させる、2) (non-コンテナー型) ネイティブ配列 (例: int foo[42];
)、または 3) 独自の配列ラッパー クラスを最初から作成します。これは、ベクトルではなく配列を使用したいができない中間のケースであるということで正しいですか? または、配列が機能する可能性のある私ができる魔法はありますか?
理解に役立つ場合に備えて、この質問に影響を与えた理由について少し詳しく(わかりました、たくさん)以下に示します。
実行時にバイナリ データ (unsigned char[]、または配列) を繰り返し生成し、それを別のモジュール (呼び出し先など) に渡すモジュールがあります (呼び出し元など)。呼び出し先モジュールは配列を変更しません (コピーを作成し、必要に応じてそれを変更します)。そのため、呼び出し元モジュールが最初に配列を作成すると、サイズは変更されません (内容も変更されません)。ただし、2 つの問題が発生します。1) 呼び出し元は、配列が生成されるたびに同じサイズの配列を生成しない場合があります。呼び出し元は、配列を作成する実行時に配列サイズを認識しますが、コンパイル時には認識しません。2) 呼び出し元が配列を呼び出し先に渡すメソッドは、呼び出し元が渡す任意のサイズの配列を取得できる必要があります。
テンプレート関数にすることを考えました。
template<size_t N> void foo(const array<unsigned char, N>& my_array);
ただし、呼び出し先モジュールの実装からインターフェイスを分離するために、インターフェイス クラスを使用しています。したがって、関数は、テンプレート化と相互に排他的な仮想メソッドである必要があります。さらに、それが問題にならなかったとしても、上記の #1 と同じ問題が残ります。コンパイル時に配列のサイズがわからない場合、コンパイル時にテンプレート化された関数を解決することもできません。
私の実際の機能:
virtual void foo(const array<unsigned char, N>& my_array); // but what is N???
要約すると、私の唯一の本当の選択肢は、ベクトルまたはネイティブ配列を使用することです。たとえば、
virtual void foo(const vector<unsigned char> my_array); // unnecessary overhead
virtual void foo(const unsigned char[] my_array, size_t my_array_len); // yuk
または、std::array または boost::array を使用できるようにする、見落としているトリックがありますか?