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 booloperador 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 != !Bimplementa 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.