Proper manual logical XOR implementation depends on how closely you want to mimic the general behavior of other logical operators (||
and &&
) with your XOR. There are two important things about these operators: A) they guarantee short-circuit evaluation, B) they introduce a sequence point.
XOR evaluation, as you understand, cannot be short-circuited. So A is out of question. But what about B? If you don't care about B, then with normalized (i.e. bool
) values operator !=
does the job of XOR in terms of the result. And the operands can be easily normalized with unary !
, if necessary.
If you care about the extra sequence point though, neither !=
nor bitwise ^
is the proper way to implement XOR. One possible way to do XOR(a, b) correctly might look as follows
a ? !b : b
This is actually as close as you can get to making a homemade XOR "similar" to ||
and &&
. This will only work, of course, if you implement your XOR as a macro. A function won't do, since the sequencing will not apply to function's arguments.
Someone might say though, that the only reason of having a sequence point at each &&
and ||
is to support the short-circuited evaluation, and thus XOR does not need one. This makes sense, actually. Yet, it is worth considering having a XOR with a sequence point in the middle.
For example, the following expression
++x > 1 && x < 5
has defined behavior and specificed result in C/C++ (with regard to sequencing at least). So, one might reasonably expect the same from user-defined logical XOR, as in
XOR(++x > 1, x < 5)
while a !=
-based XOR doesn't have this property.