Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1370 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Specialisation partielle de fonction membre de classes templates...

 

Sujet(s) à lire :
    - Spécialisation des templates
 

 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Specialisation partielle de fonction membre de classes templates...

n°1251206
Mackila
Posté le 23-11-2005 à 01:13:17  profilanswer
 

...C'est faisable ? Les choses n'ont pas évolué depuis le dernier sujet ?
 
ma reference
 

Code :
  1. #include <iostream>
  2. #include <string>
  3. using namespace std ;
  4. template <class T, int I>
  5. class test {
  6. public :
  7. void methode(T t) { cout << "generique " << t << " " << I << endl ; }
  8. // Plein d'autres méthodes
  9. } ; // class test
  10. /*
  11. provoque une erreur, mais c'est pourtant ce que je voudrais :  
  12. spécialiser le comportement d'une seule méthode...
  13. template <int I>
  14. void test<string,I>::methode(string t) { cout << "specifique string " << I << endl ; }
  15. */
  16. template <>
  17. void test<string,4>::methode(string t) { cout << "specifique string 4" << endl ; }
  18. int main(int argc, char* argv[])
  19. {
  20. test<long, 2>  tl2 ;
  21. test<string,3> ts3 ;
  22. test<string,4> ts4 ;
  23. tl2.methode(1234)         ;
  24. ts3.methode("blabla" )     ;
  25. ts4.methode("oui, lol" )   ;
  26. return 0 ;
  27. }


 
J'aurais aimé spécialiser le comportement d'une seule méthode de ma classe lorsqu'un seul des paramètres change. La spécialisation fonctionne bien quand je spécialise ma méthode complètement...
 
Pour l'instant j'ai fait le crados (j'ai sorti mon code spécialisé dans une fonction, et j'ai écrit autant de spécialisations complètes de ma méthode - 3 - que nécessaire), mais ca ne me plait pas.
 
 
 

mood
Publicité
Posté le 23-11-2005 à 01:13:17  profilanswer
 

n°1252519
Mackila
Posté le 24-11-2005 à 18:41:12  profilanswer
 

Bide.

n°1252527
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 24-11-2005 à 18:48:45  profilanswer
 

bon anniversaire :hello:

n°1252565
Mackila
Posté le 24-11-2005 à 19:32:44  profilanswer
 

Ha oui, merci :D (3 ans déja...)
 
Et sinon, pour les templates  :whistle:

n°1252590
++fab
victime du syndrome IH
Posté le 24-11-2005 à 20:00:31  profilanswer
 

comme tu as pu le remarquer, ce que tu veux faire n'est pas légal. Voici une modeste façon de contourner le problème, s'appuyant sur la résolution de surcharge.  
A la résolution de surcharge, une fonction non template est élue face à une fonction template uniquement s'il y a match exact. Les conversions implicites ne sont pas considérées. C'est pourquoi il faut fournir une surcharge char const*.
 

Code :
  1. #include <iostream>
  2. #include <string>
  3. #include <boost/type_traits/is_convertible.hpp>
  4. #include <boost/mpl/assert.hpp>
  5. template <class T, int I>
  6. class test
  7. {
  8. public:
  9.     template <class T2>
  10.     void methode( T2 const& t ) const
  11. {
  12.     BOOST_MPL_ASSERT(( boost::is_convertible<T,T2> ));
  13.     std::cout << "generique " << t << ' ' << I << '\n';
  14. }
  15.     void methode( std::string const& s ) const
  16. { do_it(); }
  17.     void methode( char const* s ) const
  18. { do_it(); }
  19. private:
  20.     void do_it() const
  21. { std::cout << "specifique string " << I << '\n'; }
  22. };
  23. int main()
  24. {
  25.     test<long,2>  tl2;
  26.     test<std::string,3> ts3;
  27.     test<std::string,4> ts4;
  28.    
  29.     tl2.methode(1234.9); // pas de warnings :/
  30.     tl2.methode<long>(1234.9); // pour avoir des warnings
  31.     ts3.methode("blabla" );
  32.     ts4.methode("oui, lol" );
  33. }

n°1252669
Mackila
Posté le 24-11-2005 à 21:17:52  profilanswer
 

