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 !

9 réponses

1 2
Avatar
Franck Branjonneau
Wang Zangkun écrivait:

Bonjour,


Salut,

Where ?

../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


in function std::istream& operator>>(std::istream&, [...]

What ?

../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


*Erreur* : [...] Matrice<int, classPlus<int>, classFois<int>,
2147483647, 0>::mat is private [...]

Merci pour vos réponses !


*Lis* les messages d'erreurs.

--
Franck

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


C'est ptet pour éviter ce cas de figure que Fabien a demandé "Donne un bout
de code minimal et compilable, sans les commentaires en vrac".
Si tu donnes un code complet qui reproduit l'erreur alors on pourra donner
des raisons exactes. En attendant, on ne peut que speculer que tu n'as pas
déclaré l'operateur >> comme friend, ou quelque chose du genre.

--
Vincent

Avatar
kanze
Wang Zangkun wrote:
"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,


Justement. Tu n'as pas mis le bout qui provoque l'erreur. Ou au
moins pas tout. C'est assez facile de compléter ton code pour
qu'il n'y a pas d'erreur. Il faut croire que tu l'as complété
autrement, mais comment ?

S'il y a une erreur de compilateur, on n'a pas forcément besoin
du main, mais on a quand même besoin d'un bout complet, qu'on
peut essayer de compiler soi-même (pour en voir l'erreur).

De même, poster les messages d'erreur, avec les numéros de
ligne, ne sert à rien si on ne peut pas faire l'association
entre le numéro de ligne dans le message d'erreur et le code
posté. Une solution consiste à marquer la ligne en question avec
un commentaire, du genre « // <== c'est ici que ça coince »)

Par exemple, dans tes messages d'erreur, je vois :

../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

(J'ai réformatté pour éviter les problèmes de réformattage
automatique.)

Alors, c'est difficile à suivre ce qui se passe. Les numéros de
lignes ici vont de 25 à 110 dans le fichier templatematrix.h. Tu
n'en as pas posté autant (heureusement). Il y a mention aussi
d'une fonction operator>> que je ne vois pas dans le code que tu
as présenté.

Les trois premières lignes ci-dessus semblent dire que tu as
accédé à Matrice<>::mat dans la fonction globale operator>>,
sans qu'elle soit friend. Mais je ne vois pas de fonction
globale operator>> dans ton code. Alors, qu'est-ce que je dois
conclure ? À part que tu n'as pas posté un extrait suffisamment
pour qu'on puisse commencer à la récherche du problème.

Comme a dit Fabien (ou quelqu'un d'autre) : crée le plus petit
bout du code qui se compile et qui manifeste l'erreur, et le
poster. Et alors, on verra.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
Wang Zangkun
Ok, donc j'ai fait un fichier test.cc en reduisant le code (mais c deja
long).

En fait, ça m'a permet de voir d'ou venait le problème : il vient de la
fonction amie operator>>. Si je commente le code (comme c'est fait
actuellement) pas de pb, ça compile. Si je décommente, ça compile plus.
(messages d'erreurs à la fin).

----

#include <iostream>
#include <vector>

using namespace std;

template <class T> class classFois;
template <class T> class classPlus;
template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois> class Matrice;

/**
* Classe générique matrice d'objets T
* T type des objets de la matrice
*
*/
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 (cols * ligs, nullPlus), nbCols(cols) {
}

/**
* Destructeur
*/
~Matrice() {
}

template <T, OpPlus, OpFois, T, T> friend ostream& operator<< (ostream& os, Matrice<T, OpPlus, OpFois, nullPlus, nullFois>& mat);
};

template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois>
istream& operator>>(istream& is,
Matrice<T, OpPlus, OpFois, nullPlus, nullFois>& m) {
/* ICI QUAND JE DECOMMENTE, J'AI DES ERREURS ***************************
int lig = 0;

for (unsigned int i = 0; i < m.mat.size(); i++) {
if (i % m.nbCols == 0) {
lig++;
}
is >> m.at(lig - 1, i);
}
*/
return is;
}

// Objets fonctions

template <class T> class classFois {
public:
T operator()(const T& op1, const T& op2) {
return (op1 + op2);
}
};

template <class T> class classPlus {
public:
T operator()(const T& op1, const T& op2) {
return (op1 < op2) ? op1 : op2; // min op1, op2
}
};

// Programme principal

int main(int argc, char* argv[])
{
const unsigned dim = 4;
Matrice<int, classPlus<int>, classFois<int>, INT_MAX, 0> M(dim,dim);
cin >> M;

return 0;
}

-----

Et quand je décommente :
test.cc: 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]": test.cc:80: instantiated from here
test.cc:20: erreur: "std::vector<int, std::allocator<int> > Matrice<int,
classPlus<int>, classFois<int>, 2147483647, 0>::mat" is private
test.cc:48: erreur: à l'intérieur du contexte test.cc:80: instantiated
from here
test.cc:19: erreur: "int Matrice<int, classPlus<int>, classFois<int>,
2147483647, 0>::nbCols" is private test.cc:49: erreur: à l'intérieur du
contexte test.cc:52: erreur: "class Matrice<int, classPlus<int>,
classFois<int>, 2147483647, 0>" has no member named "at"

(ça produit un exécutable avec le code commenté, et aucun warning ni
erreur)

C'est bizarre que ça induise notamment l'erreur "nbCols is private."
Avatar
bof
Wang Zangkun wrote:
Ok, donc j'ai fait un fichier test.cc en reduisant le code (mais c deja
long).

