OVH Cloud OVH Cloud

Comment déclarer friend un paramètre template d'une classe ?

16 réponses
Avatar
Helfer Thomas
Cette question est liée à l'impossibilité d'écrire le code suivant :

template<class T>
struct Test
{
friend class T;
};

Existerait-il un moyen (détourné) de faire cela ?

Cordialement,

Helfer Thomas

6 réponses

1 2
Avatar
Gabriel Dos Reis
Arnaud Meurgues writes:

| Gabriel Dos Reis wrote:
|
| > Parce que le « class » dans « friend class T » dit vraiment que T est
| > une classe (i.e. quelque déclarée avec « class » ou « struct. »)
| [...]
| > le « class » dans « template<class T> » est la même chose que
| > « typename », ce qui est différent.
|
| Parfois, je me demande pourquoi j'aime le C++... ;-)

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1520.pdf
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1616.pdf
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1722.pdf
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1791.pdf

-- Gaby
Avatar
Sylvain
kanze wrote on 19/07/2006 10:45:

template<class T>
struct Test
{
friend class T;
};


je suppose que le /struct/ Test vient du fait qu'en effet avec
une /classe/ template cela ne passe pas (parce que écrit comme
cela ça passe évidemment).


Tu pourrais t'expliquer. Parce que je ne vois pas la moindre
différence entre struct et class ici.


"expliquer" c'est dur puisqu'il s'agit d'un code tellemnt réduit qu'il
ne montre pas l'objet même de la question.

déroulons: "friend class T" exprime le fait que la classe "T"
machin-chose (comment dites-vous d'ailleurs?) du template aurait accès
au membres protégés de "Test".

or "Test" est une struct (et non une classe) et donc publie déjà tous
ses membres aux classes amies ou pas, comme à tout bout de code.

second point, Test n'a aucune donnée membre, donc savoir si T sera
suffisamment copain pour accéder à rien est également difficile à commenter.

Sylvain.



Avatar
Gabriel Dos Reis
Laurent Deniau writes:

| Gabriel Dos Reis wrote:
| > Arnaud Meurgues writes:
| > | Gabriel Dos Reis wrote:
| > | | > Parce que le « class » dans « friend class T » dit vraiment
| > que T est
| > | > une classe (i.e. quelque déclarée avec « class » ou « struct. »)
| > | [...]
| > | > le « class » dans « template<class T> » est la même chose que |
| > > « typename », ce qui est différent.
| > | | Parfois, je me demande pourquoi j'aime le C++... ;-)
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1520.pdf
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1616.pdf
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1722.pdf
| > http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1791.pdf
|
| vous avez pas les memes au format patch ou un cvs qqpart? ;-)

Je suis persuadé que l'auteur en dispose quelque part :-)

-- Gaby
Avatar
kanze
Sylvain wrote:
kanze wrote on 19/07/2006 10:45:

template<class T>
struct Test
{
friend class T;
};


je suppose que le /struct/ Test vient du fait qu'en effet
avec une /classe/ template cela ne passe pas (parce que
écrit comme cela ça passe évidemment).


Tu pourrais t'expliquer. Parce que je ne vois pas la moindre
différence entre struct et class ici.


"expliquer" c'est dur puisqu'il s'agit d'un code tellemnt
réduit qu'il ne montre pas l'objet même de la question.


C'est sûr que dans l'exemple même, le friend ne pourrait pas
donner accès à grand chose, étant donné que la classe ne
contient pas grand chose.

déroulons: "friend class T" exprime le fait que la classe "T"
machin-chose (comment dites-vous d'ailleurs?) du template
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


La classe T. Ou simplement T.

aurait accès au membres protégés de "Test".


Je suppose qu'ici, tu entends par « protégé » le sens général
du mot, et non comme traduction du mot clé « protected ».
Friend donne bien accès aussi aux membres « private ».

or "Test" est une struct (et non une classe)


« Test » est une classe. Il n'y a pas de « struct » en C++.
Il y a bien un concepte de « POD-struct », et une
instanciation de Test ici serait bien un « POD-struct ». Mais
il me semble évident que la définition ici ne contient que des
parties qui rapporte à la discussion ; dans l'absense de
membre, friend ne sert effectivement à rien. Et dans la mesure
qu'on ne sait rien de ces membres, on ne saurait dire si la
classe réele est une POD-struct ou non.

et donc publie déjà tous ses membres aux classes amies ou pas,
comme à tout bout de code.


C'est une convention assez répandue d'utiliser le mot clé struct
pour définir une classe où tous les membres sont publics, et que
pour de telles classes, mais c'est loin d'être une règle.

second point, Test n'a aucune donnée membre, donc savoir si T
sera suffisamment copain pour accéder à rien est également
difficile à commenter.


Tout à fait d'accord là. Mais la question tournait uniquement
sur la légalité de la declaration « friend », non sur son
utilité dans le cas précis de l'exemple. Le point que Thomas
faisait, c'est qu'il n'y a aucune façon de faire un paramètre
type d'un template ami de la classe templatée.

(En fait, il y a une tradition d'utiliser le mot-clé struct,
plutôt de class, dans les questions qui concernent
l'interprétation de la norme. Sans doute parce qu'en général, la
question ne concerne pas l'accès, et les spécifications d'accès
n'y serait que du verbiage pour rien.)

--
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
Helfer Thomas
Merci pour vos réponses. Pour répondre à vos questions, j'utilise de
manière indifférente class ou struct. La finalité de la question est
bien sûr que le paramètre template de Test puisse accéder aux données
membres privées/protégées (Oui, je n'en ai pas mis dans l'exemple...).

J'ai trouvé une astuce qui fonctionne avec gcc 4.1. Il s'agit de faire
ceci :

template<typename T>
struct identity
{
typedef T type;
};

template<class T>
struct Test
{
friend class typename identity<T>::type;
};

Cette solution fonctionne. Puis-je attendre qu'elle soit portable ?

Cordialement,

Helfer Thomas

Cette question est liée à l'impossibilité d'écrire le code suivant :

template<class T>
struct Test
{
friend class T;
};

Existerait-il un moyen (détourné) de faire cela ?

Cordialement,

Helfer Thomas


Avatar
Gabriel Dos Reis
Helfer Thomas writes:

[...]

| template<typename T>
| struct identity
| {
| typedef T type;
| };
|
| template<class T>
| struct Test
| {
| friend class typename identity<T>::type;
| };
|
| Cette solution fonctionne. Puis-je attendre qu'elle soit portable ?

Normalement, elle est invalide ; voir le premier des liens que j'ai
postés hier.

-- Gaby
1 2