C ++アレイクラステンプレートが必要です。これは固定サイズ、スタックベースで、デフォルトのコンストラクターを必要としません

StackOverflow https://stackoverflow.com/questions/3873625

質問

そのため、Boost :: Arrayを検討していましたが、定義されたデフォルトのコンストラクターが必要です。この配列をデータで埋める最良の方法は、Push_back(const t&)メソッドを使用することです。サイズ(コンパイル時に既知)よりも多くの場合、ビルド構成に応じてアサートまたは例外が発生します。これにより、常に意味のあるデータが含まれます。この概念の効率的でポータブルで信頼できる実装を知っている人はいますか?

役に立ちましたか?

解決

まあ、私は誰かが今答えをもたらしただろうと思っていただろうが、そうではないようだ。

あなたが望んでいるのは、私が夢見てきたものです: boost::optional_array<T,N>.

2つのバリエーションがあります。

  • 最初:に似ています boost::array< boost::optional<T>, N >, 、それは各要素が設定されている場合とそうでない場合があります。
  • 2番目:aに似ています std::vector<T> (どういうわけか)、それはすべて開始要素が設定されており、すべての次の要素は設定されていません。

以前の質問 /コメントを考えると、2番目の質問が欲しいようですが、両方が非常に似ているので、それは実際には問題ではありません。

template <typename T, size_t N>
class stack_vector
{
public:
  bool empty() const { return mSize == 0; }
  size_t size() const { return mSize; }
  size_t capacity() const { return N; }
  size_t max_size() const { return N; }

  T& operator[](size_t i) { return *(this->pfront() + i); }
  /// ...

private:
  T* pfront() const { return reinterpret_cast<T*>(&mStorage); }

  std::aligned_storage< N * sizeof(T), alignof(T) > mStorage;
  size_t mSize; // indicate how many elements are set, from the beginning
};

これらの非常に特別な作戦に焦点を当てましょう。

template <typename T, size_t N>
void push_back(T const& t)
{
  new (this->pfront() + mSize) T(t); // in place construction
  ++mSize;
}

template <typename T, size_t N>
void clear()
{
  for (size_t i = 0; i != mSize; ++i)
  {
    (this->pfront() + i)->~T();
  }
  mSize = 0;
}

ご存知のように、主な困難はそれを覚えておくことです。

  • まだそこに要素が構築されていない場合は、割り当ての代わりに配置new +コピー構造が必要です。
  • 「時代遅れ」になる要素(つまり、最後の要素の後になります)は適切に廃棄する必要があります(つまり、それらの破壊者が呼び出されます)。

従来のSTLコンテナには、実装が難しい場合がある多くの操作があります。 aで vector, 、要素シャッフル(ため insert また erase)おそらく最も恐ろしい例です。

また、C ++ 0xおよびInitializer-Listsの場合にも注意してください vector 得る emplace_back 所定の位置に要素を直接構築し、したがって、 CopyConstructible 要件は、あなたのケースに依存する素晴らしい恩恵かもしれません。

他のヒント

boost::array<T, 12> ta; と違いはありません T[12] ta;;初期イザーリストを使用しない場合、要素はデフォルトの構築されます。

一般的な回避策はそうでしょう boost::array<T*, 12> ta; または多分 boost::array<unique_ptr<T>, 12> ta;.

価値で保存する唯一の方法は、コピーすることです。

struct A {
    A(int i):_i(i){ cout << "A(int)" << endl; }
    A(const A& a){ cout << "A(const A&)" << endl; }
    ~A(){ cout << "~A()" << endl; }

    int _i;
};

int main(){
    boost::array<A, 2> ta = {{1, 2}};
}

これは出力です:

A(int)
A(const A&)
A(int)
A(const A&)
~A()
~A()
~A()
~A()

http://codepad.org/vjgeqwk5

ブースト::バリアントをboost :: arrayに保存することができますか?最初のパラメーターをintか何かにします。

すなわち

boost::array<boost::variant<int, foo>, 6> bar;

さて、あなたはバリアントに対処する必要がありますが、それはスタックが割り当てられています...

C ++ 0xでは、あなたは得た std::array<type, size> (おそらくBoost :: Arrayと同じ)。使用して配列データを初期化できます fill() また std::fill_n():

std::array<int, 30> array;
array.fill(0);
boost::array<int, 30> barray;
std::fill_n(barray.begin(), 30, 0);

定義でデフォルトのInitializedを取得したい場合は、コピーターを使用できます。

static std::array<int, 30> const nullarray = {0, 0, 0, ..., 0}; // nullarray.fill(0);
// (...)
std::array<int, 30> array{nullarray};

なぜスタックに住む必要があるのですか?作成したという経験的証拠はありますか reserveing a vector 遅すぎる(aを使用してください vector 明らかな答えのようです)?

たとえそうであっても、スペースが予約されているベクトルのプールを作成できます。 swap 事前に割り当てられたベクトルの1つは、ローカルコピーになります。あなたが地元のものを終わらせたら、それをもう一度交換します( splice のためのトリック lists)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top