Pregunta

Lo que realmente quiero es un || = operador.

old_value = old_value || possible_new_value;
old_value ||= possible_new_value;

La segunda línea es un error de compilación (c ++ no tiene || = operador).

¿Cuáles son mis otras opciones?

old_value += possible_new_value;
old_value |= possible_new_value;

Mientras estoy en el tema ¿cómo se comportan bool con otros operadores booleanos no?

-
-=
&
&=
...

Puedo verificar estos empíricamente, pero estoy más interesado en lo que dice la norma.

¿Fue útil?

Solución

Según 4,7 (conversiones integral), párrafo 4, "Si el tipo de destino es bool, ver 4.12. Si el tipo de fuente es bool, el valor false se convierte en cero y el true valor se convierte a uno". En 4.12, "An rvalue de la aritmética, enumeración, puntero, o puntero a tipo de miembro se puede convertir en un valor p de tipo bool un valor cero, el valor de puntero nulo, o el valor puntero miembro nulo se convierte en false;. Cualquier otro valor se convertido a true ".

En un contexto en operandos bool no están permitidos pero operandos integrales son, la bool se convertirá en un tipo integral. Cuando el resultado entero se almacena en una variable bool, se convierte en bool.

Por lo tanto, usted será capaz de utilizar + y * como booleano OR y AND, y se puede usar | y también. Usted no puede salirse con la mezcla de ellos, como (+ Bool1 Bool2) y bool3 rendirá false si las tres variables son true. ((1 + 1) y 1 es 2 y 1, que es 0, o falsa.)

Recuerde que | y || no funcionan de forma idéntica incluso aquí. | evaluará ambos lados, y luego evaluar el nivel de bits o. || evaluará el primer operando, entonces sólo si era falsa evaluará el segundo.

No voy a discutir las cuestiones estilísticas aquí, pero si lo hiciera nada por el estilo estaría seguro de hacer comentarios para que la gente sabía lo que estaba haciendo y por qué.

Otros consejos

El sayeth estándar:

4.5-4 "Promociones Integrales"

  

Un valor p de tipo bool puede ser   convertido a un valor p de tipo int,   con falso y verdadero ser cero   convirtiéndose en uno.

5.17-7 "Operadores de asignación"

  

El comportamiento de una expresión de la   formar E1 = E2 op es equivalente a E1 =   E1 op E2 E1 excepto que se evalúa   sólo una vez. En + = y - =, E1 deberá   o bien tienen tipo aritmético o ser una   puntero a una posiblemente cvqualified   completamente definido tipo de objeto. En todo   otros casos, E1 tendrán aritmética   tipo.

4,12-1 "booleanas" Conversiones

  

Un valor p de la aritmética, la enumeración,   puntero, o puntero a tipo de miembro puede   ser convertido a un valor p de tipo   bool. Un valor cero, puntero nulo   valor o valor de puntero miembro nula es   convertido a false; cualquier otro valor es   convertido en true.

Así que esto significa que

b1 += b2

Donde b1 y b2 son boolean será equivalente a

b1 = b1 + b2

Y b1 y b2 se promoverá a 0/1 enteros, y luego se convierte de nuevo a booleano en la regla que otra cosa que no sea 0 es verdadera.

Así es la tabla de verdad

            true   false
true     true   true
false    true   false

so + = de hecho funciona como || = de acuerdo con la norma. Sin embargo, esto probablemente va a ser confuso otros programadores, lo que evitaría que sigue.

Podría usted sólo tiene que utilizar el operador ternario?

  

old_value = !old_value ? possible_new_value : old_value;

No utilice |= y &= con Bools. Pueden trabajar la mayor parte del tiempo, pero sigue siendo malo. Por lo general, el tipo bool es sólo un int glorificado o carbón. En el código anterior que he trabajado con, BOOL es sólo typedef'd a int o carbón. En estos casos, se puede obtener la respuesta equivocada si se han manipulado de alguna manera los bits (Por ejemplo, 1&2 es 0 (falso)). Y no estoy seguro, pero creo que el resultado de operadores de bits va a ser un entero, incluso para Bools.

if (!old_value)
    old_value = possible_new_value;

Este es un equivalente directo de la condición original. Podría generar código más simple ya que no siempre va a asignar a old_value -. Pero yo no esperaría que la diferencia de rendimiento que sea fácil de medir en un programa grande

Una diferencia es que los operadores lógicos tales como || garantizar el orden de evaluación y proporcionar un cortocircuito, donde los operadores bit a bit y aritméticas no lo hacen.

Creo que el compilador tratará los operadores no lógicos mediante la conversión de los Bools a valores numéricos (0, 1) aplicando el operador y la conversión hacia atrás. Estas conversiones se definen estrictamente por la norma, por ejemplo:.

  

Un valor p de la aritmética, enumeración, puntero, o puntero a tipo de miembro se puede convertir en un valor p de tipo bool. Un valor cero, el valor de puntero nulo, o el valor de puntero nulo miembro se convierte en falsa cualquier otro valor se convierte en verdadera.

Nasty macro hackery:

#define UPDATE(x) x = x

UPDATE(old_value) || possible_new_value;

Pero no recomiendo esto en absoluto. Las macros de este tipo son una muy mala idea por varias razones.

Una función más sano, pero sin el cortocircuitos:

bool set_or(bool &old, bool value) {
  return (old = old || value);
}

...

bool v = false;
set_or(v, true);

Creo que la norma define explícitamente verdadero y falso como 1 y 0, por lo que puede utilizar con seguridad operadores de bits en los valores bool. Otros tipos que pueden ser tratadas de manera implícita como Bools en otro contexto se deben convertir de forma explícita para que esto funcione de forma fiable.

He visto el compilador de Microsoft genera un aviso fea cada vez que lo haga, ya que cree que hay un peligro en convertir implícitamente el resultado int volver a bool.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top