2016-12-31 2 views
1

Voici mon problème, j'ai affaire à une donnée en n dimensions. Disons n = 2 pour la simplicité. J'ai aussi un algorithme pour les données 1D. Afin d'étendre cet algorithme pour le problème 2D, je peux faireEst-il possible de réaliser un fonctionnement par colonne et un fonctionnement par ligne par une fonction de modèle?

for each row 
    apply algorithm 

Cependant, si je veux appliquer cet algorithme pour chaque colonne, je dois écrire une nouvelle fonction

for each column 
    apply algorithm 

Par exemple, Supposons que j'ai une fonction:

void func(vector<T> &vec); 

appliquer ensuite cette fonction à un vecteur je peux simplement appeler cette fonction:

vector<T> vec; 
func(vec); 

Pour les données 3D:

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

De ma connaissance, si je veux appliquer ci-dessus fonction pour tous les vecteurs de première dimension, je le ferai:

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

Cependant, pour la mêmes données, si je veux appliquer la fonction ci-dessus pour tous les vecteurs dans la troisième dimension, j'ai besoin de le réécrire comme:

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

Fondamentalement, tout est pareil sauf les itérateurs dans chaque boucle. J'espère qu'il y a des manières que je peux réaliser ces deux calculs avec une fonction.

Thx

Répondre

0

Je ne sais pas une solution générale mais vous pouvez résoudre votre problème (utilisez la première ou la deuxième ou la troisième index ou ...) en utilisant une référence.

Dans le cas 3D, d'abord, vous pouvez déclarer les variables de boucle (i, j et k)

std::size_t i, j, k; 

Ensuite, vous pouvez "lien" une autre variable (r) à i, j ou k selon un La valeur de modèle I

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

Ce qui suit est un exemple compilable

#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 
} 

--- EDIT ---

L'OP demander

est là de toute façon que cette fonction pourrait travailler pour la dimension arbitraire?

No.

Non cette fonction.

Mais je propose une solution complètement différente (et plus complexe). Je l'écris mais ne me demande pas de vérifier si cela fonctionne vraiment.

L'idée n'est plus basée sur la référence mais sur la spécialisation du template.

Cette fois, l'index de modèle est 1-basé: utiliser la valeur du modèle 1 si vous voulez intercepter le premier indice (ex x), 2 si vous voulez intercepter le second index (ex y), etc.

Alors vous appelez

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

pour un vecteur 1D,

pour un vecteur 2D, etc. .

Si vous appelez

foo<I>(data) 

I est plus grande que la dimension de data, vous obtenez une erreur de compilation.

Si vous appelez

foo<0>(data) 

vous obtenez une erreur de compilation, mais seulement si vous compilez C++ 11 ou plus récent (avec 98 r C++ deviennent zéro, mais vous pouvez ajouter un assert() pour obtenir une exécution Erreur).

L'exemple

#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

Y at-il de toute façon que cette fonction pourrait travailler pour la dimension arbitraire? –

+0

@DiMiao - réponse améliorée; J'espère que cela t'aides. – max66

+0

Thx, votre méthode me donne une bonne direction pour mon problème. C'est vraiment utile. –