1

これが私の問題です。n次元のデータを扱っています。簡単のために n=2 としましょう。また、1D データのアルゴリズムもあります。このアルゴリズムを 2D 問題用に拡張するには、次のようにします。

for each row
    apply algorithm

ただし、このアルゴリズムを各列に適用する場合は、新しい関数を作成する必要があります

for each column
    apply algorithm

たとえば、関数があるとします。

void func(vector<T> &vec);

次に、この関数をベクトルに適用するには、この関数を呼び出すだけです。

vector<T> vec;
func(vec);

3D データの場合:

T multiArray[l][m][n];

私の知る限り、最初の次元のすべてのベクトルに上記の関数を適用したい場合は、次のようにします。

for(int j=0;j<m;j++){
    for(int k=0;k<n;k++){
        vector<T> singleArray;
        for(int i=0;i<l;i++){
            singleArray.push_back(multiArray[i][j][k]);
        }
        func(singleArray);
    }
}

ただし、同じデータに対して、上記の関数を 3 次元のすべてのベクトルに適用する場合は、次のように書き直す必要があります。

for(int i=0;i<l;i++){
    for(int j=0;j<m;j++){
        vector<T> singleArray;
        for(int k=0;k<n;k++){
            singleArray.push_back(multiArray[i][j][k]);
        }
        func(singleArray);
    }
}

基本的に、各 for ループの反復子を除いて、すべて同じです。この 2 つの計算を 1 つの関数で実現できる方法がいくつかあることを願っています。

どうも

4

1 に答える 1

0

一般的な解決策はわかりませんが、参照を使用して特定の問題を解決できます(最初、2番目、3番目のインデックスを使用するか...)。

3D の場合、最初にループ変数 ( ijおよびk)を宣言できます。

std::size_t i, j, k;

r次に、別の変数 ( ) を にijまたはkテンプレート値に従って「リンク」できます。I

std::size_t & r = (I == 0U ? i : (I == 1U ? j : k));

以下はコンパイル可能な例です

#include <vector>
#include <iostream>

template <std::size_t I>
void func (std::vector<std::vector<std::vector<double> > > & d)
 {
   std::size_t i, j, k;

   std::size_t & r = (I == 0U ? i : (I == 1U ? j : k));

   for ( i = 0U ; i < d.size() ; ++i )
     for ( j = 0U ; j < d[i].size() ; ++j )
       for ( k = 0U ; k < d[i][j].size() ; ++k )
          d[i][j][k] += r+1;
 }

int main()
 {
   std::vector<std::vector<std::vector<double> > > data;

   // some data in data

   func<0>(data); // r is i
   func<1>(data); // r is j
   func<2>(data); // r is k
 }

- - 編集 - -

OPの質問

とにかく、この関数が任意の次元で機能する可能性はありますか?

いいえ。

この機能ではありません。

しかし、私はまったく異なる (そしてより複雑な) 解決策を提案します。私はそれを書いていますが、それが本当に機能するかどうかを確認するように求めていません。

アイデアはもはや参照に基づくものではなく、テンプレートの専門化に基づいています。

今回は、テンプレート インデックスは 1 ベースです。1最初のインデックス (ex ) をインターセプトする場合xはテンプレート値を使用2し、2 番目のインデックス (ex y) をインターセプトする場合は、などを使用します。

だからあなたは電話する

foo<1U>(data1);    // r is the first index

1D ベクトルの場合、

foo<1U>(data2);     // r is the first index
foo<2U>(data2);     // r is the second index

2D ベクトルなど

電話すれば

foo<I>(data)

どこでIの次元よりも大きい場合data、コンパイル エラーが発生します。

電話すれば

foo<0>(data)

コンパイル エラーが発生しますが、これは C++11 以降をコンパイルした場合のみです (C++98 ではゼロになりますが、ランタイム エラーを取得するために をr追加できます)。assert()

#include <vector>
#include <iostream>

template <std::size_t I>
struct bar
 {
   template <typename T>
   static void baz (std::vector<T> & v, std::size_t)
    {
      for ( std::size_t i = 0U ; i < v.size() ; ++i )
         bar<I-1U>::baz(v[i], i);
    }
 };

template <>
struct bar<0U>
 {
   template <typename T>
   static void baz (std::vector<T> & v, std::size_t r)
    {
      for ( std::size_t i = 0U ; i < v.size() ; ++i )
         baz(v[i], r);
    }

   static void baz (double & d, std::size_t r)
    { d += r + 1U; }
 };


template <std::size_t I, typename V>
void foo (V & v)
 {
#if __cplusplus >= 201103L   
   static_assert(I > 0U, "!"); // c++11 or newer
#endif

   bar<I>::baz(v, 0U);
 }

int main()
 {
   std::vector<double >                            data1;
   std::vector<std::vector<double> >               data2;
   std::vector<std::vector<std::vector<double> > > data3;

   // some data in data1, data2 and data3

   // foo<0U>(data1);  // compilation error in C++11 or newer
   foo<1U>(data1);     // r is the first index
   // foo<2U>(data1);  // compilation error

   // foo<0U>(data2);  // compilation error in C++11 or newer
   foo<1U>(data2);     // r is the first index
   foo<2U>(data2);     // r is the second index
   // foo<3U>(data2);  // compilation error

   // foo<0U>(data3);  // compilation error in C++11 or newer
   foo<1U>(data3);     // r is the first index
   foo<2U>(data3);     // r is the second index
   foo<3U>(data3);     // r is the third index
   // foo<4U>(data3);  // compilation error
 }
于 2016-12-31T22:23:04.903 に答える