6

Bjarne sugiere usar la condición en ifs como restricción de ámbito. En particular este ejemplo.double as true/false

if (double d = fd() ) { 
    // d in scope here... 
} 

Soy curioso cómo interpretar la declaración en un sentido verdadero/falso.

  1. Es una declaración
  2. Es un doble.

Edit: Está en 6.3.2.1 El lenguaje de programación C++ como una recomendación.

Edit2: templatetypedefs sugerencia de punteros, en particular con moldes dinámicos, podría dar una idea de la sugerencia de Bjarnes.

SteveJessop me dice: - Una condición no es una expresión, también puede ser una declaración, el valor utilizado, es el valor que se evalúa.

+1

La respuesta a [esta pregunta] (http://stackoverflow.com/q/9833790/636019) responderá a su pregunta también. – ildjarn

+1

Acabo de leer la sección de la que estás hablando y salí con la sensación de que la discusión era más sobre usarla como restricción de alcance (y obtener el beneficio adicional del código compacto) y no tenía mucho que ver con el tipo de datos específico Creo que pudo haber reemplazado 'double' con' int' y todavía consiguió su mensaje intencionado. Sin embargo, así es como lo leí. – jedwards

+0

@jedwards Sí, pero el uso del doble está pidiendo una respuesta. Una declaración int es todavía una anomalía que merece una respuesta. –

Respuesta

6

El código que está viendo es una técnica especializada para declarar variables en las declaraciones if. Usted comúnmente ve algo como esto:

if (T* ptr = function()) { 
    /* ptr is non-NULL, do something with it here */ 
} else { 
    /* ptr is NULL, and moreover is out of scope and can't be used here. */ 
} 

Un caso particularmente común es el uso de dynamic_cast aquí:

if (Derived* dPtr = dynamic_cast<Derived*>(basePtr)) { 
    /* basePtr really points at a Derived, so use dPtr as a pointer to it. */ 
} else { 
    /* basePtr doesn't point at a Derived, but we can't use dPtr here anyway. */ 
} 

lo que está sucediendo en su caso es que usted está declarando una double dentro de la instrucción if. C++ interpreta automáticamente cualquier valor distinto de cero como true y cualquier valor cero como false. Lo que significa este código es "declare d y configúrelo como fd(). Si no es cero, ejecute la instrucción if".

Dicho esto, esta es una muy mala idea porque double s están sujetos a todo tipo de errores de redondeo que impiden que sean 0 en la mayoría de los casos. Es casi seguro que este código ejecutará el cuerpo de la declaración if, a menos que function se comporte muy bien.

Espero que esto ayude!

+0

@ CapitánGiraffe, podrías marcarlo como la respuesta ... – bames53

+0

@ bames53 Es casi como si leyeras mi mente. Todavía me gustaría un comentario sobre la inconsistencia de bool b = double d = fd(); sin embargo, pero esa podría ser otra pregunta. –

+1

"y además está fuera del alcance y no se puede usar aquí" - está * en * alcance en la cláusula 'else', pero por supuesto con punteros y punteros inteligentes no hay mucho que pueda hacer con una variable que prueba falso, por lo que normalmente no lo usas allí. Podría asignar otro valor, supongo. Si lo usó con un tipo definido por el usuario que tiene un idioma bool seguro para indicar "falla", entonces quizás en la cláusula 'else' interrogaría al objeto * por qué *" falló ". –

2

la instrucción if se basa en el valor asignado a la variable en la expresión de asignación. Si el doble se evalúa a cualquier cosa menos a 0.0, ejecutará el código dentro.

Tenga en cuenta que no debe comparar dobles con cero, pero en general funciona en mi experiencia.

Básicamente, no deberías hacer esto.

Los otros contribuidores a este tema han encontrado que esta expresión se usa para excluir el caso cero para evitar una división por cero. Eso es definitivamente inteligente y tal situación legitima este uso en lo que a mí respecta (pero considere la confusión que tal código puede causar).

+0

Bjarne me dice que esto es un modismo. Solo digo. 6.3.2.1 El lenguaje de programación C++. –

+2

Puede estarse refiriendo al hecho de que la doble 'd' está * en el alcance * dentro (y solo dentro) del bloque' if'. Lo cual no es necesariamente obvio. Mi punto es que a menudo no hay una buena razón para lanzar un doble al bool. Por qué una variable de tipo 'int' no se usa, no tengo idea. (ESO es un modismo muy común) –

+2

¿Por qué demonios no se supone que debes comparar dobles con cero? Funciona perfectamente bien y tiene un comportamiento bien definido. La matemática de punto flotante puede ser sorprendente, pero no es vudú y no está bien atendido por ese tipo de consejo. –

2

Es a la vez una declaración y un doble. Esto es bastante equivalente a

{ 
    double d = fd(); 
    if (d) { 
    } 
} 

Sin embargo, este patrón es la pena el pequeño sintaxis adicional para simplificar, ya que es bastante útil y común.Además, la transformación es menos obvia una vez que comienzas a agregar cláusulas else, ya que d está fuera del alcance de ellas.

También, como otros han señalado, es útil, en general, pero los tipos de PF en específica tener algunos problemas cuando se compara con 0.

+0

Esta es la primera respuesta con la que estoy contento. Esta sintaxis está por todos lados. – jedwards

+0

Mi pregunta también direcciones does bool b = double d = 0.0; –

+1

¿Estás seguro de que 'd' está fuera del alcance de las ramas' else'? – jedwards

5

En el ejemplo Stroustrup da, el código en el bloque de if divide un valor por d:

if (double d = prim(true)) { 
    left /= d; 
    break; 
} 

la división por 0 es un comportamiento indefinido, por lo que tiene sentido en este caso para probar d contra el valor 0.0 antes de dividirse. Poner la definición en la condición es una manera conveniente de hacer esto, por las razones que Stroustrup afirma.

Su código no da ninguna razón por la cual el valor 0.0 sería especial, y por lo tanto no está claro por qué alguien combinaría la definición de d con esa prueba. Solo use el patrón de Stroustrup cuando los valores "falsos" del tipo que está definiendo necesiten ser tratados especialmente. De lo contrario, simplemente haga esto:

{ 
    double d = fd(); 
    // d in scope here... 
} 
+0

Acabo de leer la sección y no hice la conexión, pensé que era un ejemplo de usar y tirar - buena atrapada. ¿Alguna idea sobre el 'break '? – jedwards

+0

@jedwards: más allá de lo obvio (se rompe de algún bucle o interruptor circundante, no se muestra en este fragmento de código) No lo sé. ¿Tal vez este fragmento de código está tomado de algún código usado en otra parte del capítulo/libro? Para el caso, tampoco sé lo que hace la función 'prim'. –

+0

Aww, Esperaba que fuera algún truco que me intrique como algunas de estas gemas (http://www2.research.att.com/~bs/bs_faq.html). ¡Gracias! – jedwards