[C++ / résolu] Vérifier le type donné à un template... typeid?

Vérifier le type donné à un template... typeid? [C++ / résolu] - C++ - Programmation

Marsh Posté le 23-07-2006 à 13:32:13    

Salut à tous :)
 
Bon, j'ai une classe pour faire des calculs mathématiques, j'ai décidé d'en faire un template pour l'instancier soit avec float, soit avec double selon la précision des calculs désirés (ou la taile mémoire occupée).
 
Seulement, à un moment donné je doit connaître quel est le type passé en argument du template pour pouvoir appeler a bonne fonction, j'ai essayé avec typeid, mais ça me fait une belle erreur assez incompréhensible:
 

Code :
  1. template <typename Real> class Math
  2. {
  3.   public:
  4.   inline static Real sqrt(Real v)
  5.   {
  6.     if(v.typeid()==((float)0).typeid())
  7.       return sqrtf(v);
  8.     else
  9.       return ::sqrt(v);
  10.   }
  11. };


GCC4 me dit:


./math.h: In static member function 'static Real Math<Real>::sqrt(Real)':
./math.h:49: error: expected unqualified-id before 'typeid'
./math.h:49: error: expected `)' before 'typeid'


Message édité par nargy le 23-07-2006 à 16:03:12
Reply

Marsh Posté le 23-07-2006 à 13:32:13   

Reply

Marsh Posté le 23-07-2006 à 14:48:35    

1 - typeid n'est pas une fonction membre.  
2 - la présence de condition n'empêche pas l'instanciation. Si tu instanties Real avec double, sqrtf doit pouvoir prendre un double ...
3 - tu pourrais implémenter Real et utilisant simplement std::sqrt.
4 - Sans blagues !

Reply

Marsh Posté le 23-07-2006 à 15:04:00    

A la limite, si c'est pour mettre une condition pour chaque type de template, autant coder plusieurs fois la fonctions ... les templates perdent tout leur interet si c'est pour les utiliser comme une surcharge de fonction :)


---------------
tutos de programmation 3D :
Reply

Marsh Posté le 23-07-2006 à 15:47:16    

Ah oui, je vais voir du côté de std::sqrt... voir comment c'est codé.
 
En fait, la fonction sqrt n'est qu'un exemple, j'ai besoin de stocker une grosse matrice et je ne suis sûr ni qu'elle tiendrait en mémoire, ni de quelle précision de calcul j'aurais besoin. Pour info, sqrt me servirait à calculer le cosinus entre deux rangs ou deux colonnes de la matrice, mais j'en ai d'autres pas trop standards à base de décalage de bits sur des flottants!
 
Pour l'instant j'ai des gros #ifdef REALISDOUBLE... Je ne vois que les templates en C++ pour me faire un code identiquement optimisé.
 
Une autre possibilité serait d'utiliser sizeof(Real), comme dans la librairie standard <math.h>.
 
Le problème de l'instanciation n'en est pas un, il me semble, car double et float sont convertibles entre eux d'une part. D'autre part, il me semble que normalement sur une condition toujours vraie (ou fausse) le compilo ne génère pas le code correspondant au if, ni la condition fausse (ou vraie).

Reply

Marsh Posté le 23-07-2006 à 15:57:15    

Je m'éloigne du sujet de départ, mais en quoi sqrt peut servir pour calculer le cosinus de deux vecteurs d'une matrice ?
Ou est-ce tout simplement pour calculer la norme de chaque vecteur u et v pour aboutir à   cos  =  ( u | v ) / ( sqrt(  u | u ) * sqrt( v | v ) )   ?
 
Si c'est pas pour ca, je demmande à savoir :) tjrs en manque d'apprendre des nvelles choses ! ;)
 
[edit] c'est quoi "deux RANGS d'une matrice" ? je connais le rang, qui est le rang de l'application linéaire associé bla bla, ou encore le nombre de vecteurs colones lineairements indépendants ds la matrice, mais qd tu dis deux rangs... tu veux dire deux rangées ?


Message édité par icareo le 23-07-2006 à 15:59:22

---------------
tutos de programmation 3D :
Reply

Marsh Posté le 23-07-2006 à 15:57:35    

ah ouais, peut être bien une solution plus simple ferai l'affaire:

Code :
  1. inline static Real sqrt(float v)
  2. { return sqrtf(v); }
  3. inline static Real sqrt(double v)
  4. { return ::sqrt(v); }
  5. inline static Real sqrt(long double v)
  6. { return sqrtl(v); }

Reply

Marsh Posté le 23-07-2006 à 15:58:27    

exact, cosinus = produit scalaire / (norme1 * norme2)

Reply

Marsh Posté le 23-07-2006 à 15:59:48    

template <class T>
static Real sqrt( T v )
{ return std::sqrt( v ); }

Reply

Marsh Posté le 23-07-2006 à 16:00:44    

wai, quand t'as seulement un petit nombre de types à traiter, des fois la surcharge de fonctions est moins casse tete que les templates ^^
 
cf aussi mon edit de mon post précédent, pr info :s


---------------
tutos de programmation 3D :
Reply

Marsh Posté le 23-07-2006 à 16:01:37    

exact, ++fab... le code que j'ai donné plus haut est ce que fait std::sqrt.

Reply

Marsh Posté le 23-07-2006 à 16:01:37   

Reply

Marsh Posté le 23-07-2006 à 16:01:38    

std::sqrt est surchargée ?


---------------
tutos de programmation 3D :
Reply

Marsh Posté le 23-07-2006 à 16:02:02    

ok


---------------
tutos de programmation 3D :
Reply

Marsh Posté le 23-07-2006 à 16:03:28    

Merci à vous deux :)

Reply

Marsh Posté le 23-07-2006 à 16:38:13    

nargy a écrit :

Le problème de l'instanciation n'en est pas un, il me semble, car double et float sont convertibles entre eux d'une part.


Oui, là ça ne pose pas de problème. Mais je pense que tu as compris l'idée.
 

Citation :

D'autre part, il me semble que normalement sur une condition toujours vraie (ou fausse) le compilo ne génère pas le code correspondant au if, ni la condition fausse (ou vraie).


Il instantie quand même. Lors d'une passe ultérieur, il pourra décider de ne pas générer de code.

Reply

Marsh Posté le 23-07-2006 à 17:54:39    

++fab> merci de préciser, c'était bien ce que je voulais dire... il s'agit de compilation optimisante.
 
Autre solution peut être plus élégante (?): les template spécialisés (je les avais totalement oubliés ceux-là!)
 
Exemple avec des fonctions templates:

Code :
  1. template <typename Real>
  2.   inline static Real sqrt(Real v)
  3. { // normalement c'est ici qu'on lance une exception...
  4. // ... ou que l'on trouve le bon pragma du compilo
  5.   cerr<< "On ne calcule pas de racine carré autre que pour les types float et double! -- et puis quoi encore??" ; exit(314);
  6. }
  7. template <>
  8.   inline static float sqrt(float v)
  9. { return sqrtf(v); }
  10.      
  11. template <>
  12.   inline static double sqrt(double v)
  13. { return ::sqrt(v); }


Note: j'ai pas compilé le code ci-dessus mais ça devrai passer...

Reply

Marsh Posté le 23-07-2006 à 23:21:59    

regarde du coté de BOOST_STATIC_ASSERT pour emettre un message d'erreur à la compialtion.

Reply

Marsh Posté le 24-07-2006 à 01:08:58    

ça sert à rien dernier code, mais alors a rien. surtout avec le exit tout pourri. Si ça n'existe pas, alors ne le code pas. T'auras une erreur de compilation est c'est tout. Et je vois pas l'intérêt de ces templates dans ce cas précis. donc en gros ton dernier morceau de code ne sert à rien et se réduit à std::sqrt(x)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed