1

可変数の値を使用する初期化関数のファミリーが必要です。私はそれらを使用して、Eigenライブラリで収集操作を実装しています。これが、ベクトルの長さごとに1つのテンプレートを使用して現在行っている方法です。

template<typename T1, typename T2>
inline void gather (Array<T1,4,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,4,1> &index) 
{
    to << from[index[0]], from[index[1]], from[index[2]], from[index[3]];
}

template<typename T1, typename T2>
inline void gather (Array<T1,6,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,6,1> &index) 
{
    to << from[index[0]], from[index[1]], from[index[2]], from[index[3]], from[index[4]], from[index[5]];
}

上記のようなテンプレートの長いリストを、長さパラメーター(上記のスニペットの4と6)でパラメーター化された単一のテンプレートに置き換える方法はありますか?もしそうなら、それは以前のC ++ 11言語仕様で行うことができますか(私はVisual Studio 2010を使用しています)?

from場合によってはコンパイル時の初期化(constおよび)が生成される可能性があるため、コンマ区切りの値の構文を保持したいと思いますindex。しかし、私はこの仮定が間違っているかもしれません。イニシャライザリストには1〜16個の値を指定できます。空のリストについて心配する必要はありません。

4

2 に答える 2

2

演算子のオーバーロードに基づいてこの構文を一般化するのは非常に難しいのでoperator,、結果はせいぜい厄介に見えます(機能する場合)。私は他のオプションを試すことをお勧めします(例えば、MatrixBase::operator<<(DenseBase&)オペレーターのために行きます)。

それでも必要な場合は、スカラーを1つずつ解凍する必要があります。

template<typename T1, typename T2, class CI, int Current, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Current>*)
{
  gather(to, from, index, (ci,from[index[Current]]), (std::integral_constant<int, Current+1>*)0);
}

template<typename T1, typename T2, class CI, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Height>*) {}

template<typename T1, typename T2, int Height>
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index) {
  gather(to, from, index, (to << index[from[0]]), (std::integral_constant<int, 1>*)0);
}

醜い、そして問題があるかもしれません(あなたは値を処理する必要があります、それが可能であればゼロの高さ、再帰にDynamic渡る問題があるかもしれませんなど)CommaInitializers

さらに、線形のテンプレートインスタンス化の深さ(およびこの場合は避けられないIMHO)があります。

于 2012-11-14T12:11:19.320 に答える
2

この設定ではコンマ初期化構文を使用しないでください。面倒になります。この構文は、リテラルを使用するときに読みやすくするために使用されますが、これはあなたの場合ではありません。

代わりに、次のようなものをお勧めします。

template<typename T1, typename T2, unsigned int SIZE, unsigned int INDEX>
struct gather {
   gather(Array<T1,SIZE,1> &to, 
          const Array<T2,Dynamic,1> &from, 
          const Array<int,SIZE,1> &index) 
   {
      to.col(INDEX) = from[index[INDEX]];
      gather<T1,T2,SIZE,INDEX+1>(to,from, index);
   }
};

template<typename T1, typename T2, unsigned int SIZE>
struct gather<T1,T2,SIZE,SIZE>{
    gather(Array<T1,SIZE,1> &to, 
           const Array<T2,Dynamic,1> &from, 
           const Array<int,SIZE,1> &index)
    {
    }
};

これはうまく同じ効果を生み出しますが、静的です(ループなし)。

関数に対するテンプレートの特殊化の部分的な制限のため、ここでは構造体を使用していますが、インライン化のため、同じようになります。

于 2012-11-14T13:56:20.677 に答える