[C++] Spécialisation d'une fonction template un peu tordue...

Spécialisation d'une fonction template un peu tordue... [C++] - C++ - Programmation

Marsh Posté le 09-02-2010 à 13:35:42    

Bonjour
 
J'ai une question à laquelle je n'arrive pas à trouver de solution : j'ai une fonction template que je voudrais spécialiser pour une instance d'une classe template.
 
Un exemple valant mieux qu'un long discourt, voici mon cas. J'ai la classe templatisée suivante :

Code :
  1. template<class T>
  2. class Size
  3. {
  4. public :
  5.   T width;
  6.   T height;
  7. };


Ainsi que la fonction template suivante :

Code :
  1. template<class T>
  2. bool IsEqual(const T & a, const T & b)
  3. {
  4.   return (a == b);
  5. }


Bien évidemment, il y a eut des spécialisations pour cette méthode (notamment pour les cas des doubles).
 
L'idée serait de spécialiser IsEqual avec la class Size, histoire d'avoir un code similaire à ça :

Code :
  1. template<class T>
  2. bool IsEqual(const Size<T> & a, const Size<T> & b)
  3. {
  4.   return IsEqual<T>(a.width, b.width) && IsEqual<T>(a.height, b.height);
  5. }


Bien évidemment, ça ne marche pas (sinon je ne posterais pas là ^^)... pour spécialiser, il faut que je spécifie "template<>"   j'ai beau cherché, je ne trouve pas de solutions :/ Enfin si, j'ai une solution, mais qui ne me convient pas vraiment (elle a le mérite de marcher au moins) : c'est de surdéfinir l'opérateur == de Size :

Code :
  1. inline bool operator==( const Size & size ) const
  2. {
  3.   return ivs::IsEqual<T>(width, size.width) && ivs::IsEqual<T>(height, size.height);
  4. }


(c'est ce que je fais pour le moment, faute de mieux)
 
Auriez vous une idée de réaliser la chose ? Un grand merci par avance ;)

Message cité 1 fois
Message édité par MrDiablo le 09-02-2010 à 13:57:18
Reply

Marsh Posté le 09-02-2010 à 13:35:42   

Reply

Marsh Posté le 09-02-2010 à 14:16:44    

MrDiablo a écrit :

Bonjour
 
J'ai une question à laquelle je n'arrive pas à trouver de solution : j'ai une fonction template que je voudrais spécialiser pour une instance d'une classe template.
 
Un exemple valant mieux qu'un long discourt, voici mon cas. J'ai la classe templatisée suivante :

Code :
  1. template<class T>
  2. class Size
  3. {
  4. public :
  5.   T width;
  6.   T height;
  7. };


Ainsi que la fonction template suivante :

Code :
  1. template<class T>
  2. bool IsEqual(const T & a, const T & b)
  3. {
  4.   return (a == b);
  5. }


Bien évidemment, il y a eut des spécialisations pour cette méthode
(notamment pour les cas des doubles).


 
Ca ne me semble pas evident du tout.  Je ne vois pas comment faire une
telle specialisation qui tienne la route.
 

Citation :

L'idée serait de spécialiser IsEqual avec la class Size, histoire d'avoir un code similaire à ça :

Code :
  1. template<class T>
  2. bool IsEqual(const Size<T> & a, const Size<T> & b)
  3. {
  4.   return IsEqual<T>(a.width, b.width) && IsEqual<T>(a.height, b.height);
  5. }


Bien évidemment, ça ne marche pas (sinon je ne posterais pas là ^^)... pour
spécialiser, il faut que je spécifie "template<>"


 
Ce que tu ecris n'est pas une specialisation, mais une surcharge.  Et ca
devrait fonctionner sans probleme.  En tout cas

Code :
  1. #include <iostream>
  2. template <class T>
  3. class Size
  4. {
  5. public:
  6.     T width;
  7.     T height;
  8. };
  9. template <class T>
  10. bool isEqual(T const& a, T const& b)
  11. {
  12.     std::cout << "isEqual<T>(T const&, T const& );\n";
  13.     return true;
  14. }
  15. template <class T>
  16. bool isEqual(Size<T> const&a, Size<T> const& b)
  17. {
  18.     std::cout << "isEqual<T>(Size<T> const&, Size<T> const& )\n";
  19.     return isEqual(a.width, b.width) && isEqual(a.height, b.height);
  20. }
  21. int main()
  22. {
  23.     int a, b;
  24.     Size<int> c, d;
  25.     isEqual(a, b);
  26.     isEqual(c, d);
  27.     return 0;
  28. }


 
