Et bien entendu, quand dans un autre fichier, je tente de faire :
class APtr;
"class" introduit un nouveau type. Or, APtr n'est pas un nouveau type, puisque c'est exactement "boost::shared_ptr<A>".
Imagine ceci :
class A; class B; void f (A const&) {} void f (B const&) {} // OK, ce n'est pas la même fonction car le paramètre est différent
typedef A B; // Oups, finalement A et B sont un seul type !
James Kanze
Loïc Joly wrote:
Je me trouve souvent avec du code comme ça : class A {...}; typedef boost::shared_ptr<A> APtr;
Et bien entendu, quand dans un autre fichier, je tente de faire :
class APtr; class B { int f(APtr a); };
Ca ne marche pas.
Je ne suis pas sûr ce que tu veux dire par : ça ne marche pas. Si quelque part dans cet autre fichier, tu as inclu le premier, c'est normal que tu aies un problème. D'une part, tu dis que APtr est en fait boost::shared_ptr<A>, et de l'autre tu dis que c'est une classe en soi. Il ne peut pas être les deux.
Si, en revanche, il n'y a pas d'inclusion, il ne doit pas y avoir de problème. Un nom défini par un typedef n'est pas visible en dehors de l'unité de compilation où il est déclaré. Le typedef ne doit pas poser de problème dans la définition d'une classe du même nom dans une autre unité de compilation.
Enfin, si tu t'attends à ce que la classe APtr dans le deuxième fichier correspond bien au typedef dans le premier, comme le semble penser d'autres qui ont répondu, je me démande bien pourquoi. Tu sais bien que (§3.5/8) « Names not covered by these rules have no linkage. » Quelle règle donne un linkage au nom APtr dans le premier fichier ?
Indépendamment des règles, j'aimerais bien savoir comment tu implémenterais une telle chose. L'implémentation classique des fonctions décore les noms des fonctions avec des informations sur les paramètres. Donc, dans le deuxième fichier, on aurait quelque chose comme __1cBBBf6MnEAPtr__i_ ou _ZN1B1fE4APtr, tandis qu'avec boost::shared_ptr<A> serait quelque chose comme __1cBBBf6MnFboostKshared_ptr4nBA____i_ ou _ZN1B1fEN5boost10shared_ptrI1AEE. D'ailleurs, rien ne t'empèche, dans le deuxième fichier, d'inclure une définition de la classe A sans le typedef, et de surcharger f avec un paramètre du type boost::shared_ptr<A>. C-à-d que la légalité de :
#include <boost/shared_ptr.hpp> class A ; class APtr ;
class B { int f( APtr ) ; int f( boost::shared_ptr<A> ) ; } ;
dépendrait d'un typedef dans une autre unité de compilation, que le compilateur ne pourrait pas voir (et qui n'est peut-être même pas écrit au moment que je compile ce code).
-- James Kanze (GABI Software) email: 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
Loïc Joly wrote:
Je me trouve souvent avec du code comme ça :
class A {...};
typedef boost::shared_ptr<A> APtr;
Et bien entendu, quand dans un autre fichier, je tente de faire :
class APtr;
class B
{
int f(APtr a);
};
Ca ne marche pas.
Je ne suis pas sûr ce que tu veux dire par : ça ne marche pas.
Si quelque part dans cet autre fichier, tu as inclu le premier,
c'est normal que tu aies un problème. D'une part, tu dis que
APtr est en fait boost::shared_ptr<A>, et de l'autre tu dis que
c'est une classe en soi. Il ne peut pas être les deux.
Si, en revanche, il n'y a pas d'inclusion, il ne doit pas y
avoir de problème. Un nom défini par un typedef n'est pas
visible en dehors de l'unité de compilation où il est déclaré.
Le typedef ne doit pas poser de problème dans la définition
d'une classe du même nom dans une autre unité de compilation.
Enfin, si tu t'attends à ce que la classe APtr dans le deuxième
fichier correspond bien au typedef dans le premier, comme le
semble penser d'autres qui ont répondu, je me démande bien
pourquoi. Tu sais bien que (§3.5/8) « Names not covered by
these rules have no linkage. » Quelle règle donne un linkage au
nom APtr dans le premier fichier ?
Indépendamment des règles, j'aimerais bien savoir comment tu
implémenterais une telle chose. L'implémentation classique des
fonctions décore les noms des fonctions avec des informations
sur les paramètres. Donc, dans le deuxième fichier, on aurait
quelque chose comme __1cBBBf6MnEAPtr__i_ ou _ZN1B1fE4APtr,
tandis qu'avec boost::shared_ptr<A> serait quelque chose comme
__1cBBBf6MnFboostKshared_ptr4nBA____i_ ou
_ZN1B1fEN5boost10shared_ptrI1AEE. D'ailleurs, rien ne t'empèche,
dans le deuxième fichier, d'inclure une définition de la classe
A sans le typedef, et de surcharger f avec un paramètre du type
boost::shared_ptr<A>. C-à-d que la légalité de :
#include <boost/shared_ptr.hpp>
class A ;
class APtr ;
class B
{
int f( APtr ) ;
int f( boost::shared_ptr<A> ) ;
} ;
dépendrait d'un typedef dans une autre unité de compilation, que
le compilateur ne pourrait pas voir (et qui n'est peut-être même
pas écrit au moment que je compile ce code).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
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
Je me trouve souvent avec du code comme ça : class A {...}; typedef boost::shared_ptr<A> APtr;
Et bien entendu, quand dans un autre fichier, je tente de faire :
class APtr; class B { int f(APtr a); };
Ca ne marche pas.
Je ne suis pas sûr ce que tu veux dire par : ça ne marche pas. Si quelque part dans cet autre fichier, tu as inclu le premier, c'est normal que tu aies un problème. D'une part, tu dis que APtr est en fait boost::shared_ptr<A>, et de l'autre tu dis que c'est une classe en soi. Il ne peut pas être les deux.
Si, en revanche, il n'y a pas d'inclusion, il ne doit pas y avoir de problème. Un nom défini par un typedef n'est pas visible en dehors de l'unité de compilation où il est déclaré. Le typedef ne doit pas poser de problème dans la définition d'une classe du même nom dans une autre unité de compilation.
Enfin, si tu t'attends à ce que la classe APtr dans le deuxième fichier correspond bien au typedef dans le premier, comme le semble penser d'autres qui ont répondu, je me démande bien pourquoi. Tu sais bien que (§3.5/8) « Names not covered by these rules have no linkage. » Quelle règle donne un linkage au nom APtr dans le premier fichier ?
Indépendamment des règles, j'aimerais bien savoir comment tu implémenterais une telle chose. L'implémentation classique des fonctions décore les noms des fonctions avec des informations sur les paramètres. Donc, dans le deuxième fichier, on aurait quelque chose comme __1cBBBf6MnEAPtr__i_ ou _ZN1B1fE4APtr, tandis qu'avec boost::shared_ptr<A> serait quelque chose comme __1cBBBf6MnFboostKshared_ptr4nBA____i_ ou _ZN1B1fEN5boost10shared_ptrI1AEE. D'ailleurs, rien ne t'empèche, dans le deuxième fichier, d'inclure une définition de la classe A sans le typedef, et de surcharger f avec un paramètre du type boost::shared_ptr<A>. C-à-d que la légalité de :
#include <boost/shared_ptr.hpp> class A ; class APtr ;
class B { int f( APtr ) ; int f( boost::shared_ptr<A> ) ; } ;
dépendrait d'un typedef dans une autre unité de compilation, que le compilateur ne pourrait pas voir (et qui n'est peut-être même pas écrit au moment que je compile ce code).
-- James Kanze (GABI Software) email: 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
Mathias Gaunard
Je me trouve souvent avec du code comme ça : class A {...}; typedef boost::shared_ptr<A> APtr;
class APtr : public boost::shared_ptr<A> { };
devrait donner plus ou moins ce que tu veux.
Je me trouve souvent avec du code comme ça :
class A {...};
typedef boost::shared_ptr<A> APtr;
class APtr : public boost::shared_ptr<A> { }; devrait donner plus ou moins ce que tu veux.
Cette solution t'oblige à redéfinir les constructeurs et opérateurs d'affectation dans la classe dérivée, ce qui ne me semble pas très pratique...
Falk
Loïc Joly
Loïc Joly wrote:
D'abord, merci à tous ceux qui ont répondu.
Enfin, si tu t'attends à ce que la classe APtr dans le deuxième fichier correspond bien au typedef dans le premier, comme le semble penser d'autres qui ont répondu, je me démande bien pourquoi. Tu sais bien que (§3.5/8) « Names not covered by these rules have no linkage. » Quelle règle donne un linkage au nom APtr dans le premier fichier ?
Je savais que ça ne marchais pas (même si je ne savais plus le paragraphe exact, merci), mais je ne savais pas trop pour quelle raison on ne l'avait pas fait marcher. Parce que ça pourrait avoir de l'intérêt. Ainsi, dans mon code, un simple : class APtr;
Pourrait remplacer les deux alternatives que j'ai actuellement, et qui m'obligent à trop inclure, et à trop écrire : #include <shared_ptr.hpp> class A; typedef boost::shared_ptr<A> APtr;
ou bien : #include "A.h"
Aujourd'hui, le type de pointeur intelligent sur A que j'utilise est spécifié à de multiples points dans mon code, et ça m'ennuie. Ou alors je peux écrire un fichier "APtr.h" qui ne défini que le typedef, mais ça me semble lourd d'ajouter un fichier rien que pour ça. A réfléchir.
Indépendamment des règles, j'aimerais bien savoir comment tu implémenterais une telle chose. L'implémentation classique des fonctions décore les noms des fonctions avec des informations sur les paramètres. Donc, dans le deuxième fichier, on aurait quelque chose comme __1cBBBf6MnEAPtr__i_ ou _ZN1B1fE4APtr, tandis qu'avec boost::shared_ptr<A> serait quelque chose comme __1cBBBf6MnFboostKshared_ptr4nBA____i_ ou _ZN1B1fEN5boost10shared_ptrI1AEE. D'ailleurs, rien ne t'empèche, dans le deuxième fichier, d'inclure une définition de la classe A sans le typedef, et de surcharger f avec un paramètre du type boost::shared_ptr<A>. C-à-d que la légalité de :
#include <boost/shared_ptr.hpp> class A ; class APtr ;
class B { int f( APtr ) ; int f( boost::shared_ptr<A> ) ; } ;
dépendrait d'un typedef dans une autre unité de compilation, que le compilateur ne pourrait pas voir (et qui n'est peut-être même pas écrit au moment que je compile ce code).
Ce sont effectivement deux bonnes raisons, et je ne vois guère que l'introduction d'un typedef fortement typé pour résoudre ces problèmes.
-- Loïc
Loïc Joly wrote:
D'abord, merci à tous ceux qui ont répondu.
Enfin, si tu t'attends à ce que la classe APtr dans le deuxième
fichier correspond bien au typedef dans le premier, comme le
semble penser d'autres qui ont répondu, je me démande bien
pourquoi. Tu sais bien que (§3.5/8) « Names not covered by
these rules have no linkage. » Quelle règle donne un linkage au
nom APtr dans le premier fichier ?
Je savais que ça ne marchais pas (même si je ne savais plus le
paragraphe exact, merci), mais je ne savais pas trop pour quelle raison
on ne l'avait pas fait marcher. Parce que ça pourrait avoir de
l'intérêt. Ainsi, dans mon code, un simple :
class APtr;
Pourrait remplacer les deux alternatives que j'ai actuellement, et qui
m'obligent à trop inclure, et à trop écrire :
#include <shared_ptr.hpp>
class A;
typedef boost::shared_ptr<A> APtr;
ou bien :
#include "A.h"
Aujourd'hui, le type de pointeur intelligent sur A que j'utilise est
spécifié à de multiples points dans mon code, et ça m'ennuie. Ou alors
je peux écrire un fichier "APtr.h" qui ne défini que le typedef, mais ça
me semble lourd d'ajouter un fichier rien que pour ça. A réfléchir.
Indépendamment des règles, j'aimerais bien savoir comment tu
implémenterais une telle chose. L'implémentation classique des
fonctions décore les noms des fonctions avec des informations
sur les paramètres. Donc, dans le deuxième fichier, on aurait
quelque chose comme __1cBBBf6MnEAPtr__i_ ou _ZN1B1fE4APtr,
tandis qu'avec boost::shared_ptr<A> serait quelque chose comme
__1cBBBf6MnFboostKshared_ptr4nBA____i_ ou
_ZN1B1fEN5boost10shared_ptrI1AEE. D'ailleurs, rien ne t'empèche,
dans le deuxième fichier, d'inclure une définition de la classe
A sans le typedef, et de surcharger f avec un paramètre du type
boost::shared_ptr<A>. C-à-d que la légalité de :
#include <boost/shared_ptr.hpp>
class A ;
class APtr ;
class B
{
int f( APtr ) ;
int f( boost::shared_ptr<A> ) ;
} ;
dépendrait d'un typedef dans une autre unité de compilation, que
le compilateur ne pourrait pas voir (et qui n'est peut-être même
pas écrit au moment que je compile ce code).
Ce sont effectivement deux bonnes raisons, et je ne vois guère que
l'introduction d'un typedef fortement typé pour résoudre ces problèmes.
Enfin, si tu t'attends à ce que la classe APtr dans le deuxième fichier correspond bien au typedef dans le premier, comme le semble penser d'autres qui ont répondu, je me démande bien pourquoi. Tu sais bien que (§3.5/8) « Names not covered by these rules have no linkage. » Quelle règle donne un linkage au nom APtr dans le premier fichier ?
Je savais que ça ne marchais pas (même si je ne savais plus le paragraphe exact, merci), mais je ne savais pas trop pour quelle raison on ne l'avait pas fait marcher. Parce que ça pourrait avoir de l'intérêt. Ainsi, dans mon code, un simple : class APtr;
Pourrait remplacer les deux alternatives que j'ai actuellement, et qui m'obligent à trop inclure, et à trop écrire : #include <shared_ptr.hpp> class A; typedef boost::shared_ptr<A> APtr;
ou bien : #include "A.h"
Aujourd'hui, le type de pointeur intelligent sur A que j'utilise est spécifié à de multiples points dans mon code, et ça m'ennuie. Ou alors je peux écrire un fichier "APtr.h" qui ne défini que le typedef, mais ça me semble lourd d'ajouter un fichier rien que pour ça. A réfléchir.
Indépendamment des règles, j'aimerais bien savoir comment tu implémenterais une telle chose. L'implémentation classique des fonctions décore les noms des fonctions avec des informations sur les paramètres. Donc, dans le deuxième fichier, on aurait quelque chose comme __1cBBBf6MnEAPtr__i_ ou _ZN1B1fE4APtr, tandis qu'avec boost::shared_ptr<A> serait quelque chose comme __1cBBBf6MnFboostKshared_ptr4nBA____i_ ou _ZN1B1fEN5boost10shared_ptrI1AEE. D'ailleurs, rien ne t'empèche, dans le deuxième fichier, d'inclure une définition de la classe A sans le typedef, et de surcharger f avec un paramètre du type boost::shared_ptr<A>. C-à-d que la légalité de :
#include <boost/shared_ptr.hpp> class A ; class APtr ;
class B { int f( APtr ) ; int f( boost::shared_ptr<A> ) ; } ;
dépendrait d'un typedef dans une autre unité de compilation, que le compilateur ne pourrait pas voir (et qui n'est peut-être même pas écrit au moment que je compile ce code).
Ce sont effectivement deux bonnes raisons, et je ne vois guère que l'introduction d'un typedef fortement typé pour résoudre ces problèmes.
-- Loïc
Fabien LE LEZ
On Fri, 09 Feb 2007 21:27:26 +0100, Loïc Joly :
et je ne vois guère que l'introduction d'un typedef fortement typé pour résoudre ces problèmes.
Y'a une chance pour que ce graal voie le jour ?
On Fri, 09 Feb 2007 21:27:26 +0100, Loïc Joly
<loic.actarus.joly@numericable.fr>:
et je ne vois guère que
l'introduction d'un typedef fortement typé pour résoudre ces problèmes.
et je ne vois guère que l'introduction d'un typedef fortement typé pour résoudre ces problèmes.
Y'a une chance pour que ce graal voie le jour ?
Mathias Gaunard
Cette solution t'oblige à redéfinir les constructeurs et opérateurs d'affectation dans la classe dérivée, ce qui ne me semble pas très pratique...
Uniquement les constructeurs non défauts, pas de problème avec operator=. Et le problème des constructeurs sera résolu en permettant l'utilisation des constructeurs avec using.
À mon avis ils auraient mieux fait de carrément supporter les mixins, mais bon.
Cette solution t'oblige à redéfinir les constructeurs et opérateurs
d'affectation dans la classe dérivée, ce qui ne me semble pas très
pratique...
Uniquement les constructeurs non défauts, pas de problème avec operator=.
Et le problème des constructeurs sera résolu en permettant l'utilisation
des constructeurs avec using.
À mon avis ils auraient mieux fait de carrément supporter les mixins,
mais bon.
Cette solution t'oblige à redéfinir les constructeurs et opérateurs d'affectation dans la classe dérivée, ce qui ne me semble pas très pratique...
Uniquement les constructeurs non défauts, pas de problème avec operator=. Et le problème des constructeurs sera résolu en permettant l'utilisation des constructeurs avec using.
À mon avis ils auraient mieux fait de carrément supporter les mixins, mais bon.