2017-03-19 16 views
2

再帰的に使用できるアルゴリズムを再帰的に使用しましたが、再帰的な方法で動作しますが、テンプレートからn-1次元変数を作成できないため、 。ヘルプについて
私は変数名とその意味書き留め:それはint x[3][6][4]のように見えるの配列だった場合、その後、:すべてのディメンション(例でnは長いベクトル:n次元ベクトルをフラット化

  • v:n次元ベクトル
  • dimsを{3,6、4})
  • p:フラットベクター(例えば、サイズを取得するために使用される大きさの生成物:3 * 6 * 4)
  • retdimsは、のように見える返さフラットベクトル
  • sub_dims:最初の寸法せずdims execpt同じ(例:{6,4})
  • sub_p:第一の要因無し以外は同じようp(例:6 * 4)
  • sub_ret:用返さフラットベクトルN-1次元ベクトル

コード:このコードプロジェクトのビルドで

template <typename T> 
vector<int> dim_flat(vector<T> v, vector<int> dims) 
{ 
    // creating variables and vectors 
    int n = dims.size(); 
    int p = dims[0]; 
    for (int i = 1; i < n; i++) 
    { 
     p *= dims[i]; 
    } 
    int sub_p = p/dims[0]; 
    vector<int> sub_dims; 
    sub_dims.assign(dims.begin() + 1, dims.end()); 
    vector<int> ret(p); 

    // algorithm 
    if (n > 1) 
    { 
     for (int i = 0; i < dims[0]; i++) 
     { 
      vector<int> sub_ret = dim_flat(v[i], sub_dims); 

      for (int j = 0; j < sub_p; j++) 
      { 
       ret[i * sub_p + j] = sub_ret[j]; 
      } 
     } 
    } 
    else 
    { 
     // case for the input is 1D 
     // not yet written 
    } 

    return ret; 
} 

、しかし私がメインでそれを呼び出す場合:

vは、例えば、 4Dベクトルとdimsベクター含有ある{3、3、3、3}構築しようとすると、私は、次を得る:ライン

vector<int> sub_ret = dim_flat(v[i], sub_dims); 

ため

error C2784: 'std::vector<_Ty> dim_flat(std::vector<T>,std::vector<_Ty>)' : could not deduce template argument for 'std::vector<T>' from 'int' 

をIはちょっと(しかし本当に)それは、このためにやっている、このエラーの意味を理解し、私は同じことが起こらないと予想さ:

T x = v[i]; 
vector<int> sub_ret = dim_flat(x, sub_dims); 

これは私がと思ったので、私は本当に、もうエラーを理解していない部分でありますウィ引数はvector<T> vです。 4Dベクトルは、Tのベクトルとして理解され、ここで、Tは、そのvector<T>からインデックス付けすることができる3Dベクトルである。したがって、この論理に従えば、再帰に最初のTが3Dベクトルであるとすれば、この3Dベクトルより深いステップは、T'のベクトルとして理解されることになり、T'は2Dベクトルとなります。

明らかに私のロジックに欠陥があるか、間違った方法(または両方)を使用していたので、質問はどうすれば解決できますか?

EDIT:
解決策はMax66になります。
コードはおそらくより最適化できますが、少なくとも今は動作しています。
コード:

//// for integer only 
// case input is 0-dimensional (simply a variable) 
template <typename T> 
vector<int> dim_flat (const T &v, const vector<int> &dims) 
{ 
    return vector<int>(1, v); 
} 

// case input is n-dimensional 
template <typename T> 
vector<int> dim_flat(const vector<T> &v, const vector<int> &dims) 
{ 
    // creating variables and vectors 
    int n = dims.size(); 
    int p = dims[0]; 
    for (int i = 1; i < n; i++) 
    { 
     p *= dims[i]; 
    } 
    int sub_p = p/dims[0]; 
    vector<int> sub_dims; 
    sub_dims.assign(dims.begin() + 1, dims.end()); 
    vector<int> ret(p); 

    // algorithm 
    if (n > 1) // case n-dimensional 
    { 
     for (int i = 0; i < dims[0]; i++) 
     { 
      vector<int> sub_ret = dim_flat(v[i], sub_dims); 
      for (int j = 0; j < sub_p; j++) 
      { 
       ret[i * sub_p + j] = sub_ret[j]; 
      } 
     } 
    } 
    else // case 1-dimensional 
    { 
     for (int i = 0; i < p; i++) 
     { 
      vector<int> sub_ret = dim_flat(v[i], sub_dims); 
      ret[i] = sub_ret[0]; 
     } 
    } 
    return ret; 
} 

答えて

0

短い答え:あなたはC +を使用する必要があれば、あなたがC++ 11以降、または

std::vector<int> dim_flat (int v, std::vector<int> const &) 
{ return std::vector<int>(1, v); } 

を使用できるかどうかの機能に

std::vector<int> dim_flat (int v, std::vector<int> const &) 
{ return {v}; } 

を追加98

長い答え:私は間違っていないよ場合、問題はあなたがを呼び出すときに、ということですstd::vector<int>Tintあるとき)、あなたはとてもdim_flat()しかしコンパイラは必要がないことを理解することはとてもスマートではありません(「入力1D用ケース」を実行している)と呼ばれていない、n == 1を持っていますdim_flat()int(代わりにstd::vector<T>)と呼ぶため、dim_flat(int, std::vector<int>)を探してもそれを見つけられません。

ので、コンパイラを幸せにするために、あなたはdim_flat(int, std::vector<int>)を実装する必要があります。

は(空のベクターを返す)ダミー関数を指定できますが、私はあなたがそれを正しく実装することをお勧めします。

話題の少し:、ベクトルのunusefullコピーを避けてください。 dim_flat()vdimsは読み取り専用で、変更されていません。

template <typename T> 
std::vector<int> dim_flat(std::vector<T> const & v, 
          std::vector<int> const & dims) 

P .:次のように単純に書くのはなぜですか?

std::vector<int> dim_flat (std::vector<int> const & v) 
{ return v; } 

template <typename T> 
std::vector<int> dim_flat(std::vector<std::vector<T>> const & v) 
{ 
    std::vector<int> ret; 

    for (auto const & e : v) 
    { 
     auto s = dim_flat(e); 

     ret.reserve(ret.size() + s.size()); 
     ret.insert(ret.end(), s.cbegin(), s.cend()); 
    } 

    return ret; 
} 
+0

ありがとうございました!最小限の調整で( 'int v'の代わりに' T v'を使用しなければならなかった)、それは動作します。何らかの理由で、返すためのC++ 11形式が動作せず、 'syntax error'が出ましたが、C++ 98形式が動作します。また、constリファレンスの提案もありがとうございます。私はそれについて知っていて、実際にそれを使いたいと思っていましたが、私はまだ何とかそこに置くことを忘れていました。 – Rettenet