Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Template, conversion implicite, fonction amie

3 réponses
Avatar
marc.boyer.news
Bnojour à tous,

je reprenais un code qui fonctionnait avec un vieux gcc, et ne
fonctionne plus.

L'idée: soit une classe template Num<T> qui offre une convertion
implicite de T -> Num<T>, et qui offre une fonction membre operator+=.

J'aimerais batir une fonction operator+ qui se base sur operator+=
mais accepte les conversions implices (qu'on puisse faire T + Num<T>
ou Num<T> + T ).

Quand j'ai demandé comme faire, il y a longtemps, on m'a expliqué
qu'il n'y
avait pas de conversion implicite vers les fonctions templates, mais
qu'on
pouvait faire une fonction amie d'une classe template.

template <class T>
class Num {
Num<T>(const T){...}:
const Num<T>& operator+=(const Num<T>& incr){...}
friend Num<T> operator+(const Num<T>& l, const Num<T>& r);
};

Tout va bien (et gcc me préviens que je fais une fonction amie non
template),
jusqu'à ce que je doive définir la dite fonction.

J'écris
template <class T>
inline Num<T> operator+(const Num<T>& l, const Num<T>& r){
Num<T> tmp(l);
return tmp+= r;
}

Cela compile, mais au moment de l'édition de lien, il se plaind d'une
undefined reference to operator+(Num<int>const &, Num<int>const &);

J'ai relu mon TC++PL, mais je n'ai pas su y trouver quoi que ce soit
qui m'aide là.

Merci d'avance,
Marc Boyer

3 réponses

Avatar
Laurent
Est ce que tu as essayé de définir l'operateur + avec le prototype (const
Num<T>& l, const Num<T>& r) directement à la suite de sa déclaration dans la
classe. J'avais eu un problème dans ce genre mais je ne suis pas sûr que ce
soit le même car je crois que ça bloquait plutôt à la compilation.
Avatar
Bertrand Motuelle
del yahoo wrote:

template <class T>
class Num {
Num<T>(const T){...}:
const Num<T>& operator+=(const Num<T>& incr){...}
friend Num<T> operator+(const Num<T>& l, const Num<T>& r);
};

Tout va bien (et gcc me préviens que je fais une fonction amie non
template),


La partie importante est le *non template*.

jusqu'à ce que je doive définir la dite fonction.

J'écris
template <class T>
inline Num<T> operator+(const Num<T>& l, const Num<T>& r){
Num<T> tmp(l);
return tmp+= r;
}


Et là tu déclares et définis une fonction *template* (i.e.
différente de la famille de fonctions *non template* amies déclarées
précedemment).

Cela compile, mais au moment de l'édition de lien, il se plaind
d'une

undefined reference to operator+(Num<int>const &, Num<int>const &);


Lors de la résolution de surcharge, la fonction amie *non* template
est préférée à la fonction template. Mais tu ne lui as pas fourni
de définition donc tu obtiens une erreur lors de l'édition de liens.

Si tu définis (la fonction non template utilisée):
inline Num<int> operator+(const Num<int>& l, const Num<int>& r)
{
...
}
tout devrait compiler et lier (mais ce n'est pas, heu, très général)


Pour faire ce que recherches:
template<class T> class Num;

template<class T> Num<T> operator+(const Num<T>&, const Num<T>&);

template <class T>
class Num
{
Num<T>(const T){...}:
const Num<T>& operator+=(const Num<T>& incr){...}
friend Num<T> operator+ <>(const Num<T>& l, const Num<T>& r);
};

Le <>, sur la ligne du friend, permet de déclarer amie une
spécialisation de la fonction template.

Et ensuite implémente la fonction...
template <class T>
inline Num<T> operator+(const Num<T>& l, const Num<T>& r)
{
Num<T> tmp(l);
return tmp+= r;
}

a+
Bertrand.

Avatar
marc.boyer.news
"Bertrand Motuelle" wrote in message news:...
del yahoo wrote:

template <class T>
class Num {
Num<T>(const T){...}:
const Num<T>& operator+=(const Num<T>& incr){...}
friend Num<T> operator+(const Num<T>& l, const Num<T>& r);
};

Tout va bien (et gcc me préviens que je fais une fonction amie non
template),


La partie importante est le *non template*.


Ben oui, mais j'avasi cru comprendre que c'était ce qu'il fallait.

J'écris
template <class T>
inline Num<T> operator+(const Num<T>& l, const Num<T>& r){
Num<T> tmp(l);
return tmp+= r;
}


Et là tu déclares et définis une fonction *template* (i.e.
différente de la famille de fonctions *non template* amies déclarées
précedemment).


Oui, mais j'arrivais pas à écrire la fonction non-template qui corresponde.

Lors de la résolution de surcharge, la fonction amie *non* template
est préférée à la fonction template. Mais tu ne lui as pas fourni
de définition donc tu obtiens une erreur lors de l'édition de liens.


OK


Si tu définis (la fonction non template utilisée):
inline Num<int> operator+(const Num<int>& l, const Num<int>& r)
{
...
}
tout devrait compiler et lier (mais ce n'est pas, heu, très général)


Oui, c'est pas vraiment le but de l'exercice.

Pour faire ce que recherches:
template<class T> class Num;

template<class T> Num<T> operator+(const Num<T>&, const Num<T>&);

template <class T>
class Num
{
Num<T>(const T){...}:
const Num<T>& operator+=(const Num<T>& incr){...}
friend Num<T> operator+ <>(const Num<T>& l, const Num<T>& r);
};

Le <>, sur la ligne du friend, permet de déclarer amie une
spécialisation de la fonction template.


Et les règles de recherche feront qu'il arrivera quand même
à faire la conversion implicite.
OK, merci, j'ai testé et ça semble marcher tout comme il faut.

Marc Boyer