Правильная ручная логическая реализация XOR зависит от того, насколько близко вы хотите имитировать общее поведение других логических операторов ( ||
и &&
) с вашим XOR. В этих операторах есть две важные вещи: 1) они гарантируют оценку короткого замыкания, 2) они вводят точку последовательности, 3) они оценивают свои операнды только один раз.
Оценка XOR, как вы понимаете, не может быть закорочена, так как результат всегда зависит от обоих операндов. Так что 1 не может быть и речи. Но как насчет 2? Если вас не волнует 2, то bool
оператор нормализованных (то есть ) значений !=
выполняет работу XOR с точки зрения результата. И операнды могут быть легко нормализованы с одинарными !
, если это необходимо. Таким образом, !A != !B
реализуется надлежащий XOR в этом отношении.
Но если вам небезразлична дополнительная точка последовательности, ни правильное , ни !=
побитовое не ^
является правильным способом реализации XOR. Один из возможных способов сделать XOR (a, b) правильно может выглядеть следующим образом
a ? !b : b
На самом деле это настолько близко, насколько вы можете сделать самодельный XOR "похожим" на ||
и &&
. Конечно, это будет работать, только если вы реализуете XOR как макрос. Функция не будет выполнять, так как последовательность не будет применяться к аргументам функции.
Кто-то может сказать, однако, что единственная причина наличия точки последовательности в каждой &&
и ||
состоит в поддержке короткозамкнутой оценки, и, следовательно, XOR не нуждается в ней. Это имеет смысл, на самом деле. Тем не менее, стоит подумать о наличии XOR с точкой последовательности в середине. Например, следующее выражение
++x > 1 && x < 5
определил поведение и конкретный результат в C / C ++ (по крайней мере, в отношении последовательности). Таким образом, можно ожидать того же от пользовательского логического XOR, что и в
XOR(++x > 1, x < 5)
в то время как !=
XOR на основе этого свойства не имеет.