En fait, ça m'a permet de voir d'ou venait le problème : il vient de la
fonction amie operator>>. Si je commente le code (comme c'est fait
actuellement) pas de pb, ça compile. Si je décommente, ça compile plus.
(messages d'erreurs à la fin).


Ou l'operateur>> est-il declare comme un ami?

Avatar
Fabien LE LEZ
On Fri, 02 Dec 2005 14:31:08 +0100, Wang Zangkun
:

template <T, OpPlus, OpFois, T, T> friend ostream& operator<< (ostream& os, Matrice<T, OpPlus, OpFois, nullPlus, nullFois>& mat);


Tu déclares un opérateur << ami...

template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois>
istream& operator>>(istream& is,


... donc operator >> n'a aucune raison de pouvoir accéder aux membres
privés.

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

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


Depuis le début de ce thread, ta kirielle de paramètres templates me
chiffonne.

Généralement, pour faire ce genre de chose, on utilise des traits.

template <class T> struct OperationsParDefaut
{
static T Addition (T const& a, T const& b) { return a+b; }
static T ElementNeutreAddition() { return T(); }
// et idem pour la multiplication
};

Si les valeurs ne conviennent pas, tu peux faire une spécialisation.

Ensuite, tu définis ta classe Matrice comme suit :

template <class T, class Traits= OperationsParDefaut<T> >
class Matrice
{
public:
Matrice operator+= (Matrice const& autre)
{
(pour chaque élément)
element[i]= Traits::Addition (element[i], autre.element[i]);
}
};


Ainsi, pour déclarer une matrice de flottants avec des paramètres
normaux (opérateurs + et * classiques, éléments neutres 1 et 0), tu
déclares simplement :

Matrice<double> m;

Et si tu veux une addition un peu bizarre, tu crées une classe "trait"
différente :

struct TraitBizarre
{
static T Addition (T const& a, T const& b)
{ return UneFonctionBizarre (a,b); }
//etc.
};

et tu déclares alors ta matrice comme suit :

Matrice <double, TraitBizarre> m2;

Avatar
Wang Zangkun
Décidément je fais pleins d'erreur. En fait je me suis trompé, j'ai
corrigé, et du coup la fonction operator>> est bien déclarée en friend,
et définie ensuite.
Mais le meme problème subsiste
------

#include <iostream>
#include <vector>

using namespace std;

template <class T> class classFois;
template <class T> class classPlus;
template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois> class Matrice;

/**
* Classe générique matrice d'objets T
* T type des objets de la matrice
*
*/
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 (cols * ligs, nullPlus), nbCols(cols) {
}

/**
* Destructeur
*/
~Matrice() {
}
// operator<<
template <T, OpPlus, OpFois, T, T> friend ostream& operator<< (ostream& os, Matrice<T, OpPlus, OpFois, nullPlus, nullFois>& mat);
};
// operator<< ! (c pareil maintenant)
template <class T, class OpPlus, class OpFois, T nullPlus, T nullFois>
ostream& operator<<(ostream& os,
Matrice<T, OpPlus, OpFois, nullPlus, nullFois>& m) {

int lig = 0;

for (unsigned int i = 0; i < m.mat.size(); i++) {
if (i % m.nbCols == 0) {
os << endl;
lig++;
}

os << m.at(lig - 1, i) << " ";
}

cout << endl;

return os;
}

// Objets fonctions

template <class T> class classFois {
public:
T operator()(const T& op1, const T& op2) {
return (op1 + op2);
}
};

template <class T> class classPlus {
public:
T operator()(const T& op1, const T& op2) {
return (op1 < op2) ? op1 : op2; // min op1, op2
}
};

// Programme principal

int main(int argc, char* argv[])
{
const unsigned dim = 4;
Matrice<int, classPlus<int>, classFois<int>, INT_MAX, 0> M(dim,dim);
cout << M;

return 0;
}
Avatar
James Kanze
Wang Zangkun wrote:
Ok, donc j'ai fait un fichier test.cc en reduisant le code
(mais c deja long).


En fait, ça m'a permet de voir d'ou venait le problème : il
vient de la fonction amie operator>>. Si je commente le code
(comme c'est fait actuellement) pas de pb, ça compile. Si je
décommente, ça compile plus. (messages d'erreurs à la fin).


----


#include <iostream>
#include <vector>


using namespace std;

template <class T> class classFois;
template <class T> class classPlus;
template <class T, class OpPlus, class OpFois, T nullPlus, T
nullFois> class Matrice;


/**
* Classe générique matrice d'objets T
* T type des objets de la matrice
*
*/
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 (cols * ligs, nullPlus), nbCols(cols) {
}


/**
* Destructeur
*/
~Matrice() {
}


template <T, OpPlus, OpFois, T, T> friend ostream& operator<<
(ostream& os, Matrice<T, OpPlus, OpFois, nullPlus, nullFois>& mat);


Attention : je ne suis pas sûr ce que ça veut dire pour un
template d'être ami. (Autrefois, je crois que c'était interdit
même, puisque ça donne l'amitié à un ensemble illimité de
fonctions, et une une spécialisation permettait à n'importe quel
code d'accéder à n'importe quoi.)

Ce que tu veux, c'est que la fonction (non-template):

ostream& operator<<( ostream& dest, Matrice< T, OpPlus, OpFois,
nullPlus, nullFois>& mat ) ;

soit l'ami. (Note bien qu'elle n'est pas un template.) Ensuite,
évidemment, le problème c'est de le générer pour chaque instance
de la classe. La solution la plus simple (que je connais, en
tout cas), c'est de la définir directement ici :

ostream& operator<<( ostream& dest, Matrice< T, OpPlus, OpFois,
nullPlus, nullFois>& mat )
{
return mat.print( dest ) ;
}

Avec une fonction membre print qui convient. Et alors,
évidemment, elle n'a plus besoin d'être ami ; tu peux donc la
définir comme template en dehors de la classe.

C'est ce que je ferais, de toute façon.

};


--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

1 2