Was ist denn hier los?
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.
}
In Abschnitt 6.4.3 des Standards von 2003 wird erläutert, wie Variablen, die in einer Auswahlanweisungsbedingung deklariert sind, einen Bereich haben, der sich bis zum Ende der von der Bedingung gesteuerten Unteranweisungen erstreckt. Aber ich sehe nicht, wo es etwas darüber aussagt, dass die Deklaration nicht in Klammern gesetzt werden kann, und es sagt auch nichts über nur eine Deklaration pro Bedingung aus.
Diese Einschränkung ist selbst in Fällen ärgerlich, in denen nur eine Erklärung in der Bedingung erforderlich ist. Bedenken Sie.
bool a = false, b = true;
if(bool x = a || b)
{
}
Wenn ich den 'if "-Körperbereich eingeben möchte, wobei x auf false gesetzt ist, benötigt die Deklaration Klammern (da der Zuweisungsoperator eine niedrigere Priorität als das logische ODER hat), aber da Klammern nicht verwendet werden können, muss x außerhalb deklariert werden Der Körper verliert diese Deklaration an einen größeren Umfang als gewünscht. Offensichtlich ist dieses Beispiel trivial, aber ein realistischerer Fall wäre einer, bei dem a und b Funktionen sind, die Werte zurückgeben, die getestet werden müssen
Entspricht das, was ich tun möchte, nicht dem Standard, oder sprengt mein Compiler nur meine Bälle (VS2008)?
quelle
if
.if
ist keine Schleife, es ist eine Bedingung.while
sind die gleichen wie fürif
.if (int a = foo(), int b = bar(), a && b)
? Wenn der Kommaoperator nicht überladen ist, gibt der Standard an, dass die Ausdrücke von links nach rechts ausgewertet werden und der Ergebniswert der letzte Ausdruck ist. Es funktioniert mitfor
Schleifeninitialisierung, warum nicht hier?if
, und es scheint eine falsche Annahme zu sein.Antworten:
Ab C ++ 17 ist endlich möglich, was Sie versucht haben :
Beachten Sie die Verwendung von
;
von anstelle von,
, um die Deklaration und den tatsächlichen Zustand zu trennen.quelle
Ich denke, Sie haben das Problem bereits angedeutet. Was soll der Compiler mit diesem Code machen?
Der Operator "&&" ist ein logisches UND-Kurzschluss-UND. Das heißt, wenn sich der erste Teil
(1==0)
als falsch herausstellt, sollte der zweite Teil(bool a = false)
nicht bewertet werden, da bereits bekannt ist, dass die endgültige Antwort falsch sein wird. Wenn dies(bool a = false)
nicht ausgewertet wird, was ist dann mit dem später verwendeten Code zu tuna
? Würden wir die Variable einfach nicht initialisieren und undefiniert lassen? Würden wir es auf die Standardeinstellung initialisieren? Was wäre, wenn der Datentyp eine Klasse wäre und dies unerwünschte Nebenwirkungen hätte? Was wäre, wenn anstelle vonbool
Ihnen eine Klasse verwendet würde und sie keinen Standardkonstruktor hätte, sodass der Benutzer Parameter angeben muss - was machen wir dann?Hier ist ein weiteres Beispiel:
Die Einschränkung, die Sie gefunden haben, scheint völlig vernünftig zu sein - sie verhindert, dass solche Unklarheiten auftreten.
quelle
Der Zustand in einer
if
oderwhile
Anweisung kann entweder eine sein , die Expression oder eine einzelne variable Deklaration (mit Initialisierung).Ihr zweites und drittes Beispiel sind weder gültige Ausdrücke noch gültige Deklarationen, da eine Deklaration nicht Teil eines Ausdrucks sein kann. Es wäre zwar nützlich, Code wie in Ihrem dritten Beispiel schreiben zu können, es würde jedoch eine wesentliche Änderung der Sprachsyntax erforderlich sein.
Die Syntaxspezifikation in 6.4 / 1 gibt für die Bedingung Folgendes an:
Angabe einer einzelnen Erklärung ohne Klammern oder andere Verzierungen.
quelle
Wenn Sie Variablen in einem engeren Bereich einschließen möchten, können Sie immer zusätzliche verwenden
{ }
quelle
Der letzte Abschnitt funktioniert bereits, Sie müssen ihn nur etwas anders schreiben:
quelle
Hier ist eine hässliche Problemumgehung mithilfe einer Schleife (wenn beide Variablen Ganzzahlen sind):
Aber das wird andere Programmierer verwirren und es ist ziemlich schlechter Code, also nicht zu empfehlen.
Ein einfacher umschließender
{}
Block (wie bereits empfohlen) ist viel einfacher zu lesen:quelle
Eine Sache zu beachten ist auch, dass die Ausdrücke innerhalb des größeren if-Blocks
Es ist nicht unbedingt garantiert, dass sie von links nach rechts bewertet werden. Ein ziemlich subtiler Fehler, den ich damals hatte, hatte damit zu tun, dass der Compiler tatsächlich von rechts nach links statt von links nach rechts testete.
quelle
if(p && p->str && *p->str) ...
. Von rechts nach links wäre tödlich und nicht subtil gewesen. Mit anderen Betreibern - auch Zuordnung! - und Funktionsaufrufargumente Sie haben Recht, aber nicht mit den Kurzschlussoperatoren.Mit ein wenig Template-Magie können Sie das Problem umgehen, dass Sie nicht mehrere Variablen deklarieren können:
(Beachten Sie, dass dadurch die Kurzschlussauswertung verloren geht.)
quelle