a le comportement auquel je m'attends.  (Note que j'ai ecrit
isEqual(a.width, b.width) et non isEqual<T>(a.width, b.width) pour
permettre a une eventuelle autre surcharge de jouer son role).
 
Une specialisation partielle s'ecrirait

Code :
  1. template <>
  2. template <class T>
  3. bool isEqual(Size<T> const&a, Size<T> const& b)
  4. {
  5. ...
  6. }


Mais effectivement, on ne peut pas specialiser partiellement une fonction.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 09-02-2010 à 15:10:39    

En tout premier lieu, merci pour ta réponse ;)
 

Un Programmeur a écrit :


Ca ne me semble pas evident du tout.  Je ne vois pas comment faire une
telle specialisation qui tienne la route.


Effectivement (et c'est pour cette raison que j'ai posté, c'est bien la première fois que je demande de l'aide ainsi).
 

Citation :


Ce que tu ecris n'est pas une specialisation, mais une surcharge.  Et ca
devrait fonctionner sans probleme.


Exactement. Je n'ai pas dit qu'il s'agissait d'une spécialisation, mais d'une solution (qui me permet d'avancer et d'éviter de rester coincer sur le sujet... au moins, j'ai un programme qui tourne, même si ce n'est pas l'idéal). J'en ai parlé pour éviter qu'elle soit aborder ;)
 

Citation :


Mais effectivement, on ne peut pas specialiser partiellement une fonction.


Rien à redire ^^

Reply

Marsh Posté le 09-02-2010 à 15:25:45    

MrDiablo a écrit :


Effectivement (et c'est pour cette raison que j'ai posté, c'est bien la première fois que je demande de l'aide ainsi).


 
Tu ici parlais des doubles.  Je faisais allusion au fait qu'une specialisation pour les doubles faisant intervenir un epsilon a toutes les chances de ne pas etre transitive ce qui, en plus du probleme de determination d'un epsilon adequat, va la rendre aussi problematique que la version avec l'operateur ==.
 
Les flottants, c'est delicats.
 


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 09-02-2010 à 19:01:19    

Un Programmeur a écrit :


 
Tu ici parlais des doubles.  Je faisais allusion au fait qu'une specialisation pour les doubles faisant intervenir un epsilon a toutes les chances de ne pas etre transitive ce qui, en plus du probleme de determination d'un epsilon adequat, va la rendre aussi problematique que la version avec l'operateur ==.
 
Les flottants, c'est delicats.
 


Code :
  1. template<class T>
  2. class Size
  3. {
  4. public :
  5.   T width;
  6.   T height;
  7. bool operator==( const Size &a) const
  8. {
  9.         return ((this->width==a.width) && (this->height==a.height));
  10. }
  11. };
  12. template<class T>
  13. bool isEqual(const T &a, const T &b) {return a==b;}


c'est pas bon? (mis à part l'égalité de floats)


Message édité par GrosBocdel le 09-02-2010 à 19:01:45
Reply

Marsh Posté le 09-02-2010 à 19:06:45    

À première vue, trois problèmes.  Ça n'utilise pas isEqual (qui peut être spécialisé ou surchargé) pour comparer les membres, ça ajoute un opérateur== qui peut ne pas être désiré, l'opérateur== n'est pas symétrique (visible si il y a des conversions implicites vers Size<T> ).


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 09-02-2010 à 19:21:19    

Un Programmeur a écrit :

l'opérateur== n'est pas symétrique (visible si il y a des conversions implicites vers Size<T> ).


T'as un exemple là dessus?

Reply

Marsh Posté le 28-02-2010 à 00:44:53    

Code :
  1. class DoubleSize
  2. {
  3. public:
  4.     operator Size< double >() const;
  5.     // some more code
  6. private:
  7.     double w;
  8.     double h;
  9. };
  10. Size< double > x;
  11. DoubleSize y;
  12. x == y; // toujours ok
  13. y == x; // marche pas avec ton code, mettre operator== en free fonction, ou friend function.


 
J'avoue que souvent je mets aussi operator== en methode membre par pure flemme, mais c'est pas bien, sauf si t'es absolument certain que ton type ne sera pas dérivé, implicit-casté etc...

Reply

Marsh Posté le 28-02-2010 à 08:06:08    

les opérateurs binaires, sauf semantique spéciale n'ont pas a etre membre ou friend. Des fonctions libres suffisent.

Reply

Sujets relatifs:

Leave a Replay

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