La implementación adecuada de XOR lógico manual depende de cuán estrechamente desee imitar el comportamiento general de otros operadores lógicos ( ||
y &&
) con su XOR. Hay dos cosas importantes sobre estos operadores: 1) garantizan la evaluación de cortocircuito, 2) introducen un punto de secuencia, 3) evalúan sus operandos solo una vez.
La evaluación XOR, como comprenderá, no se puede cortocircuitar ya que el resultado siempre depende de ambos operandos. Entonces 1 está fuera de cuestión. ¿Pero qué hay de 2? Si no le importan 2, entonces, con bool
valores normalizados (es decir , el operador) !=
hace el trabajo de XOR en términos del resultado. Y los operandos se pueden normalizar fácilmente con unario !
, si es necesario. Por lo tanto, !A != !B
implementa el XOR adecuado en ese sentido.
Pero si le importa el punto de secuencia adicional, ni la manera adecuada de implementar XOR es !=
ni bit a bit ^
. Una posible forma de hacer XOR (a, b) correctamente podría tener el siguiente aspecto
a ? !b : b
En realidad, esto es lo más cerca que puede llegar a hacer un XOR casero "similar" a ||
y &&
. Esto solo funcionará, por supuesto, si implementa su XOR como una macro. Una función no funcionará, ya que la secuencia no se aplicará a los argumentos de la función.
Sin embargo, alguien podría decir que la única razón de tener un punto de secuencia en cada uno &&
y ||
es apoyar la evaluación de cortocircuito, y por lo tanto, XOR no necesita uno. Esto tiene sentido, en realidad. Sin embargo, vale la pena considerar tener un XOR con un punto de secuencia en el medio. Por ejemplo, la siguiente expresión
++x > 1 && x < 5
tiene un comportamiento definido y un resultado específico en C / C ++ (con respecto a la secuencia al menos). Entonces, uno podría esperar razonablemente lo mismo de XOR lógico definido por el usuario , como en
XOR(++x > 1, x < 5)
mientras que un !=
XOR basado en no tiene esta propiedad.