 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Helfer Thomas Guest
|
Posted: Wed Jul 19, 2006 2:23 am Post subject: Comment déclarer friend un paramètre template d'une classe ? |
|
|
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 |
|
| Back to top |
|
 |
Sylvain Guest
|
Posted: Wed Jul 19, 2006 3:44 am Post subject: Re: Comment déclarer friend un paramèt re template d'une cla |
|
|
Helfer Thomas wrote on 18/07/2006 23:23:
| Quote: | 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 ?
|
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).
si c'est du cas par cas, vous pouvez forcez la génération du code
template et résoudre l'impossibilité par:
lib:
template<class T>
class Test
{
....
};
code applicatif:
class theT;
class TestTheT : public Test<TheT> {
friend class TheT;
};
Sylvain. |
|
| Back to top |
|
 |
Helfer Thomas Guest
|
Posted: Wed Jul 19, 2006 9:12 am Post subject: Re: Comment déclarer friend un paramètre template d'une clas |
|
|
Le Wed, 19 Jul 2006 00:44:02 +0200, Sylvain a écrit :
| Quote: | Helfer Thomas wrote on 18/07/2006 23:23:
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 ?
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).
Non le problème est le même que l'on soit en struct ou en class. De |
manière plus précise, le morceau de code écrit plus haut conduit au
message d'erreur suivant (gcc-4.0) :
essai.cxx:15: erreur: using template type parameter «T» after «class»
essai.cxx:15: erreur: déclaration amie ne nomme pas une classe ou une
fonction
Votre proposition est intéressante, mais n'a pas la souplesse du code que
je souhaiterai écrire.
Cordialement,
Helfer Thomas |
|
| Back to top |
|
 |
Helfer Thomas Guest
|
Posted: Wed Jul 19, 2006 9:12 am Post subject: Re: Comment déclarer friend un paramètre template d'une clas |
|
|
Le Tue, 18 Jul 2006 23:23:59 +0200, Helfer Thomas a écrit :
Voici un extrait de la faq du compilateur Comeau qui explique
plus en détails mon soucis :
What's wrong with saying friend class T within a template?
Trying to use a template parameter in a friend is ill-formed:
template <typename T>
class xyz {
friend class T; // ill-formed code
};
According to Section 7.1.5.3 paragraph 2 of Standard C++:
3.4.4 describes how name lookup proceeds for the identifier
in an elaborated-type-specifier. ... If the identifier
resolves to a typedef-name or a template type-parameter,
the elaborated-type-specifier is ill-formed.
[Note: this implies that, within a class template
with a template type-parameter T, the declaration
friend class T;
is ill-formed. ]
The next thing one would try would be:
template <typename T>
class xyz {
friend T;
};
but this form is not allowed either because for friends, according
to 11.4 paragraph 2
An elaborated-type-specifier shall be used in a friend
declaration for a class.
And also from footnote #101:
The class-key of the elaborated-type-specifier is required.
You could also probably try some hackery with typedef, but I
suspect all of these attempts will also be illegal.
Le code que j'aimerai utilisé est donc illegal en C++ standard, d'où la
recherche d'une solution détournée...
Merci pour votre aide
Cordialement,
Helfer Thomas
| Quote: | 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 |
|
|
| Back to top |
|
 |
kanze Guest
|
Posted: Wed Jul 19, 2006 9:12 am Post subject: Re: Comment déclarer friend un paramètre template d'une clas |
|
|
Sylvain wrote:
| Quote: | Helfer Thomas wrote on 18/07/2006 23:23:
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 ?
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.
Le code est illégal, c'est sûr. (Je ne serais pas étonné qu'il y
ait une proposition pour résoudre le problème dans la prochaine
version de la norme. Mais ça n'aide pas dans l'immédiat.)
A priori, je ne connais pas de bon work-around, à part rendre
tous les membres de Test public (ce qui permettrait, évidemment,
à classe T d'y accéder, mais aussi à toutes les autres classes).
La plus proche que je peux penser, c'est d'écrire une deuxième
classe template, TestAccessor, de le déclarer comme ami de Test,
et lui pourvoir avec les fonctions (protegées) qui effectuent
tous les accès nécessaire. Aussi, on ne lui donne que un
constructeur protégé, et on utilise des contraints pour assurer
que T dérive de lui. (Est-ce qu'on pourrait s'assurer d'une
façon statique qu'aucune autre classe dérive de lui ?) Quelque
chose du genre :
template< typename T >
class TestAccessor ;
template< typename T >
class Test
{
friend class TestAccessor< T > ;
int i ;
// ...
} ;
template< typename T >
class TestAccessor : boost::noncopiable
{
protected:
int& testI( Test< T >* p ) {
assert( dynamic_cast< T* >( this ) != NULL ) ;
return p->i ;
}
// ...
TestAccessor()
{
T* p = static_cast< T* >( this ) ;
}
} ;
Ça exige que T dérive de TestAccessor<T>, et est contournable,
mais ça doit éviter les accès accidentaux.
--
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 |
|
| Back to top |
|
 |
Arnaud Meurgues Guest
|
Posted: Wed Jul 19, 2006 7:57 pm Post subject: Re: Comment déclarer friend un paramètr e template d'une cla |
|
|
Gabriel Dos Reis wrote:
Merci d'avoir insisté...
| Quote: | template<class T
struct Test
{
friend T;
};
Note l'absence de « class. »
|
Pourquoi pas class ?
Parce que aucun autre identifieur ne serait valable qu'une fonction qui
serait reconnaissable ?
Ou bien parce que le
template <class T>
a déjà précisé que T était une classe ?
Ou pour une autre raison sioux qui m'échappe ?
--
Arnaud |
|
| Back to top |
|
 |
Arnaud Meurgues Guest
|
Posted: Wed Jul 19, 2006 8:29 pm Post subject: Re: Comment déclarer friend un paramètr e template d'une cla |
|
|
Gabriel Dos Reis wrote:
| Quote: | 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++... ;-)
--
Arnaud |
|
| Back to top |
|
 |
Fabien LE LEZ Guest
|
Posted: Wed Jul 19, 2006 8:59 pm Post subject: Re: Comment déclarer friend un paramètre template d'une clas |
|
|
On Wed, 19 Jul 2006 17:29:57 +0200, Arnaud Meurgues
<news.arnaud (AT) meurgues (DOT) non.fr.invalid>:
| Quote: | Parfois, je me demande pourquoi j'aime le C++...
|
N'est-ce pas Winston Churchill qui a dit "Le C++ est le pire des
langages, à l'exception de tous les autres" ? |
|
| Back to top |
|
 |
Laurent Deniau Guest
|
Posted: Wed Jul 19, 2006 9:21 pm Post subject: Re: Comment déclarer friend un paramètr e template d'une cla |
|
|
Gabriel Dos Reis wrote:
vous avez pas les memes au format patch ou un cvs qqpart? ;-)
a+, ld. |
|
| Back to top |
|
 |
Gabriel Dos Reis Guest
|
Posted: Wed Jul 19, 2006 9:55 pm Post subject: Re: Comment déclarer friend un paramètre template d'une clas |
|
|
Arnaud Meurgues <news.arnaud (AT) meurgues (DOT) non.fr.invalid> writes:
| Gabriel Dos Reis wrote:
|
| Merci d'avoir insisté...
|
| > template<class T>
| > struct Test
| > {
| > friend T;
| > };
| >
| > Note l'absence de « class. »
|
| Pourquoi pas class ?
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. ») Que
se passe-t-il avec
union foo { /* ... */ };
Test<foo> x;
?
| Parce que aucun autre identifieur ne serait valable qu'une fonction qui
| serait reconnaissable ?
| Ou bien parce que le
| template <class T>
| a déjà précisé que T était une classe ?
le « class » dans « template<class T> » est la même chose que
« typename », ce qui est différent.
-- Gaby |
|
| Back to top |
|
 |
Gabriel Dos Reis Guest
|
|
| Back to top |
|
 |
Sylvain Guest
|
Posted: Wed Jul 19, 2006 10:59 pm Post subject: Re: Comment déclarer friend un paramètr e template d'une cla |
|
|
kanze wrote on 19/07/2006 10:45:
| Quote: |
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. |
|
| Back to top |
|
 |
Gabriel Dos Reis Guest
|
|
| Back to top |
|
 |
kanze Guest
|
Posted: Thu Jul 20, 2006 9:11 am Post subject: Re: Comment déclarer friend un paramètre template d'une clas |
|
|
Sylvain wrote:
| Quote: | 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.
| Quote: | 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.
| Quote: | 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 ».
| Quote: | 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.
| Quote: | 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.
| Quote: | 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 |
|
| Back to top |
|
 |
Helfer Thomas Guest
|
Posted: Thu Jul 20, 2006 10:33 pm Post subject: Re: Comment déclarer friend un paramètre template d'une clas |
|
|
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
| Quote: | 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 |
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|