固定長のシーケンスの標準コンテナはありますか?その長さは実行時に決定されます。できれば、各シーケンス要素のコンストラクターに引数を渡し、その引数を使用してconstメンバー(または参照)を初期化したいと思います。また、O(1)の特定のインデックスでシーケンス要素を取得したいと思います。私のすべての要件を同時に満たすことはできないように思えます。
- 長さが固定されていることは知っ
std::array
ていますが、その長さはコンパイル時に知る必要があります。 std::vector
は動的なサイズであり、を使用してコンストラクター引数を渡すことができますemplace
。reserve
実際の再割り当てを回避するためにメモリを使用することはできますが、そのような再割り当てを理論的に許可するには、タイプを移動可能にする必要があります。これにより、たとえばconstメンバーが防止されます。- 次に、とが
std::list
ありstd::forward_list
ます。これは、移動可能なタイプを必要としませんが、サイズ変更可能であり、ランダムアクセスパターンではパフォーマンスがかなり低下します。また、各リストノードは個別に割り当てられる可能性があるため、このようなリストにはかなりのオーバーヘッドが伴う可能性があると感じています。 - 不思議なことに、
std::valarray
これまでのところ、長さが固定されており、自動的にサイズ変更されないため、これが最善の策です。メソッドはありresize
ますが、実際にそのメソッドを呼び出さない限り、タイプは移動可能である必要はありません。ここでの主な欠点は、カスタムコンストラクター引数がないことです。そのため、このアプローチではconstメンバーを初期化することはできません。
私が逃したいくつかの選択肢はありますか?すべての要件を満たすように標準コンテナーの1つを調整する方法はありますか?
編集:私がやろうとしていることのより正確なアイデアをあなたに与えるために、この例を見てください:
class A {
void foo(unsigned n);
};
class B {
private:
A* const a;
const unsigned i;
public:
B(A* aa) : a(aa), i(0) { }
B(A* aa, unsigned ii) : a(aa), i(ii) { }
B(const std::pair<A*, unsigned>& args) : B(args.first, args.second) { }
B(const B&) = delete;
B(B&&) = delete;
B& operator=(const B&) = delete;
B& operator=(B&&) = delete;
};
void A::foo(unsigned n) {
// Solution using forward_list should be guaranteed to work
std::forward_list<B> bs_list;
for (unsigned i = n; i != 0; --i)
bs_list.emplace_front(std::make_pair(this, i - 1));
// Solution by Arne Mertz with single ctor argumen
const std::vector<A*> ctor_args1(n, this);
const std::vector<B> bs_vector(ctor_args1.begin(), ctor_args1.end());
// Solution by Arne Mertz using intermediate creator objects
std::vector<std::pair<A*, unsigned>> ctor_args2;
ctor_args2.reserve(n);
for (unsigned i = 0; i != n; ++i)
ctor_args2.push_back(std::make_pair(this, i));
const std::vector<B> bs_vector2(ctor_args2.begin(), ctor_args2.end());
}