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

Pb de paramètre de template

3 réponses
Avatar
MGN
J'ai quelques difficultés avec les notations associées aux paramètres des
templates.
J'ai une définition de classe suivante :

template <class T>
class CVar : public CObjet
{
friend class CVar; // toutes les instanciations de CVar sont
mutuellement amies

private :
public :

...
// constructeur de copie
template <class T1> inline CVar(const CVar<T1>&);

template <class T1> inline CVar<T> operator+(const CVar<T1>&)
const;
}

// déclarations d'instanciation explicites

template class CVar<A>;
template class CVar<B>;

template <class T>
inline CVar<T>::CVar(template <class T1> const CVar<T1> &_source) :
CObjet() { ...}

template <class T>
inline CVar<T> CVar<T>::operator+(template <class T1> const CVar<T1> &_r)
const { ... }

Mon compilateur (C++ Builder 6) accepte tout ça. Et ça a l'air de
marcher...mais est-ce le fait du hasard ?
Mais comme je n'ai pas trop de doc sur les templates et que c'est des cas un
peu particuliers, je voudrais savoir si les syntaxes sont correctes...

Mes questions :
Q1) est ce que
friend class CVar;
est la bonne syntaxe pour déclarer amies toutes les instanciations de CVar ?
Q2) même question pour la déclaration du constructeur de copie...et de
l'opérateur +
CVar<A> a;
CVar<B> b(a);

Q3) j'ai fait des déclarations d'instanciation explicite. Mais je me demande
si je dois faire pareil avec les différentes versions de l'opérateur + ?
Je m'explique. Je développe un interpréteur. J'ai une dizaine
d'instanciation du type CVar<T>. Comment m'assurer que toutes les
combinaisons seront bien implémentées ? j'avoue que je comprends hélas pas
bien la cuisine du compilateur ...

Une dernière question : quelle est la réputation de l'implémentation des
templates sur C++ Builder 6 ? j'ai parfois l'impression que mon compilateur
pête les plombs... comme moi d'ailleurs :-)))

Marc

3 réponses

Avatar
kanze
MGN wrote:
J'ai quelques difficultés avec les notations associées aux
paramètres des templates.

J'ai une définition de classe suivante :

template <class T>
class CVar : public CObjet
{
friend class CVar; // toutes les instanciations de CVar sont
mutuellement amies


Dans un template de classe, le nom de la classe templatee réfère
par défaut à l'instantiation en cours, non au template. Les
seules exceptions sont quand il est suivi d'un '<' ou qu'il est
qualifié. Ici donc, tu as déclaré la classe instantiée amie
d'elle-même (ce qui ne sert à rien).

Je crois que la declaration correcte est :

template< typename T > friend class CVar< T > ;

mais je suis loin d'être sûr.

private :
public :

...
// constructeur de copie
template <class T1> inline CVar(const CVar<T1>&);


Attention : ce n'est PAS un constructeur de copie. Au moins, pas
dans le sens de la norme -- on pourrait s'en servir pour copier,
mais sa présence n'inhibe pas la génération du constructeur de
copie par défaut, qui serait préféré par la résolution du
surcharge quand les deux types sont identiques.

template <class T1> inline CVar<T> operator+(const CVar<T1>&)
const;
}

// déclarations d'instanciation explicites

template class CVar<A>;
template class CVar<B>;


C-à-d que tu provoques l'instanciation complète de la classe
ici.

template <class T>
inline CVar<T>::CVar(template <class T1> const CVar<T1> &_source) :
CObjet() { ...}


template< typename T >
template< typename T1 >
inline
CVar<T>::CVar( CVar< T1 > const& source ) : // ...

template <class T>
inline CVar<T> CVar<T>::operator+(template <class T1> const CVar<T1> &_r)
const { ... }


