2012-12-06 4 views
0

Je travaille avec la classe Matrix modélisée dans la bibliothèque Eigen linear algebra (link). La classe Matrix prend trois paramètres de modèle nominaux:Utilisation de l'instruction conditionnelle pour sélectionner une classe de matrice différente au moment de l'exécution

Matrix<type, rows, cols> 

Dans ce qui précède, un exemple de type est double ou std::complex<double>. En outre, rows est le nombre de lignes et cols est le nombre de colonnes dans la matrice.

Comme le montre le code ci-dessous, ce que je voudrais faire est d'utiliser une classe Matrix différente lors de l'exécution en utilisant une instruction conditionnelle.

La première solution qui vient à l'esprit pourrait être d'utiliser des pointeurs de vide.

#include <iostream> 
#include <Eigen/Dense> 
#include <complex> 

using namespace Eigen; 

int main() 

{ 
    // this flag is set at run-time, but it is only set here 
    // in the code as an example 
    int create_complex = 1; 
    void *M; 

     if(create_complex) 
    { 
     Matrix<std::complex<double>,3,3> m0; 
     M = &m0; 
    } 
    else 
    { 
     Matrix<double,3,3> m0; 
     M = &m0; 
    } 
    // de-reference pointer here and use it  

return 0; 
} 

Bien que ce code compile, le pointeur void *M doit être explicitement de-référencé avant utilisation. Ceci est gênant, car je dois alors écrire des blocs de code différents pour la même logique de programme. Je me demande s'il y a quelque chose de similaire au polymorphisme qui pourrait être appliqué ici, où je n'ai pas besoin d'utiliser des pointeurs de vide.

+0

L'indicateur 'create_complex' n'est pas connu au moment de la compilation. J'utilise simplement 'create_complex' comme exemple. –

+0

Cela vous dérange-t-il d'utiliser 'boost :: variant'? J'essaierais très fort d'éviter d'être dans votre situation (peut-être qu'un peu plus de contexte nous aiderait à vous aider), mais si je le devais, j'irais avec. –

+0

@AlexandreC: Bien sûr, je voudrais utiliser 'boost :: variant'. J'ai déjà utilisé la bibliothèque de boost, mais je ne peux pas dire que j'ai entendu parler de ce conteneur en particulier. Cela semble très intéressant. Comment pourrais-je l'utiliser? –

Répondre

1

Vous devriez aussi votre méthode créer des modèles à:

template<class T> 
my_main() { 

    Matrix<T,3,3> m0; 

    // ... 


} 

MISE À JOUR

Ou vous pouvez définir votre classe

#ifndef CREATE_COMPLEX 
    typedef double MyClass; 
#else 
    typedef std::complex<double> MyClass; 
#endif 

main() { 

    Matrix<MyClass,3,3> m0; 

    // ... 


} 

vous pouvez changer ces définitions avec la définition de préprocesseur.

+0

Bien sûr, la méthode pourrait être modélisée, et alors je n'aurais pas à traiter avec les pointeurs de vide. Merci, Dims. –

2

Ceci est pratique

Si vous lisez « pratique » comme « illégal », alors vous êtes sur place.

Les variables locales sont détruites à la fin de leur portée (c'est-à-dire la fermeture }), vous avez donc un pointeur qui pend. Vous allez donc rencontrer un comportement indéfini lorsque vous essayez de le dé-référencer.

Il n'y a pas de moyen facile de le faire, car Matrix<std::complex<double>,3,3> et Matrix<double,3,3> sont des classes complètement indépendantes. Je le répète. Ce sont des classes complètement indépendantes.

Une alternative est que Matrix a un type de base et vous avez un pointeur vers cela, mais alors vous auriez besoin d'allocation dynamique. Quelque chose comme:

BaseMatrix* m; 
if() 
    m = new Matrix<std::complex<double>,3,3>; 
else 
    m = new Matrix<double,3,3>; 
+0

@Lucian: Merci, Luchian; ça a du sens. –

2

Vous pouvez écrire votre propre fonction comme un modèle basé sur le type de matrice et appeler les différentes versions de ce dans les conditionals.

Ceci est le seul moyen car les modèles sont pour générer du code à compiler temps. Vous devez générer tous les chemins de code au moment de la compilation, puis sélectionnez l'un d'entre eux.

+0

Merci d'avoir signalé cela. –

Questions connexes