3

重複の可能性:
std::tupleをstd::array C++11に変換します

あなたが持っているとしましょう:

template<class T,int N>
struct A {
  A(const B& b): /* what comes here */ {}

  std::array<T,N> F;
};

F[]上記の場合、コンストラクターの引数を使用しての各要素を構築する必要がありますbint引数は、などのようにコンパイル時定数になり得るタイプではない可能性があるため、これは注意が必要です。

これはとは異なります。積分テンプレートパラメータに応じてメンバー配列の要素を作成することは可能ですか?ここではユーザー定義の構造体が使用されているため、実行時のコピーが必要です。

4

2 に答える 2

8

インデックストリックはここでも適用できます。少し変換する必要があります。

template <std::size_t... Is>
struct indices {};

template <std::size_t N, std::size_t... Is>
struct build_indices
  : build_indices<N-1, N-1, Is...> {};

template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};

template<class T,int N>
struct A {
  template<std::size_t... Is>
  A(const B& b, indices<Is...>) : F{{(void(Is),b)...}} {}
  A(const B& b) : A(b, build_indices<N>{}) {}

  std::array<T,N> F;
};

実例。

基本的にインデックスの値を無視し、パック自体を使用して拡張を実行します。つまり、パックのサイズのみが対象になります。実際の値には興味がないので、このためにインデックスを再利用することは悪用のように思えるかもしれませんが、ここで機械を再利用することは問題ないと思います。-elementパックを作成する他の構成はN、パックにゼロが含まれている可能性が高いことを除いて、同じように見えます。

于 2012-10-11T18:32:43.967 に答える
0

Xeoによって示されるbuild_indiciesトリックは賢く、コンパイラがそれをサポートしている場合はおそらく最良のオプションです。

別のオプションは、要素をデフォルトで構築できるようにしてから、それらを破棄し、placment new/uninitialized_fillを使用して再構築することです。

template<class T,int N>
struct A {
  A(const B& b) {
      for (size_t i=0;i<N;++i) {
          F[i].~T();
          new (&F[i]) T(b);
      }
  }

  std::array<T,N> F;
};

デフォルトの構造を回避するために、通常は初期化されないストレージを使用することもできます。

template<class T,int N>
struct A {    
  typedef std::array<T,N> array_type;
  std::aligned_storage<sizeof(array_type),alignof(array_type)>::type storage;

  array_type &F() {
    return reinterpret_cast<array_type&>(storage);
  }

  A(const B& b) {
    // placement new/uninitialized_fill
  }
};
于 2012-10-11T19:52:07.577 に答える