edit (conneries supprimées) : Ha mais si, j'ai mal lu. Bon faudra vraiment que je réfléchisse à ton truc demain :D
 
Merci  :) !


Message édité par Mackila le 24-11-2005 à 21:20:08
n°1252791
++fab
victime du syndrome IH
Posté le 24-11-2005 à 23:23:13  profilanswer
 

YES !
 
beaucoup plus simple en apparance. friend for ever :D
 
 

Code :
  1. #include <iostream>
  2. #include <string>
  3. template <class T, int I>
  4. class test
  5. {
  6. public:
  7.     friend void freef( T const& t )
  8. { std::cout << "generique " << t << ' ' << I << '\n'; }
  9.     friend void freef( std::string const& s )
  10. { std::cout << "specifique string " << I << '\n'; }
  11.     void methode( T const& t ) const
  12. { freef( t ); }
  13. };
  14. int main()
  15. {
  16.     test<long,2>  tl2;
  17.     test<std::string,3> ts3;
  18.     test<std::string,4> ts4;
  19.     tl2.methode( 1234 );
  20.     tl2.methode(1234.9);
  21.     ts3.methode("blabla" );
  22.     ts4.methode("oui, lol" );
  23.     freef( 5 ); // (*)
  24. }


 
(*) le minuscule (inexistant normalement) désagrément de cette technique est la pollution de la namespace scope par la fonction libre freef. Cepandant, avec un compilateur a la norme, cette ligne ne doit pas compiler. Si elle compile, c'est que le compilateur supporte encore l'extension "friend name injection" chère à Barton & Nackman. gcc < 4.1 la supporte par défaut, et une beta d'aout de gcc-4.1 que j'ai, continue de compiler ce code (?!).
 
edit : changement de l'ordre de declaration


Message édité par ++fab le 25-11-2005 à 08:12:47
n°1252833
Mackila
Posté le 25-11-2005 à 00:38:21  profilanswer
 

Heu j'ai pas tout suivi la  :??:  
 
Quelque chose me dit que je vais passer pas mal de temps à lire de gros pavés d'explication du bouzin, demain (enfin tout à l'heure).  :sweat:  
 
Ca me parait quand même vachement space comme truc, t'aurais pas deux trois explications sur le pourquoi et comment ca marche ? (il est minuit et demi, aussi, ca aide pas...)
 
edit : et passe pas sous VS7...

Message cité 2 fois
Message édité par Mackila le 25-11-2005 à 00:43:57
n°1252838
++fab
victime du syndrome IH
Posté le 25-11-2005 à 00:46:31  profilanswer
 

Mackila a écrit :

Heu j'ai pas tout suivi la  :??:  
 
Quelque chose me dit que je vais passer pas mal de temps à lire de gros pavés d'explication du bouzin, demain (enfin tout à l'heure).  :sweat:


 
ne regarde que la deuxième solution, la première est vraiment mauvaise en fait.
 

Mackila a écrit :

Ca me parait quand même vachement space comme truc, t'aurais pas deux trois explications sur le pourquoi et comment ca marche ? (il est minuit et demi, aussi, ca aide pas...)


 
si, qu'est-ce que tu ne comprends pas ? ( en meme temps, c'est minuit et demi ...)

n°1252839
++fab
victime du syndrome IH
Posté le 25-11-2005 à 00:47:34  profilanswer
 

Mackila a écrit :

edit : et passe pas sous VS7...


message d'erreur ?

mood
Publicité
Posté le 25-11-2005 à 00:47:34  profilanswer
 

n°1253440
Mackila
Posté le 25-11-2005 à 18:26:58  profilanswer
 

Compilation...
testtemplate.cpp
d:\Documents\Mes projets\testtemplate\testtemplate\testtemplate.cpp(14) : error C2084: la fonction 'void test<T,I>::freef(const std::string & )' a déjà un corps
        with
        [
            T=long,
            I=2
        ]
        d:\Documents\Mes projets\testtemplate\testtemplate\testtemplate.cpp(16) : voir la définition précédente de 'freef'
        d:\Documents\Mes projets\testtemplate\testtemplate\testtemplate.cpp(24) : voir la référence à l'instanciation du modèle de classe 'test<T,I>' en cours de compilation
        with
        [
            T=std::string,
            I=3
        ]
