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.
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).
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;
};
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.
Helfer Thomas
Le Wed, 19 Jul 2006 00:44:02 +0200, Sylvain a écrit :
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
Le Wed, 19 Jul 2006 00:44:02 +0200, Sylvain a écrit :
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.
Le Wed, 19 Jul 2006 00:44:02 +0200, Sylvain a écrit :
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
Helfer Thomas
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
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
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
Cette question est liée à l'impossibilité d'écrire le code suivant :
template<class T>
struct Test
{
friend class T;
};
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
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
kanze
Sylvain wrote:
Helfer Thomas wrote on 18/07/2006 23:23:
Cette question est liée à l'impossibilité d'écrire le code suiv ant :
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
Sylvain wrote:
Helfer Thomas wrote on 18/07/2006 23:23:
Cette question est liée à l'impossibilité d'écrire le code suiv ant :
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
Cette question est liée à l'impossibilité d'écrire le code suiv ant :
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
Arnaud Meurgues
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 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
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 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 ?
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
Arnaud Meurgues
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++... ;-)
-- Arnaud
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++... ;-)
On Wed, 19 Jul 2006 17:29:57 +0200, Arnaud Meurgues :
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" ?
Gabriel Dos Reis
"kanze" writes:
| Sylvain wrote: | > 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.)
En effet. À chaque fois que j'avais soulevé le problème, j'ai toujours des explications techniques obscures liées à l'histoire. Finalement, à force d'insister, le langage a été changé. Mike Miller a gentiment pris le bébé et a proposé une modification qui a été acceptée dans le brouillon actuel -- il y a deux ou trois réunions je crois. Maintenant il est possible de dire
template<class T> struct Test { friend T; };
Note l'absence de « class. »
-- Gaby
"kanze" <kanze@gabi-soft.fr> writes:
| Sylvain wrote:
| > 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.)
En effet. À chaque fois que j'avais soulevé le problème, j'ai toujours
des explications techniques obscures liées à l'histoire. Finalement, à
force d'insister, le langage a été changé. Mike Miller a gentiment
pris le bébé et a proposé une modification qui a été acceptée dans le
brouillon actuel -- il y a deux ou trois réunions je crois.
Maintenant il est possible de dire
| Sylvain wrote: | > 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.)
En effet. À chaque fois que j'avais soulevé le problème, j'ai toujours des explications techniques obscures liées à l'histoire. Finalement, à force d'insister, le langage a été changé. Mike Miller a gentiment pris le bébé et a proposé une modification qui a été acceptée dans le brouillon actuel -- il y a deux ou trois réunions je crois. Maintenant il est possible de dire
template<class T> struct Test { friend T; };
Note l'absence de « class. »
-- Gaby
Laurent Deniau
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++... ;-)
| 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++... ;-)
| 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++... ;-)
vous avez pas les memes au format patch ou un cvs qqpart? ;-)
a+, ld.
Gabriel Dos Reis
Arnaud Meurgues 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.
| 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.
| 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.