¿Que está pasando aqui?
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 sección 6.4.3 de la norma de 2003 explica cómo las variables declaradas en una condición de declaración de selección tienen un alcance que se extiende hasta el final de las subdestaciones controladas por la condición. Pero no veo dónde dice nada sobre no poder poner paréntesis alrededor de la declaración, ni dice nada sobre una sola declaración por condición.
Esta limitación es molesta incluso en los casos en los que solo se requiere una declaración en la condición. Considera esto.
bool a = false, b = true;
if(bool x = a || b)
{
}
Si quiero ingresar el alcance 'if' -body con x establecido en falso, entonces la declaración necesita paréntesis (ya que el operador de asignación tiene menor precedencia que el OR lógico), pero dado que no se puede usar el paréntesis, requiere la declaración de x fuera el cuerpo, filtrando esa declaración a un alcance mayor del deseado. Obviamente, este ejemplo es trivial, pero un caso más realista sería aquel en el que a y b son funciones que devuelven valores que deben probarse
Entonces, ¿lo que quiero hacer es no conforme con el estándar, o mi compilador simplemente me está rompiendo las bolas (VS2008)?
fuente
if
.if
no es un bucle, es un condicional.while
son las mismas que paraif
.if (int a = foo(), int b = bar(), a && b)
? Si el operador de coma no está sobrecargado, el estándar dice que las expresiones se evalúan de izquierda a derecha y el valor del resultado es la última expresión. Funciona confor
inicialización de bucles, ¿por qué no aquí?if
funciona, y parece ser una suposición incorrecta.Respuestas:
A partir de C ++ 17, lo que estaba intentando hacer finalmente es posible :
Tenga en cuenta el uso de
;
en lugar de,
para separar la declaración y la condición real.fuente
Creo que ya insinuó el tema. ¿Qué debería hacer el compilador con este código?
El operador "&&" es un Y lógico de cortocircuito. Eso significa que si la primera parte
(1==0)
resulta ser falsa, entonces la segunda parte(bool a = false)
no debe evaluarse porque ya se sabe que la respuesta final será falsa. Si(bool a = false)
no se evalúa, ¿qué hacer más adelante con el código que se usaa
? ¿No inicializaríamos la variable y la dejaríamos sin definir? ¿Lo inicializaríamos con el valor predeterminado? ¿Qué pasa si el tipo de datos es una clase y hacer esto tiene efectos secundarios indeseables? ¿Qué pasa si en lugar debool
usar una clase y no tiene un constructor predeterminado de modo que el usuario debe proporcionar parámetros? ¿Qué hacemos entonces?Aquí hay otro ejemplo:
Parece que la limitación que ha encontrado parece perfectamente razonable: evita que sucedan este tipo de ambigüedades.
fuente
La condición en una declaración
if
owhile
puede ser una expresión o una declaración de variable única (con inicialización).Su segundo y tercer ejemplo no son expresiones válidas ni declaraciones válidas, ya que una declaración no puede formar parte de una expresión. Si bien sería útil poder escribir código como su tercer ejemplo, requeriría un cambio significativo en la sintaxis del lenguaje.
La especificación de sintaxis en 6.4 / 1 da lo siguiente para la condición:
especificando una sola declaración, sin paréntesis ni otros adornos.
fuente
Si desea incluir variables en un ámbito más estrecho, siempre puede utilizar adicionales
{ }
fuente
La última sección ya funciona, solo tienes que escribirla ligeramente diferente:
fuente
Aquí hay una solución fea usando un bucle (si ambas variables son enteros):
Pero esto confundirá a otros programadores y es un código bastante malo, por lo que no se recomienda.
Un
{}
bloque envolvente simple (como ya se recomendó) es mucho más fácil de leer:fuente
Una cosa a tener en cuenta, también es que las expresiones dentro del bloque if más grande
no están necesariamente garantizados para ser evaluados de izquierda a derecha. Un error bastante sutil que tuve en su día tenía que ver con el hecho de que el compilador en realidad estaba probando de derecha a izquierda en lugar de de izquierda a derecha.
fuente
if(p && p->str && *p->str) ...
. De derecha a izquierda habría sido mortal y no sutil. Con otros operadores, ¡incluso asignación! - y argumentos de llamada de función, tiene razón, pero no con los operadores de cortocircuito.Con un poco de magia de plantilla, puede evitar el problema de no poder declarar múltiples variables:
(Tenga en cuenta que esto pierde la evaluación de cortocircuito).
fuente