OVH Cloud OVH Cloud

Surcharge d'opérateurs dans une classe template

3 réponses
Avatar
Arnaud Debaene
Bonjour à tous.

J'ai un petit souçi avec une classe template qui surcharge certains
opérateurs sous formes de fonctions friends et d'autres en fonctions
membres. Voilà un exemple qui reproduit le problème :

//Prédéclaration de la classe et de l'opérateur friend template
template <typename T> class complexe;
template <typename T> complexe<T> operator- (const complexe<T>& lhs, const
complexe<T>& rhs);

template <typename T> class complexe
{
public:
complexe(T real, T imaginary);
complexe<T> operator-() const; //operateur + unaire
friend complexe<T> operator <T> (const complexe<T>& lhs, const
complexe<T>& rhs);

private:
T m_real;
T m_imaginary;
};

/***Implementation ***/
template <typename T> complexe<T>::complexe (T real, T imaginary)
: m_real(real), m_imaginary(imaginary)
{}

template <typename T> complexe<T> complexe<T>::operator-() const
{
complexe<T> retval (-m_real, -m_imaginary);
return retval;
}


template <typename T> complexe<T> operator- (const complexe<T>& lhs, const
complexe<T>& rhs)
{
complexe<T> retval (lhs.m_real-rhs.m_real,
lhs.m_imaginary-rhs.m_imaginary);
return retval;
}

Aussi bien Comeau online que VC 7.1 refusent de compiler cet exemple et
semblent se mélanger les pinceaux entre les opérateurs + unaire et binaire.
Le plus étonnant c'est que, avec les deux compilateurs, si dans la
déclaration de la classe je déclare l'opérateur unaire membre après
l'opérateur binaire friend, la compilation réussit :

template <typename T> class complexe
{
public:
complexe(T real, T imaginary);
friend complexe<T> operator- <T> (const complexe<T>& lhs, const
complexe<T>& rhs);
complexe<T> operator-() const; //ok si ceci est arpès l'opérateur
friend binaire

private:
T m_real;
T m_imaginary;
};

/***Implementation idem que l'exemple précédent***/

Quelqu'un comprend ce qui se passe? Merci d'avance.

Arnaud

3 réponses

Avatar
Arnaud Debaene
Je repostes mon code car quelques erreurs s'y étaient glissées (voilà ce qui
arrive quand on poste à de sheures pas possibles...)

J'ai un petit souçi avec une classe template qui surcharge certains
opérateurs sous formes de fonctions friends et d'autres en fonctions
membres. Voilà un exemple qui reproduit le problème :

//Prédéclaration de la classe et de l'opérateur friend template
template <typename T> class complexe;
template <typename T> complexe<T> operator- (const complexe<T>& lhs, const
complexe<T>& rhs);

template <typename T> class complexe
{
public:
complexe(T real, T imaginary);
complexe<T> operator-() const; //operateur - unaire
friend complexe<T> operator- <T> (const complexe<T>& lhs, const
complexe<T>& rhs);

private:
T m_real;
T m_imaginary;
};

/***Implementation ***/
template <typename T> complexe<T>::complexe (T real, T imaginary)
: m_real(real), m_imaginary(imaginary)
{}

template <typename T> complexe<T> complexe<T>::operator-() const
{
complexe<T> retval (-m_real, -m_imaginary);
return retval;
}


template <typename T> complexe<T> operator- (const complexe<T>& lhs, const
complexe<T>& rhs)
{
complexe<T> retval (lhs.m_real-rhs.m_real,
lhs.m_imaginary-rhs.m_imaginary);
return retval;
}

Aussi bien Comeau online que VC 7.1 refusent de compiler cet exemple et
semblent se mélanger les pinceaux entre les opérateurs - unaire et binaire.
Le plus étonnant c'est que, avec les deux compilateurs, si dans la
déclaration de la classe je déclare l'opérateur unaire membre après
l'opérateur binaire friend, la compilation réussit :

template <typename T> class complexe
{
public:
complexe(T real, T imaginary);
friend complexe<T> operator- <T> (const complexe<T>& lhs, const
complexe<T>& rhs);
complexe<T> operator-() const; //ok si ceci est arpès l'opérateur
friend binaire

private:
T m_real;
T m_imaginary;
};

/**Implementation idem que l'exemple précédent**/

Quelqu'un comprend ce qui se passe? Merci d'avance.

Arnaud
Avatar
Jean-Marc Bourguet
"Arnaud Debaene" writes:

Aussi bien Comeau online que VC 7.1 refusent de compiler cet exemple
et semblent se mélanger les pinceaux entre les opérateurs - unaire
et binaire. Le plus étonnant c'est que, avec les deux compilateurs,
si dans la déclaration de la classe je déclare l'opérateur unaire
membre après l'opérateur binaire friend, la compilation réussit :


Ton code passe avec Sun CC, HP aCC et g++ 3.3. Aucune idee quant a
qui a raison.

Est-ce que le probleme existe aussi sans les templates (si c'est un
probleme de recherche de nom, il y a des chances que ce soit le cas).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Arnaud Debaene
Jean-Marc Bourguet wrote:
"Arnaud Debaene" writes:

Aussi bien Comeau online que VC 7.1 refusent de compiler cet exemple
et semblent se mélanger les pinceaux entre les opérateurs - unaire
et binaire. Le plus étonnant c'est que, avec les deux compilateurs,
si dans la déclaration de la classe je déclare l'opérateur unaire
membre après l'opérateur binaire friend, la compilation réussit :


Ton code passe avec Sun CC, HP aCC et g++ 3.3. Aucune idee quant a
qui a raison.

Est-ce que le probleme existe aussi sans les templates (si c'est un
probleme de recherche de nom, il y a des chances que ce soit le cas).


Merci, j'ai trouvé ma réponse sur microsoft.public.vc.language (voire
http://www.google.fr/groups?hl=fr&lr=&ie=UTF-8&oe=UTF-8&threadm=O4pksAPxDHA.556%40TK2MSFTNGP11.phx.gbl&rnum=1&prev=/groups%3Fie%3DUTF-8%26oe%3DUTF-8%26as_umsgid%3DO4pksAPxDHA.556%40TK2MSFTNGP11.phx.gbl%26lr%3D%26hl%3Dfr).

En résumé, VC et Comeau ont raison et c'est effectivement un problème de
recherche de nom indépendant des templates : la déclaration de l'opérateur
unaire masque la déclaration de l'opérateur binaire dans le namespace
englobant (namespace global), ce qui fait que la déclaration du friend fait
référence à l'opérateur unaire, mais évidemment avec la mauvaise signature.

La solution consiste à déclarer le friend en spécifiant le namespace global
(ce qui oblige à des parenthèses supplémentaires, comme indiqué ci-dessous)
:

//Prédéclaration de la classe et de l'opérateur friend template
template <typename T> class complexe;
template <typename T> complexe<T> operator- (const complexe<T>& lhs, const
complexe<T>& rhs);

template <typename T> class complexe
{
public:
complexe(T real, T imaginary);
complexe<T> operator-() const; //operateur - unaire
friend complexe<T> (::operator- <T> (const complexe<T>& lhs, const
complexe<T>& rhs));

private:
T m_real;
T m_imaginary;
};


Arnaud