A implementação manual correta do XOR lógico depende de quão próximo você deseja imitar o comportamento geral de outros operadores lógicos ( ||
e &&
) com o seu XOR. Há duas coisas importantes sobre esses operadores: 1) garantem a avaliação de curto-circuito, 2) introduzem um ponto de sequência, 3) avaliam seus operandos apenas uma vez.
A avaliação do XOR, como você entende, não pode ter um curto-circuito, pois o resultado sempre depende dos dois operandos. Então, 1 está fora de questão. Mas e quanto a 2? Se você não se importa com 2, o bool
operador com valores normalizados (ou seja ) !=
realiza o trabalho de XOR em termos do resultado. E os operandos podem ser facilmente normalizados com unário !
, se necessário. Assim, !A != !B
implementa o XOR apropriado a esse respeito.
Mas se você se importa com o ponto extra de sequência, !=
nem a bit ^
a bit é a maneira correta de implementar o XOR. Uma maneira possível de executar o XOR (a, b) corretamente pode ser a seguinte
a ? !b : b
Este é realmente o mais perto que você pode começar a fazer um XOR caseiro "similar" à ||
e &&
. Obviamente, isso só funcionará se você implementar seu XOR como uma macro. Uma função não funciona, pois o seqüenciamento não se aplica aos argumentos da função.
Alguém pode dizer, porém, que a única razão de ter um ponto de sequência em cada um &&
e ||
é apoiar a avaliação em curto-circuito e, portanto, o XOR não precisa de um. Isso faz sentido, na verdade. No entanto, vale a pena considerar ter um XOR com um ponto de sequência no meio. Por exemplo, a seguinte expressão
++x > 1 && x < 5
definiu comportamento e resultado específico em C / C ++ (com relação ao seqüenciamento, pelo menos). Portanto, pode-se esperar razoavelmente o mesmo do XOR lógico definido pelo usuário , como em
XOR(++x > 1, x < 5)
enquanto um !=
XOR baseado em não tem essa propriedade.