OVH Cloud OVH Cloud

pinaillage sur typedef

26 réponses
Avatar
fabien.chene
Bonjour,

Une question qui me tarabuste, Qu'est-ce qui a motivé la norme a
déclarer ce code illégal ? (selon $7.1.3.3) :

class Foo;
typedef int Foo;

A noter que l'exemple illustratif de $7.1.3.3 se sent obliger de
montrer une définition. Dans $7.1.3.3, Je note aussi que le diagnostic
indiqué de «typedef int complex;» (suite à class complex { /*
... */};) est une redéfinition (alors que typedef fait une
déclaration).


En fait, ce serait pas mal qu'un «typedef-name» soit un «class-name»,
même s'il ne nommme pas une classe. Je suppose que cela serait source
de problèmes, mais, si c'est bien le cas, j'avoue ne pas le(s) voir du
premier coup d'oeil.

Merci d'avance.

--
Fab

10 réponses

1 2 3
Avatar
Fabien LE LEZ
On Sat, 10 Jun 2006 01:43:39 +0200, (Fabien
CHÊNE):

Une question qui me tarabuste, Qu'est-ce qui a motivé la norme a
déclarer ce code illégal ? (selon $7.1.3.3) :

class Foo;
typedef int Foo;


Je n'ai pas la version officielle, mais je suppose que ça vient du
fait qu'on peut écrire :

class Foo;

void f (int);
void f (Foo);

Si tu écris "typedef int Foo;", tout à coup les deux fonctions "f()"
deviennent identiques :

void f (int);
void f (int);

Avatar
Jean-Marc Bourguet
(Fabien CHÊNE) writes:

Une question qui me tarabuste, Qu'est-ce qui a motivé la
norme a déclarer ce code illégal ? (selon $7.1.3.3) :

class Foo;
typedef int Foo;


Je ne vois pas quel est le problème avec ça. Un nom
introduit par typedef est utilisé dans les mêmes contextes
que les noms de type, une surcharge n'est donc pas
résolvable par le contexte.

La vraie question est plutôt pourquoi

typedef class Foo Foo;

est autorisé. La raison est la compatibilité avec le C ou

struct S;

n'introduit pas S comme nom de type et donc il est courant
de faire

typedef struct S S;

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Fabien LE LEZ
On 10 Jun 2006 09:06:41 +0200, Jean-Marc Bourguet :

class Foo;
typedef int Foo;


Je ne vois pas quel est le problème avec ça. [...]

La vraie question est plutôt pourquoi

typedef class Foo Foo;


Je veux bien que ce soit une question intéressante, mais je ne vois
pas le rapport.


Avatar
Fabien LE LEZ
On Sat, 10 Jun 2006 11:19:10 +0200, (Fabien
CHÊNE):

Prenons cet exemple, sinon Foo est un type incomplet.
class Foo;
void f( int& ); // 1
void f( Foo& ); // 2


Là, tu déclares deux fonctions différentes.

Si tu rajoutes
typedef int Foo;

tout à coup, les deux fonctions différentes sont la même.


En fait, l'idée est que écrire

class Foo;

indique que "Foo" est un nouveau type.

Alors que écrire
typedef int Foo;

indique que "Foo" est un alias pour "int". À la portée près, c'est
quasiment la même chose que
#define Foo int

Les deux déclarations sont donc incompatibles.

Avatar
fabien.chene
Fabien LE LEZ writes:

On Sat, 10 Jun 2006 01:43:39 +0200, (Fabien
CHÊNE):

Une question qui me tarabuste, Qu'est-ce qui a motivé la norme a
déclarer ce code illégal ? (selon $7.1.3.3) :

class Foo;
typedef int Foo;


Je n'ai pas la version officielle, mais je suppose que ça vient du
fait qu'on peut écrire :

class Foo;

void f (int);
void f (Foo);


Prenons cet exemple, sinon Foo est un type incomplet.
class Foo;
void f( int& );
void f( Foo& );


Si tu écris "typedef int Foo;", tout à coup les deux fonctions "f()"
deviennent identiques :

void f (int);
void f (int);


ça, c'est légal. Par contre pour les définitions, effectivement, il y
aura un problème :

typedef int Foo;
void f( int& ) {}
void f( Foo& ) {} // double définition


--
Fab


Avatar
Fabien LE LEZ
On Sat, 10 Jun 2006 01:43:39 +0200, (Fabien
CHÊNE):

Je note aussi que le diagnostic
indiqué de «typedef int complex;» (suite à class complex { /*
... */};) est une redéfinition

(alors que typedef fait une déclaration).


typedef ne déclare rien, sinon une nouvelle orthographe pour un type.

Avatar
Fabien LE LEZ
On Sat, 10 Jun 2006 13:17:06 +0200, Fabien CHÊNE :

Considérons que ceci est légal :
class Foo;
typedef int Foo;

Il s'en suit qu'il y a deux déclarations identiques, ce qui n'est pas
encore génant.


Comment ça, pas gênant ?

Tu dis que Foo est un nouveau type, puis tu dis que "Foo" veut dire
"int".

Devant cette contradiction patente, le compilateur jette l'éponge.


C'est aussi absurde que d'écrire
char x; double x;

Avatar
fabien.chene
Fabien LE LEZ writes:

On Sat, 10 Jun 2006 11:19:10 +0200, (Fabien
CHÊNE):

Prenons cet exemple, sinon Foo est un type incomplet.
class Foo;
void f( int& ); // 1
void f( Foo& ); // 2


Là, tu déclares deux fonctions différentes.

Si tu rajoutes
typedef int Foo;

tout à coup, les deux fonctions différentes sont la même.


Considérons que ceci est légal :
class Foo;
typedef int Foo;

Il s'en suit qu'il y a deux déclarations identiques, ce qui n'est pas
encore génant. Si les deux fonctions f sont définis, le compilateur
diagnostiquera une double définition (*).
Est-ce génant ? On pourrait voir la définition de la fonction
f(int&){} comme une interdiction à Foo de nommer un int.

(*) sauf si les fonctions sont inline, et ont la même définition --
mais je crois qu'il n'y a que le front end d'EDG qui arrive à
diagnostiquer cela.

Ensuite, que se passe-t'il si (1) est spécifié inline et pas (2) ?
Si (2) est spécifié inline et pas (1) ?

ça devient tordu :-)

En fait, l'idée est que écrire

class Foo;

indique que "Foo" est un nouveau type.

Alors que écrire
typedef int Foo;

indique que "Foo" est un alias pour "int".

Les deux déclarations sont donc incompatibles.


Je ne sais pas si cette notion existe dans la norme. Si elle l'est,
alors le commentaire de §7.1.3.3 me parait de plus en plus bizarre.


--
Fab


Avatar
Fabien LE LEZ
class C;

void f (C&);
int f (int&);

typedef int C;
Avatar
fabien.chene
Fabien LE LEZ writes:

On Sat, 10 Jun 2006 13:17:06 +0200, Fabien CHÊNE :

Considérons que ceci est légal :
class Foo;
typedef int Foo;

Il s'en suit qu'il y a deux déclarations identiques, ce qui n'est pas
encore génant.


Comment ça, pas gênant ?

Tu dis que Foo est un nouveau type, puis tu dis que "Foo" veut dire
"int".

Devant cette contradiction patente, le compilateur jette l'éponge.


Désolé, je n'ai pas mis assez de contexte :

Je suppose que ceci est légal :
class Foo;
typedef int Foo;

Et je fais

void f( int& );
void f( Foo& );

//je défini Foo et les f plus tard.

Les déclarations identiques dont je parlais sont celles de f.

--
Fab


1 2 3