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

  FORUM HardWare.fr
  Programmation
  C++

  Spécialisation d'un modèle vers modèle utilisant des pointeurs

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Spécialisation d'un modèle vers modèle utilisant des pointeurs

n°1529041
Amonchakai
Posté le 15-03-2007 à 18:40:37  profilanswer
 

Bonjour,
   Je me suis posé un petit exercice : j'ai d'abord cherché à créer un modèle de conteneur associatif.
Ce qui me donne :  

Code :
  1. #include<vector>
  2. #include<algorithm>
  3. template<typename T, typename T2>
  4. struct Pair
  5. {
  6. T key;
  7. T2 value;
  8. Pair(T gkey):key(gkey){};
  9. Pair(T gkey, T2 gvalue):key(gkey), value(gvalue) {};
  10. bool operator==(const Pair<T, T2> &other);
  11. };
  12. template<typename T, typename T2>
  13. bool Pair<T, T2>::operator ==(const Pair<T,T2> &other)
  14. {
  15. return (other.key == key);
  16. }
  17. template<typename T, typename T2>
  18. class Map
  19. {
  20. std::vector<Pair<T, T2>> data;
  21. public:
  22. typedef typename std::vector<Pair<T,T2>>::iterator iterator;
  23. iterator begin();
  24. iterator end();
  25. virtual T2 &operator[](T key);
  26. };
  27. template<typename T, typename T2>
  28. T2 &Map<T, T2>::operator [](T key)
  29. {
  30. std::vector<Pair<T, T2>>::iterator it = data.begin();
  31. it = std::find(data.begin(), data.end(), Pair<T,T2>(key, T2()));
  32. if(it == data.end())
  33. {
  34.  data.push_back(Pair<T,T2>(key, T2()));
  35.  return (data.back()).value;
  36. }
  37. else
  38.  return (*it).value;
  39. }
  40. template<typename T, typename T2>
  41. typename Map<T,T2>::iterator Map<T, T2>::begin()
  42. {
  43. return data.begin();
  44. }
  45. template<typename T, typename T2>
  46. typename Map<T,T2>::iterator Map<T, T2>::end()
  47. {
  48. return data.end();
  49. }


Donc ça, j'ai pas de soucis : ça marche. Mais a titre d'exercice je me suis dit que j'allais chercher a traiter autrement les pointeurs. Donc pour cela j'ai dérivé mon modèle comme ça :

Code :
  1. template<typename T, typename T2>
  2. class Map<T, T2*> : public Map<T, T2>
  3. {
  4. public:
  5. T2 *operator[](T key);
  6. };
  7. template<typename T, typename T2>
  8. T2 *Map<T, T2*>::operator [](T key)
  9. {
  10. std::vector<Pair<T, T2>>::iterator it = data.begin();
  11. it = std::find(data.begin(), data.end(), Pair<T,T2>(key));
  12. if(it == data.end())
  13. {
  14.  data.push_back(Pair<T,T2*>(key, &T2()));
  15.  return (data.back()).value;
  16. }
  17. else
  18.  return (*it).value;
  19. }


Mais la, mon problème c'est qu'il est pas content que le type de retour de mon opérateur [] change entre la classe mère et la classe fille. Ce que je comprend... mais en fait je vois pas comment régler le problème. (autre que de changer d'exemple pour m'entrainer à ce type de spécialisation... :D )
 
Donc, je sais pas si vous voyez une solution...
Merci :)
 
ps : au passage si il y a quelque chose qui vous choque dans mon utilisation des modèles, merci de me le signaler (je demande qu'a m'améliorer :) )

mood
Publicité
Posté le 15-03-2007 à 18:40:37  profilanswer
 

n°1529300
Joel F
Real men use unique_ptr
Posté le 16-03-2007 à 08:45:59  profilanswer
 

Bon ... y a des trucs à revoir :|
 
Deja ton schéma d'héritage entre modèle me  
parait pas la meilleur solution. Ensuite, tu  
cherche à spécialiser partiellement une méthode  
de ton modèle dans le cas ou T2 est un pointeur.  
Pour cela, il te faut résoudre 2 problèmes :
 
-> générer un type de retour valide
-> changer le contenu de ta méthode.
 
Une maniére plus propre consiste à :
 
1/ Génération du type de retour :
On utilise une technique qui s'appelle les Traits.  
Cette technique consiste à utiliser des spécialisations  
de template comme un filtre logique (un match en ML).  
Ici on a deux cas :
 
T2 quelconque -> on renvoit T2&
T2* -> on renvoit T2*
 
 
En outre, lorsque tu crée T2& , il faut faire gaffe au fait  
que T2 ne soit pas déjà une référence ! On crée donc le modèle  
suivant  
 

