Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Quel opérateur de cast ?

23 réponses
Avatar
meow
Hello,

Plutot que de relire pour la dixi=E8me fois le 30 chapitres et
tutoriaux sur les cast, auxquels je n'ai toujours rien pann=E9, j'ai
d=E9cid=E9 de changer de technique : je pose la question sur un cas
concret et j'affinerai ma connaissance au fur et =E0 mesure. Dans
l'extrait de code :

Volumetric* create(Kind k){
Volumetric* v;
switch (k) {
case RAW:
v =3Dnew RawVolumetric;break;
default:
v =3DNULL;break;
}
return v;
}

il y a un v=3DNULL qui ne me semble pas tr=E8s joli. Il faudrait tout du
moins que je le caste en Volumetric*, non ? Et si oui, quel operateur
dois-je utiliser ?

--Ben

10 réponses

1 2 3
Avatar
Loïc Joly

Au fait, question subsidiaire : j'ai toujours entendu parler de
"single entry, single exit", et j'avoue que je ne saisis pas bien le
"single entry" : on peut entrer dans une fonction par un autre endroit
que le début ?


Dans certains langages, on peut. En vieux basic, avec Gosub, on peut
entrer où on veut dans une "fonction".

--
Loïc

Avatar
Sylvain
Loïc Joly wrote on 14/07/2006 01:18:

Dans certains langages, on peut. En vieux basic, avec Gosub, on peut
entrer où on veut dans une "fonction".


en fortran courant également et surement en C à coup de 'setjmp'.

Sylvain.

Avatar
Jean-Marc Bourguet
Fabien LE LEZ writes:

On Thu, 13 Jul 2006 22:47:38 +0200, James Kanze :

(Il y a eu
une discussion récemment dans le groupe anglophone, du fait que
« (0, 0) » n'est pas, malgré les apparences, une expression
constante entière.)


Tiens ? Qu'est-ce donc, alors ?


C'est une expression entière non constante. Tu ne peux pas
faire quelque chose comme:

int i[(0, 5)];

(Note bien aussi que si tu fais un « reinterpret_cast
» d'une variable de type int, dont la valeur est 0,
ce n'est pas garantie que tu ais le même résultat que
si tu as une expression constante qui vaut 0.)


Si je ne m'abuse, on peut généraliser : si tu fais un
"reinterpret_cast<T*>(i)", où "i" est un nombre, tu n'as
absolument aucune garantie...


La valeur 0 est la seule pour laquelle il soit sensé de
faire une différence entre expression constante et non
constante lors de la détermination du résultat.

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
Jean-Marc Bourguet
Fabien LE LEZ writes:

Au fait, question subsidiaire : j'ai toujours entendu parler de
"single entry, single exit", et j'avoue que je ne saisis pas bien le
"single entry" : on peut entrer dans une fonction par un autre endroit
que le début ?


C'est naturellement possible en assembleur. Ce l'a été dans
certains langages (FORTRAN, BLISS, peut-être BCPL).

Mais l'expression SESE concerne n'importe quel bloc
structurel. Et avoir plusieurs entrées pour en bloc en C++,
c'est possible en jouant avec goto (ou switch, voir duff
device).

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
Jean-Marc Bourguet
Fabien LE LEZ writes:

Au fait, question subsidiaire : j'ai toujours entendu parler de
"single entry, single exit", et j'avoue que je ne saisis pas bien le
"single entry" : on peut entrer dans une fonction par un autre endroit
que le début ?


C'est naturellement possible en assembleur. Ce l'a été dans
certains langages (FORTRAN, BLISS, peut-être BCPL).

Mais l'expression SESE concerne n'importe quel bloc
structurel. Et avoir plusieurs entrées pour un bloc en C++,
c'est possible en jouant avec goto (ou switch, voir duff
device).

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 Fri, 14 Jul 2006 10:09:37 +0200, Jean-Marc Bourguet
:

C'est une expression entière non constante. Tu ne peux pas
faire quelque chose comme:

int i[(0, 5)];


Ah, OK. J'imagine que c'est parce que c'est considéré comme la valeur
de retour d'une fonction ? (En l'occurence, 'operator,')

Avatar
Gabriel Dos Reis
Fabien LE LEZ writes:

| On Fri, 14 Jul 2006 10:09:37 +0200, Jean-Marc Bourguet
| :
|
| >C'est une expression entière non constante. Tu ne peux pas
| >faire quelque chose comme:
| >
| >int i[(0, 5)];
|
| Ah, OK. J'imagine que c'est parce que c'est considéré comme la valeur
| de retour d'une fonction ? (En l'occurence, 'operator,')

Je ne sais pas. C'est une règle que C++ a hérité de C. Si on doit
considérer « operator, » comme une fonction, qu'en est-il de
« operator+ » dans « 5 + 2 » ?

À la dernière réunion de Berlin, j'ai tenté de changer cette règle
(dans notre proposition d'expression constante généralisée) mais je me
suis vite rendu compte que cela change la sémantique de programmes
C++ actuels. Donc j'ai fait machine arrière. La question de savoir si
ces programmes sont suffisamment importants est un autre débat, un
débat dans lequel je ne voudrais pas m'engager :-)

Par exemple,

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


f((5, 0)); // OK : appelle "void f(int)"
f(0); // ERROR : ambiguité

-- Gaby
Avatar
James Kanze
Fabien LE LEZ wrote:
On Thu, 13 Jul 2006 22:56:53 +0200, James Kanze :
mais certains n'aiment pas les fonctions avec plusieurs
"return" ; j'avoue ne pas trop savoir pourquoi.




Parce qu'on aime pouvoir raisonner de façon rigueureuse sur
la correction du code.



Ce qui ne veut pas dire qu'on n'admet pas d'exception.



Justement, parlons-en, des exceptions... (Au sens C++, pour le coup.)


Le mécanisme des exceptions fait que de toutes façons, dans la plupart
des fonctions non triviales, il y a une possibilité pour qu'on sorte
de la fonction par un autre endroit que le "return".


C'est pourquoi on ne s'en sert que pour des erreurs critiques,
qu'on ne peut pas traiter localement. Une exception équivaut un
abort, mais à un niveau plus bas.

Et qu'en cas d'exception, on a abandonné l'algorithme. Il n'y a
donc plus à raisonner sur sa correction.

Par conséquent, la durée de vie des objets locaux, et la
validité des objets "externes", ne doit pas se baser sur le
principe SESE.


D'autre part, il me semble que le compilateur se charge de
s'assurer que quelque soit le cheminement dans la fonction,
une valeur de retour est bien renvoyée.


Du coup, je ne vois pas bien ce que se forcer à mettre un seul
"return", avec toutes les circonvolutions que ça amène
parfois, apporte réellement.


Il permet de raisonner sur les invariantes de la fonction.

Au fait, question subsidiaire : j'ai toujours entendu parler
de "single entry, single exit", et j'avoue que je ne saisis
pas bien le "single entry" : on peut entrer dans une fonction
par un autre endroit que le début ? Ou l'expression est comme
ça par pur amour de la symétrie ?


Il ne s'agit pas que de fonctions, mais de blocs de code en
général. Donc, par exemple, pas de goto au milieu d'une boucle.
(Mais en fait, je ne connais personne de sérieux qui met en
question le single entry. Du moment que tu ne sais pas d'où tu
es arrivé, c'est vraiment impossible de raisonner sur le code.)

--
James Kanze
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
James Kanze
Loïc Joly wrote:

Au fait, question subsidiaire : j'ai toujours entendu parler
de "single entry, single exit", et j'avoue que je ne saisis
pas bien le "single entry" : on peut entrer dans une fonction
par un autre endroit que le début ?



Dans certains langages, on peut. En vieux basic, avec Gosub,
on peut entrer où on veut dans une "fonction".


En Cobol aussi ; en fait, c'est dans le PERFORM où tu spécifies
le premier bloc et le dernier bloc du « sous-programme ».

En Fortran, c'était même formalisé : il y a un mot clé spécial,
« entry », pour spécifier les points d'éntrée supplémentaire.
C'était prévu en C, mais jamais implémenté.

Mais le « single entry, single exit » s'applique à n'importe
quel bloc de code. Donc :

if ( x )
goto toto ;
while ( y ) {
f() ;
toto :
g() ;
}

viole le principe, parce qu'on entre dans le bloc g() depuis
deux points différents.

Note que s'il y a beaucoup de choses à criticiser avec goto, le
problème le plus vicieux, c'est bien qu'un goto implique un
comefrom inconnu. Du moment qu'on peut arriver de n'importe où,
qu'est-ce qu'on peut dire des préconditions ?

--
James Kanze
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
James Kanze
Fabien LE LEZ wrote:
On Thu, 13 Jul 2006 22:47:38 +0200, James Kanze :


(Il y a eu
une discussion récemment dans le groupe anglophone, du fait que
« (0, 0) » n'est pas, malgré les apparences, une expression
constante entière.)



Tiens ? Qu'est-ce donc, alors ?


Une expression. En ce qui concerne le langage et le compilateur,
il n'y a rien de différent que si on avait écrit (i, i).

(Note bien aussi que si tu fais un « reinterpret_cast »
d'une variable de type int, dont la valeur est 0, ce
n'est pas garantie que tu ais le même résultat que si tu
as une expression constante qui vaut 0.)



Si je ne m'abuse, on peut généraliser : si tu fais un
"reinterpret_cast<T*>(i)", où "i" est un nombre, tu n'as
absolument aucune garantie...


Si. Tu as le garantie que si i est le résultat d'un
reinterpret_cast d'un T*, tu te rétrouves avec la même valeur
(ou, si le type d'i n'était pas assez grand, que tu as eu une
erreur de compilation). Tu as aussi une garantie que :

int i = 1 ;
reinterpret_cast< T* >( i ) == reinterpret_cast< T* >( 1 ) ;

C'est précisement cette garantie qui manque avec 0.

Sans être une garantie, tu as aussi : « [the mapping function]
is intended to be unsurprising to those who know the addressing
structure of the underlying machine ». Une telle expression
d'intention crée des expectations en ce qui concerne la qualité
de l'implémentation.

Ce qui importe ici, c'est que la sémantique de
« reinterpret_cast<T*>( 0 ) » n'est pas la même que celle de
« reinterpret_cast<T*>( i ) », où i vaut 0. La première doit
donner un pointeur nul. La séconde doit donner quelque chose qui
ne surprendra pas quelqu'un qui connaît l'architecture de la
machine. Dans le cas d'une architecture où 0 est une adresse
bien valide, et que la représentation du pointeur nul n'est pas
0, je m'attendrais bien à un résultat différent.

J'avoue ne pas comprendre la rationale ici. Le but de
reinterpret_cast, c'est des conversions bien propre à
l'architecture, non de créer des pointeurs nuls (qui se fait
très bien avec static_cast). Que le C ait cette anomalie, je
comprends bien, parce qu'il n'a qu'un seul type de cast. Mais en
C++, si j'écris (int*)0, c'est un static_cast, et si j'écris
(int*)i, c'est un reinterpret_cast, et je ne vois pas la
nécessité, ni même l'intérêt, de l'anomalie dans la
spécification de reinterpret_cast.

(Mais ça fait deux choses ici dont je ne comprends pas la
rationale. Parce que comme toi, je trouve que « (0, 0) »
ressemble bien à une expression constante, quoiqu'en dit la
norme.)

--
James Kanze
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


1 2 3