Que se passe t-il ici?
if(int a = Func1())
{
// Works.
}
if((int a = Func1()))
{
// Fails to compile.
}
if((int a = Func1())
&& (int b = Func2()))
)
{
// Do stuff with a and b.
// This is what I'd really like to be able to do.
}
La section 6.4.3 de la norme 2003 explique comment les variables déclarées dans une condition d'énoncé de sélection ont une portée qui s'étend jusqu'à la fin des sous-instructions contrôlées par la condition. Mais je ne vois pas où cela dit quoi que ce soit sur le fait de ne pas pouvoir mettre de parenthèses autour de la déclaration, ni sur une seule déclaration par condition.
Cette limitation est ennuyeuse même dans les cas où une seule déclaration dans la condition est requise. Considère ceci.
bool a = false, b = true;
if(bool x = a || b)
{
}
Si je veux entrer la portée 'if' -body avec x défini sur false, la déclaration a besoin de parenthèses (puisque l'opérateur d'affectation a une priorité inférieure à l'OR logique), mais comme la parenthèse ne peut pas être utilisée, elle nécessite la déclaration de x à l'extérieur le corps, la fuite de cette déclaration à une portée plus grande que ce qui est souhaité. Évidemment, cet exemple est trivial mais un cas plus réaliste serait celui où a et b sont des fonctions renvoyant des valeurs qui doivent être testées
Est-ce que ce que je veux faire est non conforme à la norme, ou est-ce que mon compilateur ne fait que me casser les couilles (VS2008)?
if
.if
n'est pas une boucle, c'est un conditionnel.while
sont les mêmes que pourif
.if (int a = foo(), int b = bar(), a && b)
:? Si l'opérateur virgule n'est pas surchargé, la norme dit que les expressions sont évaluées de gauche à droite et la valeur du résultat est la dernière expression. Cela fonctionne avec l'for
initialisation des boucles, pourquoi pas ici?if
fonctionne, et cela semble être une mauvaise hypothèse.Réponses:
Depuis C ++ 17, ce que vous essayez de faire est enfin possible :
Notez l'utilisation de
;
au lieu de,
pour séparer la déclaration et la condition réelle.la source
Je pense que vous avez déjà fait allusion à la question. Que doit faire le compilateur avec ce code?
L'opérateur "&&" est un ET logique de court-circuit. Cela signifie que si la première partie
(1==0)
s'avère fausse, la deuxième partie(bool a = false)
ne doit pas être évaluée car on sait déjà que la réponse finale sera fausse. Si ce(bool a = false)
n'est pas évalué, que faire plus tard avec le code qui utilisea
? Ne devrions-nous tout simplement pas initialiser la variable et la laisser non définie? Pourrions-nous l'initialiser à la valeur par défaut? Et si le type de données était une classe et que cela avait des effets secondaires indésirables? Et si au lieu debool
vous utilisiez une classe et qu'elle n'avait pas de constructeur par défaut tel que l'utilisateur doit fournir des paramètres - que faisons-nous alors?Voici un autre exemple:
Il semble que la limitation que vous avez trouvée semble parfaitement raisonnable - elle empêche ce genre d'ambiguïtés de se produire.
la source
La condition dans une instruction
if
orwhile
peut être soit une expression , soit une déclaration de variable unique (avec initialisation).Vos deuxième et troisième exemples ne sont ni des expressions valides, ni des déclarations valides, car une déclaration ne peut pas faire partie d'une expression. S'il serait utile de pouvoir écrire du code comme votre troisième exemple, cela nécessiterait une modification significative de la syntaxe du langage.
La spécification de syntaxe en 6.4 / 1 donne ce qui suit pour la condition:
spécifiant une seule déclaration, sans parenthèses ni autres ornements.
la source
Si vous souhaitez inclure des variables dans une portée plus étroite, vous pouvez toujours utiliser des
{ }
la source
La dernière section fonctionne déjà, il vous suffit de l'écrire légèrement différemment:
la source
Voici une solution de contournement laide utilisant une boucle (si les deux variables sont des entiers):
Mais cela déroutera les autres programmeurs et c'est un code plutôt mauvais, donc déconseillé.
Un simple
{}
bloc englobant (comme déjà recommandé) est beaucoup plus facile à lire:la source
Une chose à noter est également que les expressions à l'intérieur du plus grand bloc if
ne sont pas nécessairement garantis d'être évalués de gauche à droite. Un bogue assez subtil que j'ai eu à l'époque était lié au fait que le compilateur testait en fait de droite à gauche au lieu de gauche à droite.
la source
if(p && p->str && *p->str) ...
. La droite-gauche aurait été mortelle et non subtile. Avec d'autres opérateurs - même affectation! - et les arguments d'appel de fonction vous avez raison, mais pas avec les opérateurs de court-circuit.Avec un peu de magie de modèle, vous pouvez en quelque sorte contourner le problème de ne pas pouvoir déclarer plusieurs variables:
(Notez que cela perd l'évaluation du court-circuit.)
la source