Code :
  1. template<class T> struct return_type
  2. {
  3.    typedef T& type;
  4. };
  5. template<class T> struct return_type<T&>
  6. {
  7.    typedef T& type;
  8. };
  9. template<class T> struct return_type<T*>
  10. {
  11.    typedef T* type;
  12. };


 
On peut désormais récupérer le type de retour de manière géénrique.
 
2/ Modifier le contenu de ta méthode
Même constat. On va exporter le code dabs un modèle ad-hoc qui sera appelé depuis ton modèle.
 
 
On crée donc un modèle qui ne contient que ton code de recherche dnas chaque cas.
 

Code :
  1. template<class T, class T2>
  2. struct map_access
  3. {
  4.   typedef typename return_type<T2>::type type;
  5.   typedef std::vector<Pair<T,T2>>        map_type;
  6.   static inline type run( const T& key, const map_type& data )
  7.   {
  8.     typename map_type::iterator it = data.begin();
  9.     it = std::find(data.begin(), data.end(), Pair<T,T2>(key, T2()));
  10.     if(it == data.end())
  11.     {
  12.       data.push_back(Pair<T,T2>(key, T2()));
  13.       return (data.back()).value;
  14.     }
  15.     else
  16.       return (*it).value;
  17.   }
  18. };
  19. template<class T, class T2>
  20. struct map_access<T,T2*>
  21. {
  22.   typedef typename return_type<T2*>::type type;
  23.   typedef std::vector<Pair<T,T2*>>        map_type;
  24.   static inline type run( const T& key, const map_type& data )
  25.   {
  26.     typename map_type::iterator it = data.begin();
  27.     it = std::find(data.begin(), data.end(), Pair<T,T2*>(key));
  28.     if(it == data.end())
  29.     {
  30.        data.push_back(Pair<T,T2*>(key, &T2()));
  31.        return (data.back()).value;
  32.     }
  33.     else
  34.       return (*it).value;
  35.   }
  36. };


 
Au final le code de Map<T,T2>::operator[] devient
 

Code :
  1. template<typename T, typename T2>
  2. typename return_type<T2>::type Map<T, T2>::operator [](T key)
  3. {
  4.   return map_access<T,T2>::run(key,data);
  5. }


 
Voila le principe.
 
Ensuite quelques conseils :
 
1/ std::map pue du bec que tu ai envie d'en réécrire un moins bien ?
2/ Y a plein de problème de const qui manque partout ...
3/ Il faut garder à l"esprit que lorsque tu écris du code à base de template, il faut que la PLUS GROSSE PARTIE du code manipulant des types soit générique. T2& c'ets pas générique, return_type l'est beaucoup plus car tu contrôle précisement tes schémas de spécialisation.
4/ utilise le plus possible les modéles de BOOST::Traits et de BOOST::mpl pour te simplifier la vie sur ce genre de tests


Message édité par Joel F le 16-03-2007 à 09:00:10
n°1529443
Amonchakai
Posté le 16-03-2007 à 12:30:37  profilanswer
 

Merci, beaucoup de ton aide !
 
   Bon, je vais m'entrainer encore mais j'ai compris le principe  
   bien sur, il est clair que c'est pas que la std::map "pue du bec" que j'ai essayé d'en faire une mais en fait c'est un exercice qui étais proposé dans mon Stroustrup. Je viens de lire le chapitre sur les modèles et donc je fais ensuite les exercices
 
Donc je vais améliorer tout ça... Merci pour tes conseils et de m'avoir montré le principe qu'il faut utiliser :)

n°1529444
Taz
bisounours-codeur
Posté le 16-03-2007 à 12:33:53  profilanswer
 

ouaich, vive les traits (que y en a plein de défini en standard déjà)

n°1529684
++fab
victime du syndrome IH
Posté le 16-03-2007 à 19:03:44  profilanswer
 

Taz a écrit :

ouaich, vive les traits (que y en a plein de défini en standard déjà)


mmouuais. C'est dans TR1, et ce sera probablement au prochain standard, mais c'est surclassé par les concepts.


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

  Spécialisation d'un modèle vers modèle utilisant des pointeurs

 

Sujets relatifs
linux: compiler en utilisant allegroAvis pour programme utilisant JAI (Java Advanced Imaging)
création automatique de raccourcis vers des dossiersnom-domaine.fr: redirection nom de domaine vers site
HELP! Parser un fichier de conf et renvoyer vers structPage hmtl vers Message Outlook
[POO] Champ de texte et MVC (modèle vue contrôleur)[PHP] Comment on limite les accès à un forum via chmod ?
Un ControlToValidate (composant .net) qui pointe vers une fonctionVariable d'un applet java vers du php
Plus de sujets relatifs à : Spécialisation d'un modèle vers modèle utilisant des pointeurs


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