OVH Cloud OVH Cloud

evaluation avec "? "...un vestige de C ? ex: b1 ? "..." : "...."

23 réponses
Avatar
heinquoi
bjr,

j'ai dans un exemple un programme qui contient la ligne :
cout << endl << "le nombre 11 etait " << (b2 ? "TROUVE" : "NON TROUVE") <<
endl;

je intéresse surtout à (b2 ? "TROUVE" : "NON TROUVE")
est ce que opérateur évaluation "?" est un vestige de C ?

si je remplace ce morceau par
( if b2 "TROUVE" else "NON TROUVE") cela ne fonctionne pas, pourtant il
s'agit d'evaluation sur b2
hormis le fait que cette écriture lorsqu'elle est fréquente est obscure et
limite 'incantatoire' qu'elle est sont intérêt et pourquoi fonctionne t elle
ou un if ne fonctionne pas?
--
Cordialement,
Heinquoi

10 réponses

1 2 3
Avatar
Arnaud Debaene
heinquoi wrote:
bjr,

j'ai dans un exemple un programme qui contient la ligne :
cout << endl << "le nombre 11 etait " << (b2 ? "TROUVE" : "NON
TROUVE") << endl;

je intéresse surtout à (b2 ? "TROUVE" : "NON TROUVE")
est ce que opérateur évaluation "?" est un vestige de C ?
Un"vestige" non, mais ca fait effectivement partie du C, et donc aussi du

C++ par compatibilité.

La sémantique est :
test ? <expression_si_vrai> : <expression_si_faux>


si je remplace ce morceau par
( if b2 "TROUVE" else "NON TROUVE") cela ne fonctionne pas, pourtant
il s'agit d'evaluation sur b2
if (b2)

cout<<"TROUVE";
else
cout<<"NON TROUVE";

hormis le fait que cette écriture lorsqu'elle est fréquente est
obscure et limite 'incantatoire' qu'elle est sont intérêt et pourquoi
fonctionne t elle ou un if ne fonctionne pas?
Elle a a la fois l'avantage et le défaut d'être compact, ce qui selon les

gens (et les cas!) soit alourdit soit rend plus clair le code.

La différence sémantique avec un if est que l'expression ( ... ? ... : ...)
"renvoie" (le terme exact est "est évaluée comme") une valeur de type const
char* qui peut ête envoyé directement dans le flux. Par contre, l'expression
if ne "renvoie" rien en elle même.
Ton exemple est un cas ou je trouve, personnellement, que l'écriture "... ?
... : ..." est plus claire, mais c'est hautement discutable.

Arnaud

Avatar
Jean-Noël Mégoz
"heinquoi" <nospam* a écrit dans le message de
news:40d9e65e$0$15203$
bjr,

j'ai dans un exemple un programme qui contient la ligne :
cout << endl << "le nombre 11 etait " << (b2 ? "TROUVE" : "NON TROUVE")
<<

endl;

je intéresse surtout à (b2 ? "TROUVE" : "NON TROUVE")
est ce que opérateur évaluation "?" est un vestige de C ?

si je remplace ce morceau par
( if b2 "TROUVE" else "NON TROUVE") cela ne fonctionne pas, pourtant il


( if b2 "TROUVE" else "NON TROUVE") ne peut fonctionner car, d'une part, il
manque des parenthèses autour de b2, mais surtout, "TROUVE" et "NON TROUVE"
ne sont pas des *instructions* mais des *expressions* que le "?" renvoie ou
non selon le réultat du test...
L'opérateur "?" est peut être parfois dur à lire, quand les opérandes sont
longs par exemple... Mais pour ma part, c'est une écriture que j'aime
particulièrement et que je n'ai jamais eu de mal à lire. On le retouve
d'ailleurs dans d'autres langages (Prolog, notamment).

Quant à savoir si c'est un vestige du C ou si c'est du C++ pur jus, je
laisse les spécialistes de ce NG se prononcer !

Avatar
James Kanze
"heinquoi" <nospam* writes:

|> j'ai dans un exemple un programme qui contient la ligne :
|> cout << endl << "le nombre 11 etait " << (b2 ? "TROUVE" : "NON TROUVE") <<
|> endl;

|> je intéresse surtout à (b2 ? "TROUVE" : "NON TROUVE")
|> est ce que opérateur évaluation "?" est un vestige de C ?

Dans le même sens que l'opérateur de '+' est un vestige de C ?

|> si je remplace ce morceau par
|> ( if b2 "TROUVE" else "NON TROUVE") cela ne fonctionne pas, pourtant il
|> s'agit d'evaluation sur b2
|> hormis le fait que cette écriture lorsqu'elle est fréquente est
|> obscure et limite 'incantatoire' qu'elle est sont intérêt et
|> pourquoi fonctionne t elle ou un if ne fonctionne pas?

Parce qu'un if, c'est une instruction de contrôle de flux, et ?:, c'est
un opérateur. On aurait pu imaginer qu'le même syntaxe sert dans les
deux cas, mais ce n'est pas le cas en C ni en C++ (ni en Java, ni en
Objective C, ni en ...).

Je ne sais pas en ce qui concerne les autres, mais je m'en sers assez
librement. Si l'idée importante derrière un bout de code, c'est que la
valeur x soit affectée, et non qu'on a une condition, je le trouve plus
claire d'écrire :

x = ( condition
? a
: b ) ;

que :

if ( condition ) {
x = a ;
} else {
x = b ;
}

--
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
heinquoi
"Arnaud Debaene" a écrit dans le message de
news:40d9f54d$0$29373$
La sémantique est :
test ? <expression_si_vrai> : <expression_si_faux>


d'apres ton posts j'ai cru comprendre que ?: contrairement à if else avait
une valeur de retour "est évaluée comme".
ce qui pourrait faire
<type_expression> test ? <expression_si_vrai> : <expression_si_faux>
^^^^^^^^^^^^^^
valeur de 'retour'

Cela semble impliquer que <expression_si_vrai> et <expression_si_faux> soit
de meme type. Est ce tjrs le cas ?
ex: cout << (b1 ? 3 : 4.568); // si b1==true alors cout << int (3) sinon
cout << float (4.568)


Elle a a la fois l'avantage et le défaut d'être compact, ce qui selon les
gens (et les cas!) soit alourdit soit rend plus clair le code.

La différence sémantique avec un if est que l'expression ( ... ? ... :
...)

"renvoie" (le terme exact est "est évaluée comme") une valeur de type
const

char* qui peut ête envoyé directement dans le flux. Par contre,
l'expression

if ne "renvoie" rien en elle même.


Le type renvoyé est -il tjrs char* ( cf question precedente) ?

Ton exemple est un cas ou je trouve, personnellement, que l'écriture "...
?

... : ..." est plus claire, mais c'est hautement discutable.


d'accord avec toi, lorsque l'on en connaît le sens.

--
Cordialement,
Heinquoi

Avatar
Nicolas Vervelle
"heinquoi" <nospam* a écrit

Cela semble impliquer que <expression_si_vrai> et <expression_si_faux>
soit

de meme type. Est ce tjrs le cas ?
ex: cout << (b1 ? 3 : 4.568); // si b1==true alors cout << int (3) sinon
cout << float (4.568)


Elle a a la fois l'avantage et le défaut d'être compact, ce qui selon
les


gens (et les cas!) soit alourdit soit rend plus clair le code.

La différence sémantique avec un if est que l'expression ( ... ? ... :
...)

"renvoie" (le terme exact est "est évaluée comme") une valeur de type
const

char* qui peut ête envoyé directement dans le flux. Par contre,
l'expression

if ne "renvoie" rien en elle même.


Le type renvoyé est -il tjrs char* ( cf question precedente) ?



Le type renvoyé est le type de <expression_si_vrai>.
<expression_si_faux> doit être du même type qui <expression_si_vrai> (ou au
moins castable par le compilo)

Dans ton exemple, le résultat est "cout << 3" si vrai "cout << (int) 4.568"
si faux

Nico


Avatar
Pierre Maurette
James Kanze typa:

"heinquoi" <nospam* writes:

|> j'ai dans un exemple un programme qui contient la ligne :
|> cout << endl << "le nombre 11 etait " << (b2 ? "TROUVE" : "NON TROUVE") <<
|> endl;

|> je intéresse surtout à (b2 ? "TROUVE" : "NON TROUVE")
|> est ce que opérateur évaluation "?" est un vestige de C ?

Dans le même sens que l'opérateur de '+' est un vestige de C ?

|> si je remplace ce morceau par
|> ( if b2 "TROUVE" else "NON TROUVE") cela ne fonctionne pas, pourtant il
|> s'agit d'evaluation sur b2
|> hormis le fait que cette écriture lorsqu'elle est fréquente est
|> obscure et limite 'incantatoire' qu'elle est sont intérêt et
|> pourquoi fonctionne t elle ou un if ne fonctionne pas?

Parce qu'un if, c'est une instruction de contrôle de flux, et ?:, c'est
un opérateur. On aurait pu imaginer qu'le même syntaxe sert dans les
deux cas, mais ce n'est pas le cas en C ni en C++ (ni en Java, ni en
Objective C, ni en ...).

Je ne sais pas en ce qui concerne les autres, mais je m'en sers assez
librement. Si l'idée importante derrière un bout de code, c'est que la
valeur x soit affectée, et non qu'on a une condition, je le trouve plus
claire d'écrire :

x = ( condition
? a
: b ) ;

que :

if ( condition ) {
x = a ;
} else {
x = b ;
}
Et si c'est:


int x = (condition ? a : b);

il faudrait faire:

int x;
if(condition)
{
x = a;
}
else
{
x = b;
}

Ça va plus loin, l'opérateur ? pouvant s'utiliser à la place d'une
rvalue (éventuellement temporaire), on arrive à des écritures à la
fois plus compactes et pour moi plus lisibles :
y = fonct(10, (condition ? a : b));

ou l'exemple de la question de départ:

std::cout << (condition ? "VRAI" : "FAUX") << std::endl;

En revanche, et bien que ce soit possible semble-t-il, remplacer un if
par un ? me paraît non naturel et à éviter :

(condition ? std::cout<<100 : std::cout<<200); //NON

Je veux dire par là que si le but est l'évaluation et non
l'affectation, le if() est LA solution.
--
Pierre

Avatar
Vincent Guichard
Le type renvoyé est le type de <expression_si_vrai>.
<expression_si_faux> doit être du même type qui <expression_si_vrai> (ou au
moins castable par le compilo)


Je sais pas pour la norme C++, mais dans le cas de la norme C, ce n'est
pas vrai (ou alors, j'ai mal interprété la norme...)

§6.5.15

5 If both the second and third operands have arithmetic type, the result
type that would be determined by the usual arithmetic conversions, were
they applied to those two operands, is the type of the result. If both
the operands have structure or union type, the result has that type. If
both operands have void type, the result has void type.

En tous cas, sur mon compilateur,
std::cout<<(0?3:4.567);
retourne 4.567 et non pas 4 (comme ce serai le cas avec une conversion
en int)

Vincent Guichard

Avatar
Fabien LE LEZ
On 23 Jun 2004 23:44:54 +0200, James Kanze :

Dans le même sens que l'opérateur de '+' est un vestige de C ?


Voire un vestige de B, voire BCPL, voire un langage plus ancien encore
qui m'aurait échappé ? ;-)


--
schtroumpf schtroumpf

Avatar
Fabien LE LEZ
On 23 Jun 2004 23:44:54 +0200, James Kanze :

Si l'idée importante derrière un bout de code, c'est que la
valeur x soit affectée, et non qu'on a une condition, je le trouve plus
claire d'écrire :

x = ( condition
? a
: b ) ;


J'aimerais savoir ce que tu penses de :

ifstream fichier (condition ? "input1.txt" : "input2.txt");

Je précise ma question : le fait de se passer d'une variable
"nom_de_fichier" (ce qui est rendu possible par le fait qu'on utilise
"?:" et pas "if") est-il (d'après toi) un élément de clarification ou
d'obfuscation ?


--
schtroumpf schtroumpf

Avatar
kanze
"Nicolas Vervelle" wrote in message
news:<40da65be$0$317$...
"heinquoi" <nospam* a écrit

Cela semble impliquer que <expression_si_vrai> et
<expression_si_faux> soit de meme type. Est ce tjrs le cas ?

ex: cout << (b1 ? 3 : 4.568); // si b1==true alors cout << int (3) sinon
cout << float (4.568)

Elle a a la fois l'avantage et le défaut d'être compact, ce qui
selon les gens (et les cas!) soit alourdit soit rend plus clair le
code.

La différence sémantique avec un if est que l'expression ( ... ?
... : ...) "renvoie" (le terme exact est "est évaluée comme") une
valeur de type const char* qui peut ête envoyé directement dans le
flux. Par contre, l'expression if ne "renvoie" rien en elle même.


Le type renvoyé est -il tjrs char* ( cf question precedente) ?


Le type renvoyé est le type de <expression_si_vrai>.
<expression_si_faux> doit être du même type qui <expression_si_vrai>
(ou au moins castable par le compilo)


Les règles sont bien plus compliquées que ça. Ni l'une ni l'autre des
expressions n'est privilégées, et les compilateur essaie de trouver un
type commun. Mais on limite le champs de ses recherches, quand même. En
gros :

- D'abord, il y a certaines conversions « standard » qui sont faites
systèmatiquement sur les deux types -- du genre tableau en pointeur.

- Des conversions arithmétiques habituelles peuvent être appliquées
aux deux côtés, si nécessaire.

- Si une des expressions donne un pointeur, et l'autre est une
constante integrale de valeur 0, la constante integrale est
convertie en pointeur nul.

- Si les types des deux expressions sont tous les deux des pointeurs
ou des références à des classes, et une des classes est une classe
de base de l'autre, le pointeur au type dérivé est converti en
pointeur au type de base.

- Il y a le cas spécial où une des expressions est une expression de
throw (qui a le type void) -- le type final est le type de l'autre
expression (qui serait évidemment le seul qui pourrait servir comme
résultat).

Il y a d'autres cas aussi, mais je crois qu'ils servent moins souvent.

Il y a un cas dont l'absense me frustre de temps en temps : si les types
des deux expressions sont des pointeurs à des classes, et les deux
classes ont une classe de base en commun, ça ne marche pas. Donc, des
choses comme :

Base* pb = condition ? new Derived1 : new Derived2 ;

ne marche pas ; il faut explicitement convertir au moins un des
expressions en type Base*. L'une ou l'autre (ou les deux), ça ne fait
rien.

Dans ton exemple, le résultat est "cout << 3" si vrai "cout << (int) 4.568"
si faux


Dans son exemple, le cout était en dehors de l'expression
conditionnelle. Et le type de l'expression conditionnelle, c'était bien
double, et non int, c-à-d que son expression totale était l'équivalent
de :

cout << (b1 ? static_cast< double >( 3 ) : 4.568) ;

(C'est le deuxième point cité ci-dessus : les conversions arithmétiques
habituelles.) Dans son premier exemple, il y avait aussi des
conversions, puisque le type de la première expression était char
const[7], et celui de la deuxième char const[11]. Ici, c'est le premier
point qui s'applique ; on verrait bien la différence en faisant :

sizeof( b2 ? "TROUVE" : "NON TROUVE" )

(qui ne vaut ni sizeof( "TROUVE" ) ni sizeof( "NON TROUVE" ), sauf cas
accidentel).

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



1 2 3