d:\Documents\Mes projets\testtemplate\testtemplate\testtemplate.cpp(17) : fatal error C1903: impossible de récupérer à partir des erreurs précédentes ; arrêt de la compilation

n°1253451
++fab
victime du syndrome IH
Posté le 25-11-2005 à 18:45:58  profilanswer
 

normal. Je me suis planté, la deuxième solution que j'ai proposée est complètement fausse, même si elle marche par chance chez moi (il faut dire que gcc ne m'a pas aidé d'un pouce). J'ai trouvé d'autres solutions ... J'espère que ce seront les bonnes :o
 
la première :  
 

Code :
  1. #include <iostream>
  2. #include <string>
  3. template <class T, int I>
  4. class test
  5. {
  6. public:
  7.     void methode( T const& t ) const
  8. { f( t ); }
  9. private:
  10.     template <class T2>
  11.     void f( T2 const& t ) const
  12. { std::cout << "generique " << t << ' ' << I << '\n'; }
  13.     void f( std::string const& s ) const
  14. { std::cout << "specifique string " << s << ' ' << I << '\n'; }
  15. };
  16. int main()
  17. {
  18.     test<long,2>  tl2;
  19.     test<std::string,3> ts3;
  20.     test<std::string,4> ts4;
  21.     tl2.methode( 1234 );
  22.     tl2.methode(123.9);
  23.     ts3.methode("blabla" );
  24.     ts4.methode("oui, lol" );
  25. }


 
la deuxième, plus compliqué, moins extensible, moins bonne tout court, mais intéressante (à partir d'un exemple à peine différent) :
 

Code :
  1. #include <iostream>
  2. #include <string>
  3. #include <boost/type_traits/is_same.hpp>
  4. namespace
  5. {
  6.     class Toto {};
  7. }
  8. template <class T1, class Bool>
  9. struct foo
  10. {
  11.     typedef Toto type;
  12. };
  13. template <class T1>
  14. struct foo<T1, boost::false_type>
  15. {
  16.     typedef T1 type;
  17. };
  18. template <class T1, class T2>
  19. struct ToFailOverload : foo<T1, typename boost::is_same<T1,T2>::type> {};
  20. template <class T1, class T2, class T3, int N>
  21. class Test2
  22. {
  23. private:
  24.     typedef double overloadType;
  25. public:
  26.     void methode( typename ToFailOverload<T2,overloadType>::type t2 ) const
  27. { std::cout << "generique " << t2 << ' ' << N << '\n'; }
  28.     void methode( overloadType s ) const
  29. { std::cout << "double " << s << ' ' << N << '\n'; }
  30. };
  31. int main()
  32. {
  33.     Test2<int,std::string ,std::string,4> test2;
  34.     test2.methode( "toto" );
  35.    
  36.     Test2<int,double,bool,4> test3;
  37.     test3.methode( 4.3 );
  38. }


 
avec peut etre un travail à faire pour épurer les cv-qualifiers, mais bon.


Message édité par ++fab le 25-11-2005 à 18:50:31
n°1253489
Mackila
Posté le 25-11-2005 à 20:27:54  profilanswer
 

La premiere me plait beaucoup plus (et en plus elle fonctionne :P).
J'adapterai ca sur mon code lundi (en rajoutant un bon pavé d'explications pour le gars qui repasserait éventuellement derrière, que les méthodes que je spécialise, c'est des opérateurs, ca a tendance à faire une syntaxe comme qui dirait un peu lourde :D )
 
Merci !  :jap:


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Specialisation partielle de fonction membre de classes templates...

 

Sujets relatifs
[Résolu]Utiliser une fonction dans un fichier PHPEquivalent VBA de la fonction MODE (pour excel)
Fonction pour pour convertir le code HTMLMenu en fonction des droits
besoin aide c++, fonction isnumerikboucle pour fonction mail()
fonction int premier(long n)La fonction TRIM
Appeler une fonction GetUrl dans un fichier XMLIntrospection : comment trouver toutes les classes filles ?
Plus de sujets relatifs à : Specialisation partielle de fonction membre de classes templates...


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR