OVH Cloud OVH Cloud

Pb de Templates

19 réponses
Avatar
Wang Zangkun
Bonjour,
encore un pb de template !

J'ai une classe template Matrice comme ci dessous, avec g++ j'ai à (entre
autre) l'erreur :
../templatematrice.h:24: erreur: int Matrice<int, classPlus<int>,
classFois<int>, 2147483647, 0>::nbCols is private

erreur qui disparait si je mets nbCols en public (mais je ne veux pas).

template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois>
class Matrice {

private:
int nbCols; // nombre de colonnes
vector<T>* mat; // stockage des éléments de la matrice OpPlus plus;
OpFois fois;

public:

/**
* Constructeur
*/
Matrice(int ligs, int cols) {
mat = new vector<T>(cols * ligs, nullPlus); // crée un vecteur de
taille ligs * cols nbCols = cols;
}

...

Les autres erreurs que j'ai, au cas ou ça serait lié :

Building file: ../tp06.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -otp06.o ../tp06.cpp ../tp06.cpp:
In function int main(int, char**): ../tp06.cpp:31: attention : comparaison
entre des expressions entières signée et non signée
../templatematrice.h: In function std::istream& operator>>(std::istream&,
Matrice<T, OpPlus, OpFois, nullPlus, nullFois>&) [with T = int, OpPlus =
classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T
nullFois = 0]: ../tp06.cpp:18: instantiated from here
../templatematrice.h:25: erreur: std::vector<int, std::allocator<int> >*
Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::mat is
private ../templatematrice.h:110: erreur: à lintérieur du contexte
../tp06.cpp:18: instantiated from here ../templatematrice.h:110:
attention : comparaison entre des expressions entières signée et non
signée ../templatematrice.h:24: erreur: int Matrice<int, classPlus<int>,
classFois<int>, 2147483647, 0>::nbCols is private
../templatematrice.h:111: erreur: à lintérieur du contexte
../templatematrice.h: In function std::ostream& operator<<(std::ostream&,
Matrice<T, OpPlus, OpFois, nullPlus, nullFois>&) [with T = int, OpPlus =
classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T
nullFois = 0]: ../tp06.cpp:19: instantiated from here
../templatematrice.h:25: erreur: std::vector<int, std::allocator<int> >*
Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::mat is
private ../templatematrice.h:128: erreur: à lintérieur du contexte
../templatematrice.h:24: erreur: int Matrice<int, classPlus<int>,
classFois<int>, 2147483647, 0>::nbCols is private
../templatematrice.h:129: erreur: à lintérieur du contexte
../templatematrice.h: In member function void Matrice<T, OpPlus,
OpFois, nullPlus, nullFois>::init(int) [with T = int, OpPlus =
classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T
nullFois = 0]: ../tp06.cpp:22: instantiated from here
../templatematrice.h:48: erreur: no match for operator= in
*(((Matrice<int, classPlus<int>, classFois<int>, 2147483647,
0>*)this)->Matrice<int, classPlus<int>, classFois<int>, 2147483647,
0>::mat + (+(i * 12u))) = ini
/usr/include/c++/4.0.2/bits/vector.tcc:133: note: candidats sont:
std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const
std::vector<_Tp, _Alloc>&) [with _Tp = int, _Alloc = std::allocator<int>]
../templatematrice.h: In member function Matrice<T, OpPlus, OpFois,
nullPlus, nullFois> Matrice<T, OpPlus, OpFois, nullPlus,
nullFois>::operator*(Matrice<T, OpPlus, OpFois, nullPlus, nullFois>) [with
T = int, OpPlus = classPlus<int>, OpFois = classFois<int>, T nullPlus =
2147483647, T nullFois = 0]: ../tp06.cpp:34: instantiated from here
../templatematrice.h:95: erreur: request for member at in
this, which is of non-class type Matrice<int, classPlus<int>,
classFois<int>, 2147483647, 0>* const ../templatematrice.h: In member
function T& Matrice<T, OpPlus, OpFois, nullPlus, nullFois>::at(int,
int) [with T = int, OpPlus = classPlus<int>, OpFois = classFois<int>, T
nullPlus = 2147483647, T nullFois = 0]: ../templatematrice.h:116:
instantiated from std::istream& operator>>(std::istream&, Matrice<T,
OpPlus, OpFois, nullPlus, nullFois>&) [with T = int, OpPlus =
classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T
nullFois = 0] ../tp06.cpp:18: instantiated from here
../templatematrice.h:62: erreur: invalid initialization of reference of
type int& from expression of type std::vector<int,
std::allocator<int> > make: *** [tp06.o] Erreur 1
make: La cible « all » na pas pu être refabriquée à cause derreurs.
Build complete for project tp06


Merci pour vos réponses !

10 réponses

1 2
Avatar
Fabien LE LEZ
On Thu, 01 Dec 2005 14:28:18 +0100, Wang Zangkun
:

Matrice(int ligs, int cols) {
mat = new vector<T>(cols * ligs, nullPlus); // crée un vecteur de
taille ligs * cols nbCols = cols;


Le code ci-dessus a plusieurs problèmes :

Le commentaire est sur deux lignes. Pour un tel commentaires, il
faut utiliser la syntaxe /* ... */

Un "vector<>" est un tableau, pas un vecteur. Un vecteur est un
objet mathématique, représentable par un tableau de taille fixe, avec
un certain nombre d'opérations (addition, produit scalaire, etc.).

Un commentaire qui se contente de paraphraser le code (de façon
peu lisible en plus) me paraît parfaitement inutile.

Pourquoi diable utilises-tu un "new vector<>" ? Ça t'oblige à te
taper tout le boulot qui devrait être automatique, dans le
constructeur de copie, l'opérateur de copie, le destructeur, et j'en
oublie peut-être.

Voici ce que j'écrirais (en modifiant le moins possible de code -- si
je me mets à tout modifier on n'a pas fini) :

private:
...
vector<T> mat; // stockage des éléments de la matrice OpPlus
plus;
...

public:

/**
* Constructeur
*/
Matrice(int ligs, int cols)
: mat (cols * ligs, nullPlus)
// , nbCols = cols; /* J'ai respecté le commentaire -- je
ne sais pas si c'est du code ou pas. */
{
}

Avatar
Wang Zangkun
Le Thu, 01 Dec 2005 14:53:53 +0100, Fabien LE LEZ a écrit :

On Thu, 01 Dec 2005 14:28:18 +0100, Wang Zangkun
:

Matrice(int ligs, int cols) {
mat = new vector<T>(cols * ligs, nullPlus); // crée un vecteur de
taille ligs * cols nbCols = cols;


Le code ci-dessus a plusieurs problèmes :

Le commentaire est sur deux lignes. Pour un tel commentaires, il
faut utiliser la syntaxe /* ... */


En fait non, c'est en recopiant dans la fenêtre d'édition de message
que mon logiciel a fait une nouvelle ligne.
il fallait lire :
mat = new vector<T>(cols * ligs, nullPlus);
suivi du commentaire


Un "vector<>" est un tableau, pas un vecteur. Un vecteur est un
objet mathématique, représentable par un tableau de taille fixe, avec
un certain nombre d'opérations (addition, produit scalaire, etc.).

Un commentaire qui se contente de paraphraser le code (de façon
peu lisible en plus) me paraît parfaitement inutile.


Merci, mais j'ai envie de manipuler des vecteurs dans mon programme et
j'ai choisis de les représenter avec la classe vector. D'ou le
commentaire, qui n'est pas totalement inutile puisqu'il précise que
l'objet vector mat représentera un vecteur (ou une matrice).


Pourquoi diable utilises-tu un "new vector<>" ? Ça t'oblige à te
taper tout le boulot qui devrait être automatique, dans le
constructeur de copie, l'opérateur de copie, le destructeur, et j'en
oublie peut-être.


J'ai fait le choix de stocker mon vector dans le tas. C'est peut etre un
mauvais choix, mais ça n'est pas la cause de mon erreur (je ne crois pas)


Voici ce que j'écrirais (en modifiant le moins possible de code -- si
je me mets à tout modifier on n'a pas fini) :

private:
...
vector<T> mat; // stockage des éléments de la matrice OpPlus
plus;
...

public:

/**
* Constructeur
*/
Matrice(int ligs, int cols)
: mat (cols * ligs, nullPlus)
// , nbCols = cols; /* J'ai respecté le commentaire -- je
ne sais pas si c'est du code ou pas. */
{
}


Merci tout de même pour cette réponse, mais ça ne résout pas mon
problème ...


Avatar
Fabien LE LEZ
On Thu, 01 Dec 2005 15:19:22 +0100, Wang Zangkun
:

mais j'ai envie de manipuler des vecteurs dans mon programme et
j'ai choisis de les représenter avec la classe vector.


Y'a une couille quelque part, alors. Une matrice 4*3 qui contient un
vecteur de dimension 12, mathématiquement, ça ne colle pas.

D'ou le
commentaire, qui n'est pas totalement inutile puisqu'il précise que
l'objet vector mat représentera un vecteur (ou une matrice).


Mieux vaut alors mettre le commentaire à l'endroit où tu déclares la
variable membre.

J'ai fait le choix de stocker mon vector dans le tas.


Dans ce cas, je ne saurais trop te conseiller d'isoler le vector<>
dans une classe à part.

Note par ailleurs qu'un vector<> ne "consomme" que quelques octets
dans la pile, puisqu'il stocke les données dans le tas.

Avatar
Wang Zangkun
Le Thu, 01 Dec 2005 15:28:33 +0100, Fabien LE LEZ a écrit :

On Thu, 01 Dec 2005 15:19:22 +0100, Wang Zangkun
:

mais j'ai envie de manipuler des vecteurs dans mon programme et
j'ai choisis de les représenter avec la classe vector.


Y'a une couille quelque part, alors. Une matrice 4*3 qui contient un
vecteur de dimension 12, mathématiquement, ça ne colle pas.


Une matrice 4*3 contient 12 éléments, d'ou le vector de 12 éléments.
Ensuite, quand je veux accéder à l'élement [2,1] de la matrice, je
vais chercher l'élement 2 * 3 + 1 (3 étant le nombre de colonnes).

C'est une des façons de représenter les tableaux à 2d en assembleur.

Encore une fois, le vector n'est qu'une représentation interne de la
matrice. Pour l'utilisateur, ça se comporte comme une matrice, quel que
soit la représentation interne.


D'ou le
commentaire, qui n'est pas totalement inutile puisqu'il précise que
l'objet vector mat représentera un vecteur (ou une matrice).


Mieux vaut alors mettre le commentaire à l'endroit où tu déclares la
variable membre.

J'ai fait le choix de stocker mon vector dans le tas.


Dans ce cas, je ne saurais trop te conseiller d'isoler le vector<>
dans une classe à part.


Pourquoi ?


Note par ailleurs qu'un vector<> ne "consomme" que quelques octets
dans la pile, puisqu'il stocke les données dans le tas.


C'est vrai, mais il faut penser au passage à l'échelle supérieure.
Mais c'est vrai que dans mon cas je pouvais utiliser la pile.

Sinon j'arrive à compiler en mettant nbCols et mat en public. Mais c'est
pas bien !
Il y a quand meme un warning super explicite de g++ :
../templatematrice.h:24: attention : int Matrice<int, classPlus<int>,
classFois<int>, 2147483647, 0>::nbCols
Hum. Ca aide pas beaucoup.


Avatar
Fabien LE LEZ
On Thu, 01 Dec 2005 16:31:35 +0100, Wang Zangkun
:

Une matrice 4*3 contient 12 éléments, d'ou le vector de 12 éléments.
Ensuite, quand je veux accéder à l'élement [2,1] de la matrice, je
vais chercher l'élement 2 * 3 + 1 (3 étant le nombre de colonnes).

C'est une des façons de représenter les tableaux à 2d en assembleur.


Oui. Mais ce n'est alors plus du tout un vecteur.

Dans ce cas, je ne saurais trop te conseiller d'isoler le vector<>
dans une classe à part.


Pourquoi ?


Parce que gérer un objet alloué dynamiquement est une responsabilité
assez complexe ; il vaut mieux l'isoler pour qu'elle n'interfère pas
avec le reste du code.

Note que la "classe à part" peut très bien être un pointeur
intelligent.

Note par ailleurs qu'un vector<> ne "consomme" que quelques octets
dans la pile, puisqu'il stocke les données dans le tas.


C'est vrai, mais il faut penser au passage à l'échelle supérieure.


Quel "passage à l'échelle supérieure" ?

Sinon j'arrive à compiler en mettant nbCols et mat en public. Mais c'est
pas bien !


Donne un bout de code minimal et compilable, sans les commentaires en
vrac.


Avatar
Matthieu Moy
Wang Zangkun writes:

Il y a quand meme un warning super explicite de g++ :
../templatematrice.h:24: attention : int Matrice<int, classPlus<int>,
classFois<int>, 2147483647, 0>::nbCols


Je serai bien surpris que ce soit la totalité du message d'erreur. Il
n'est pas découpé en plusieurs lignes ?

--
Matthieu

Avatar
Wang Zangkun
Donc voici le bout de code :
(le reste n'est pas nécessaire, et trop long)

Si je laisse private, ça compile pas (voir les messages d'erreurs ci
dessous), et si je met en public (ce que je ne désire pas), ça compile.
J'ai aussi mis les warnings affichés quand ça compile.

------------------------
Le code :

template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois>
class Matrice {

private:
int nbCols; // nombre de colonnes
vector<T> mat; // stockage des éléments de la matrice
OpPlus plus;
OpFois fois;

------------------------
Avec private :

../templatematrice.h: In constructor Matrice<T, OpPlus, OpFois, nullPlus, nullFois>::Matrice(int, int) [with T = int, OpPlus = classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T nullFois = 0]:
../tp06.cpp:19: instantiated from here
../templatematrice.h:25: attention : Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::mat will be initialized after
../templatematrice.h:24: attention : int Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::nbCols
../templatematrice.h:34: attention : when initialized here
../templatematrice.h: In function std::ostream& operator<<(std::ostream&, Matrice<T, OpPlus, OpFois, nullPlus, nullFois>&) [with T = int, OpPlus = classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T nullFois = 0]:
../tp06.cpp:22: instantiated from here
../templatematrice.h:25: erreur: std::vector<int, std::allocator<int> > Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::mat is private
../templatematrice.h:135: erreur: à l'intérieur du contexte
../tp06.cpp:22: instantiated from here
../templatematrice.h:24: erreur: int Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::nbCols is private
../templatematrice.h:136: erreur: à l'intérieur du contexte
../templatematrice.h: In function std::istream& operator>>(std::istream&, Matrice<T, OpPlus, OpFois, nullPlus, nullFois>&) [with T = int, OpPlus = classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T nullFois = 0]:
../tp06.cpp:23: instantiated from here
../templatematrice.h:24: erreur: int Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::nbCols is private
../templatematrice.h:115: erreur: à l'intérieur du contexte
../templatematrice.h:24: erreur: int Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::nbCols is private
../templatematrice.h:115: erreur: à l'intérieur du contexte
../templatematrice.h:25: erreur: std::vector<int, std::allocator<int> > Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::mat is private
../templatematrice.h:117: erreur: à l'intérieur du contexte
../templatematrice.h:24: erreur: int Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::nbCols is private
../templatematrice.h:118: erreur: à l'intérieur du contexte
make: *** [tp06.o] Erreur 1
make: La cible « all » n'a pas pu être refabriquée à cause d'erreurs.
Build complete for project tp06

------------------------
Avec public

make -k all
Building file: ../tp06.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -otp06.o ../tp06.cpp
../templatematrice.h: In constructor Matrice<T, OpPlus, OpFois, nullPlus, nullFois>::Matrice(int, int) [with T = int, OpPlus = classPlus<int>, OpFois = classFois<int>, T nullPlus = 2147483647, T nullFois = 0]:
../tp06.cpp:19: instantiated from here
../templatematrice.h:25: attention : Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::mat will be initialized after
../templatematrice.h:24: attention : int Matrice<int, classPlus<int>, classFois<int>, 2147483647, 0>::nbCols
../templatematrice.h:34: attention : when initialized here
Finished building: ../tp06.cpp

Building target: tp06
Invoking: GCC C++ Linker
g++ -otp06 ./tp06.o
Finished building target: tp06

Build complete for project tp06

-------------

C'est assez bizarre, non ?
Avatar
Vincent Lascaux
"Wang Zangkun" a écrit dans le message de news:

Donc voici le bout de code :
(le reste n'est pas nécessaire, et trop long)

Si je laisse private, ça compile pas (voir les messages d'erreurs ci
dessous), et si je met en public (ce que je ne désire pas), ça compile.
J'ai aussi mis les warnings affichés quand ça compile.

------------------------
Le code :

template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois>
class Matrice {

private:
int nbCols; // nombre de colonnes
vector<T> mat; // stockage des éléments de la matrice
OpPlus plus;
OpFois fois;

------------------------


Facile : il n'y a pas autant de { que de } et tu vas avoir une erreur au
linkage car il manque le main...

--
Vincent

Avatar
Wang Zangkun
Le Thu, 01 Dec 2005 09:10:51 -0800, Vincent Lascaux a écrit :


"Wang Zangkun" a écrit dans le message de news:

Donc voici le bout de code :
(le reste n'est pas nécessaire, et trop long)

Si je laisse private, ça compile pas (voir les messages d'erreurs ci
dessous), et si je met en public (ce que je ne désire pas), ça compile.
J'ai aussi mis les warnings affichés quand ça compile.

------------------------
Le code :

template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois>
class Matrice {

private:
int nbCols; // nombre de colonnes
vector<T> mat; // stockage des éléments de la matrice
OpPlus plus;
OpFois fois;

------------------------


Facile : il n'y a pas autant de { que de } et tu vas avoir une erreur au
linkage car il manque le main...


Hum, j'ai juste mis un extrait de code, c'est pour ça. Et le main n'est
pas là non plus, du coup.

J'arrive à compiler et à exécuter mon programme (comme c'est écrit
dans le message auquel tu as répondu).
Y'a meme le résultat de make, qui
dans un cas dit qu'il compile pas, et dans l'autre, il compile et crée un
exécutable.

Je me demande d'ailleurs si tu n'est pas un petit plaisantin.


Avatar
Fabien LE LEZ
On Thu, 01 Dec 2005 20:33:48 +0100, Wang Zangkun
:

J'arrive à compiler et à exécuter mon programme


Enlève dans ton programme tout ce qui ne concerne pas directement le
problème, de façon à obtenir un programme minimal mais compilable, qui
illustre le problème.

1 2