shadows template parm error

shadows template parm error - C++ - Programmation

Marsh Posté le 05-03-2008 à 07:55:15    

Bonjour,
 
je m'adresse à vous car j'ai un problème avec des classes que j'ai récupéré sur le CD d'un livre que j'ai acheté ("Introduction to C++ for financial engineers" by Daniel J. Duffy). Ce sont les classes de base de mon travail c'est à dire les structures de données (j'utilise des classe Vector, Array, Lattice...), malheureusement j'ai des erreurs lors de la compilation... J'ai réussi à en supprimer un certain nombre mais il m'en reste une sur laquelle j'ai un doute n'étant pas expert dans la définition de ce type de classe :
 
(Il s'agit ici du code du fichier Vector.hpp)
 

Code :
  1. #ifndef Vector_hpp
  2. #define Vector_hpp
  3. #include "Array.cpp"
  4. template <class V, class I=int, class S=FullArray<V> >
  5. class Vector: public Array<V, I, S>
  6. {
  7. public:
  8. // Constructors & destructor
  9.              ...
  10. // Operators
  11. Vector<V, I, S>& operator = (const Vector<V, I, S>& source);
  12. Vector<V, I, S> operator - () const;  // Unary minus
  13. template <class V, class I, class S>
  14. friend Vector<V, I, S> operator + (const Vector<V, I, S>& v,const V& a); // Add v to every element
  15. template <class V, class I, class S>
  16. friend Vector<V, I, S> operator + (const V& a, const Vector<V, I, S>& v);
  17. template <class V, class I, class S>
  18. friend Vector<V, I, S> operator - (const Vector<V, I, S>& v, const V& a); // Subtract v from every element
  19. template <class V, class I, class S>
  20. friend Vector<V, I, S> operator - (const V& a, const Vector<V, I, S>& v);
  21. template <class V, class I, class S>
  22. friend Vector<V, I, S> operator * (const Vector<V, I, S>& v, const V& a); // Multiply every element by v
  23. template <class V, class I, class S>
  24. friend Vector<V, I, S> operator * (const V& a, const Vector<V, I, S>& v);
  25.              ...
  26. }


 
A la compilation j'obtiens les messages d'erreurs du type :
Vector.hpp declaration of `class V'  
Vector.hpp  shadows template parm `class V'  
 
Vector.hpp declaration of `class I'  
Vector.hpp  shadows template parm `class I'  
 
Vector.hpp declaration of `class S'  
Vector.hpp  shadows template parm `class S'  
 
pour chacun des 6 opérateurs (c'est à dire 18 messages d'erreur).
 
En cherchant sur Internet j'ai compris qu'il y a conflit entre le nom de ces classes dans le template des opérateurs et ceux de la première ligne (template <class V, class I=int, class S=FullArray<V> > ). Je crois donc qu'il faudrait renommer les seconds en W, J, T par exemple mais dans ce cas, dois écrire cela :
 

Code :
  1. template <class W, class J, class T>
  2. friend Vector<W, J, T> operator + (const Vector<W, J, T>& v,const V& a); // Add v to every element


 
ou bien cela :
 

Code :
  1. template <class W, class J, class T>
  2. friend Vector<V, I, S> operator + (const Vector<V, I, S>& v,const V& a); // Add v to every element


 
J'avoue ne pas être tout à fait au point avec ces notions. A priori je n'en ai pas besoin, c'est juste dommage que ces classes ne se compilent pas directement...
 
Merci pour votre aide, bonne journée.
 
Jean.

Reply

Marsh Posté le 05-03-2008 à 07:55:15   

Reply

Marsh Posté le 05-03-2008 à 09:16:27    

1ere solution ;)
 
Ah et jettes ton bouquin. Préconisez des fonctions friends pour la surcharge des opérateurs binaires est une connerie sans nom.
 
Tout comme rein venter std::valarray de manière sub-optimale

Reply

Marsh Posté le 05-03-2008 à 09:38:14    

Merci Joel, peux-tu m'expliquer en quoi c'est stupide d'utiliser des fonctions friends dans ce cas ?
 
Pour l'histoire de rein venter std::valarray, je te fais confiance ;)

Reply

Marsh Posté le 05-03-2008 à 11:43:56    

bah c'est stupide dans le sens où tu peux faire sans facilement, en implémentant trivialement par exemple l'opération + comme

Code :
  1. V operator+(const V& a, const V& b)
  2. {
  3.   V sum(a);
  4.   sum += b;
  5.   return sum;
  6. }

Reply

Marsh Posté le 05-03-2008 à 11:45:35    

La pratique que je prône (et je suis pas le seul) est d'utiliser des fonctiosn libres tant que l'on peut. Cela permet de découpler fortement algorithmes et objets et de facto, augmente le niveau d'abstraction. Sutter en parle dans son GotW sur std::string en autre.
 
Plus prosaïquement, dans le cas de la surcharge d'opérateur de type +-/* etc ..., il faut bien noté que l'argument de gauche et l'argument de droite joue un rôle équivalent par rapport au résultat.  
En gros, il y a création d'une nouvelle instance à partir des arguments. Devant ce type de symétrie (à ne pas mélanger avec le fait que les opérateurs soit associatifs ou je en sais plus comment on dit)
on préférera la fonction à la méthode. Reste ensuite : pourquoi une fonction non-friend ?
 
En fait, le friend ne sert que dans des cas limites du langage. Tu peut parfaitement écrire ton operator+ sans aller accéder aux membres privés de ta classe, grâce entre autre aux accesseurs/mutateurs que tu auras bien voulu lui donné.
 
En gros :
-> opérateurs unaires : méthodes ou fonction libres
-> opérateurs binaires : fonction libres
 
J'en rajoute une couche en disant que en général, on donne à ce type de classe un opérateur += qui lui est une méthode, et on construit operator+ à partir de ça et du constructeur de copie.
 

Code :
  1. Vector operator+( const Vector& a, const Vector& b )
  2. {
  3.   Vector r(a);
  4.   r+= b;
  5.   return r;
  6. }

Reply

Marsh Posté le 05-03-2008 à 11:45:50    

Reply

Marsh Posté le 05-03-2008 à 11:46:43    


a 2mn prés :o


Message édité par Joel F le 05-03-2008 à 11:46:53
Reply

Sujets relatifs:

Leave a Replay

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