2016-12-31 63 views
1

这是我的问题,我正在处理一个n维数据。为了简单起见,假设n = 2。另外我有一个数据的算法。为了扩大该算法的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); 
    } 
} 

但是,对于相同的数据,如果我想在第三维上应用上述所有向量的函数,我需要将其重写为:

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); 
    } 
} 

基本上,除了每个循环中的迭代器外,所有内容都是相同的。我希望有一些方法可以用一个函数来实现这两种计算。

THX使用参考

回答

0

我不知道一个通​​用的解决方案,但你可以解决您的特定问题(使用第一或第二或第三索引或......)。

在3D情况下,首先可以声明

std::size_t i, j, k; 

接下来,您可以 “链接” 另一个变量(r)至ijk根据循环变量(ijk)模板值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:使用模板值,如果你想如果你想拦截第二个索引截断第一指数(前x),21(前y)等

所以你叫

foo<1U>(data1); // r is the first 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 
} 
+0

反正是有这个功能可以为任意尺寸工作? –

+0

@DiMiao - 回答改善;希望这可以帮助。 – max66

+0

Thx,你的方法为我的问题提供了一个很好的方向。这真的很有帮助。 –