template< typename T >
template< typename T1 >
inline CVar< T >
CVar< T >::operator+( CVar< T1 > const& r ) { // ...

Mon compilateur (C++ Builder 6) accepte tout ça.


C'est bizarre pour la définition des fonctions membre
templatées.

Et ça a l'air de marcher...mais est-ce le fait du hasard ?


A part la syntaxe des définitions des fonction membre templatée,
ce que tu as écrit est légal. En revanche, il ne fait pas ce que
dit les commentaires dans les deux cas cités ci-dessus -- tu as
encore le constructeur de copie par défaut, et les
instanciations ne sont pas des amies l'une de l'autre.

Selon la norme, en tout cas. Il se peut que d'anciens
compilateurs ne soient pas strictement conforme à cet égard.

Mais comme je n'ai pas trop de doc sur les templates et que
c'est des cas un peu particuliers, je voudrais savoir si les
syntaxes sont correctes...

Mes questions :

Q1) est ce que friend class CVar; est la bonne syntaxe pour
déclarer amies toutes les instanciations de CVar ?


Non. §14.6.1/1 : « Within the scope of a class template, when
the name of the template is neither qualilfied nor followed by
<, it is equivalent to the name of the template followed by the
template-arguments enclosed in <>. » Ce que tu as écrit est donc
l'équivalent de « friend class CVar<T>; ».

Selon §14.5.3, pour rendre un template de classe ami, la syntaxe
serait :
template< typename T1 > friend class C ;
Seulement, on aurait encore l'ajoute implicite du <T>. Je crois
qu'en ajoutant explicitement le <T1>, ça doit marcher, mais je
ne suis pas sûr.

Q2) même question pour la déclaration du constructeur de copie...et de
l'opérateur +


Non. Je m'étonne même qu'un compilateur accepte le deuxième
utilisation du mot clé template que tu as dans chaque
définition.

CVar<A> a;
CVar<B> b(a);

Q3) j'ai fait des déclarations d'instanciation explicite. Mais
je me demande si je dois faire pareil avec les différentes
versions de l'opérateur + ?


Quand tu démandes l'instanciation explicite d'un template de
classe, on instancie *tous* les membres. C'est vrai que quand le
membre même est aussi un template... Je ne trouve rien dans la
norme qui en parle. Logiquement, le compilateur ne peut pas
instancier le template membre, parce qu'il ne connaît pas le T1.
Je ne suis donc pas sûr du tout de la syntaxe pour le faire.
Peut-être :
template CVar<A> CVar<A>::operator+( CVar< B > const& ) ;
Mais j'avoue qu'ici, je joue aux devinettes, et que je ne suis
même pas certain que le cas est prévu ou permis.

Je m'explique. Je développe un interpréteur. J'ai une dizaine
d'instanciation du type CVar<T>. Comment m'assurer que toutes
les combinaisons seront bien implémentées ?


Comment est-ce que tu les utilise ? Si tu utilises quelque
chose, le compilateur doit l'instancier implicitement.

j'avoue que je comprends hélas pas bien la cuisine du
compilateur ...

Une dernière question : quelle est la réputation de
l'implémentation des templates sur C++ Builder 6 ? j'ai
parfois l'impression que mon compilateur pête les plombs...
comme moi d'ailleurs :-)))


Je ne le connais pas, mais il est sorti quand ? Certaines de ces
fonctionnalités ne se sont figées que tout à la fin de la
normalisation ; c'est donc normal que des compilateurs plus
anciens ne respectent pas exactement la norme en ce qui leur
concerne. Pour des choses simples, je ne dis pas, mais quand on
veut exploiter toutes les possibilités des templates, je
conseillerais un compilateur assez récent -- une version qui a
moins de deux ou trois ans, si possible.

--
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
Fabien LE LEZ
On 16 Dec 2005 01:33:05 -0800, "kanze" :

Il se peut que d'anciens
compilateurs ne soient pas strictement conforme à cet égard.


BCB6 est relativement récent.
Mais les compilos Borland ont tendance à être assez permissifs avec
les options par défaut.

Avatar
MGN
merci beaucoup pour tes réponses détaillées...
Je vais étudier tout ça ce lundi (je n'ai pas le temps avant) et je te
tiendrai au courant.
Comme je te disais,j'ai commencé à tester avec ma syntaxe actuelle et ça
marche (par exemple les différentes instanciations de CVar sont bien amies,
je peux "convertir", ajouter, etc...)...mais je préfèrerais être conforme à
la norme :-))) et que ça marche aussi !
Marc