408

Is there such a thing? It is the first time I encountered a practical need for it, but I don't see one listed in Stroustrup. I intend to write:

// Detect when exactly one of A,B is equal to five.
return (A==5) ^^ (B==5);

But there is no ^^ operator. Can I use the bitwise ^ here and get the right answer (regardless of machine representation of true and false)? I never mix & and &&, or | and ||, so I hesitate to do that with ^ and ^^.

I'd be more comfortable writing my own bool XOR(bool,bool) function instead.

8
  • 63
    Actually, Jim, that's not the only difference between & and && for example... 1 && 2 is True. but 1 & 2 => 0. Because of that, I think that "short circuiting" is just a property that they happen to have. Logical is the more important feature... Commented Oct 20, 2009 at 19:27
  • 8
    Not to mention that 2 && 3 == true, but 2 & 3 == 2. Commented Oct 20, 2009 at 19:54
  • 1
    David Thomley: Well, yeah, but 2 ==> true, so that's ok... Remember, there really aren't any booleans... Commented Oct 20, 2009 at 19:58
  • 15
    @BrianPostow: Actually, in C++, there are. Commented Aug 14, 2013 at 10:57
  • 12
    As posted below, here's Dennis Ritchie's answer as to why it doesn't exist: c-faq.com/misc/xor.dmr.html Commented Sep 15, 2014 at 11:18

12 Answers 12

727

The != operator serves this purpose for bool values.

Sign up to request clarification or add additional context in comments.

15 Comments

But false != false => false
Note that this only works for booleans. And ^ would work perfectly well there. 2 !=1 => 1 which is not what you want! as LiraNuna says, putting a ! infront of both sides solves that problem. but again, then you can use bitwise ^...
Right, I was careful to mention "for bool values" because it doesn't necessarily do what you might want for non-booleans. And as this is C++, there exists a real bool type instead of having to use int for that purpose.
If you want to do it for type a just write !(a) != !(a)
@ChrisLutz: yes, but beware of overloaded operators.
|
328

For a true logical XOR operation, this will work:

if(!A != !B) {
    // code here
}

Note the ! are there to convert the values to booleans and negate them, so that two unequal positive integers (each a true) would evaluate to false.

7 Comments

Question is, are compilers be able to properly optimize this.
@einpoklum Pure speculation, but I'd bet on no. Even if the compiled could ensure that the bool values are indeed a 0 or 1 (or whatever the system uses), which should be possible because of the first '!', they'd still have to have a specific optimization for an (in)equality between two of those boolean values. Seems too much trouble for an arguably insignificant and easily manually code able optimization.
@Aidiakapi: Not necessarily. If the eventual operation is boolean, a compiler might well try to minimize or canonicalize the formula.
Not knowing the importance of normalizing bools costed me 2 days.
why not simply if (bool(A) != bool(B)) ? imo, no need for negation.
|
57

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: 1) they guarantee short-circuit evaluation, 2) they introduce a sequence point, 3) they evaluate their operands only once.

XOR evaluation, as you understand, cannot be short-circuited since the result always depends on both operands. So 1 is out of question. But what about 2? If you don't care about 2, 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. Thus !A != !B implements the proper XOR in that regard.

But 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.

10 Comments

You're missing the other important thing about || and &&: C) they evaluate the operands in a boolean context. That is, 1 && 2 is true, unlike 1 & 2 which is zero. Likewise, a ^^ operator could be useful for providing this extra feature, of evaluating the operands in a boolean context. E.g. 1 ^^ 2 is false (unlike 1 ^ 2).
@Craig McQueen: I'm not missing it. The second paragraph of my post mentions it. In my opinion, treating operands as boolean values is not a critical feature of logical operators, in a sense that they would not be introduced for that reason alone. The main reason they were introduced is short-circuited evaluation and the sequence point required for that.
@user2019840 when actually implementing a preprocessor macro, you always have to be extra-careful with parenthesis. Don't leave this aspect to the caller. So it might be something like #define XOR(a, b) (a) ? !(b) : (b)
Since XOR cannot short-circuit, there is no need for a sequence-point. XOR is more like + in that regard. Unless you also want to argue for (++x) + x being equal to 2x+1, the sequence point is not reasonable.
@hkBst: I think this is fully covered in the second part of my answer.
|
27

There is another way to do XOR:

bool XOR(bool a, bool b)
{
    return (a + b) % 2;
}

Which obviously can be demonstrated to work via:

#include <iostream>

bool XOR(bool a, bool b)
{
    return (a + b) % 2;
}

int main()
{
    using namespace std;
    cout << "XOR(true, true):\t" << XOR(true, true) << endl
         << "XOR(true, false):\t" << XOR(true, false) << endl
         << "XOR(false, true):\t" << XOR(false, true) << endl
         << "XOR(false, false):\t" << XOR(false, false) << endl
         << "XOR(0, 0):\t\t" << XOR(0, 0) << endl
         << "XOR(1, 0):\t\t" << XOR(1, 0) << endl
         << "XOR(5, 0):\t\t" << XOR(5, 0) << endl
         << "XOR(20, 0):\t\t" << XOR(20, 0) << endl
         << "XOR(6, 6):\t\t" << XOR(5, 5) << endl
         << "XOR(5, 6):\t\t" << XOR(5, 6) << endl
         << "XOR(1, 1):\t\t" << XOR(1, 1) << endl;
    return 0;
}

4 Comments

This approach can generate some quite slow code - 3-5x slower than (!a) != (!b) on both clang and gcc using libstdc++: quick-bench.com/xtv2StFkR8PCkV4fOiqSgeG1T4Q
@xaxxon your benchmark is not correct: one of the two functions benchmarked creates a (unrelated) string inside its loop. Removing this, the code is only 30% slower. quick-bench.com/q/umQRhhr0ZVS2o03fhCQAfN3HLak
@gmargari must have forgotten to remove the auto-generated benchmark it starts with. Sorry.
@gmargari And for clang the difference vanishes completely. Funnily a + b == 1 is faster than all others on clang (and I think it is more readable too) but worse than != on gcc. quick-bench.com/q/756uY4HuBmqN62AQ5yQTqD7KEM8 I could imagine that for cases where you have more than two bools and want exactly one to be true, comparing the sum to 1 could be consistently the best solution.
16

The XOR operator cannot be short circuited; i.e. you cannot predict the result of an XOR expression just by evaluating its left hand operand. Thus, there's no reason to provide a ^^ version.

36 Comments

-1 because the main difference between && and & is not just the short circuiting. 1 && 2 is True, but 1 & 2 is false. Short circuiting is just a handy side effect.
The answer is not talking about && and & at all. Its point is that there is no reason to introduce ^^. The property that ^^ would regard any non-null value as 1 is not really useful, i suspect. Or at least i can't see any use.
Also C++ != other-languages. In C and C++ as shown above short circuit is not just some-nice-to-have-stuff but it's fundamentally important. :)
Then you should read Dennis Ritchie's answer to why it doesn't exist: it.usyd.edu.au/~dasymond/mirror/c-faq/misc/xor.dmr.html
Here's a working link on Dennis Ritchie's answer as to why it doesn't exist: c-faq.com/misc/xor.dmr.html
|
14

There was some good code posted that solved the problem better than !a != !b

Note that I had to add the BOOL_DETAIL_OPEN/CLOSE so it would work on MSVC 2010

/* From: http://groups.google.com/group/comp.std.c++/msg/2ff60fa87e8b6aeb

   Proposed code    left-to-right?  sequence point?  bool args?  bool result?  ICE result?  Singular 'b'?
   --------------   --------------  ---------------  ---------- ------------  -----------  -------------
   a ^ b                  no              no             no          no           yes          yes
   a != b                 no              no             no          no           yes          yes
   (!a)!=(!b)             no              no             no          no           yes          yes
   my_xor_func(a,b)       no              no             yes         yes          no           yes
   a ? !b : b             yes             yes            no          no           yes          no
   a ? !b : !!b           yes             yes            no          no           yes          no
   [* see below]          yes             yes            yes         yes          yes          no
   (( a bool_xor b ))     yes             yes            yes         yes          yes          yes

   [* = a ? !static_cast<bool>(b) : static_cast<bool>(b)]

   But what is this funny "(( a bool_xor b ))"? Well, you can create some
   macros that allow you such a strange syntax. Note that the
   double-brackets are part of the syntax and cannot be removed! The set of
   three macros (plus two internal helper macros) also provides bool_and
   and bool_or. That given, what is it good for? We have && and || already,
   why do we need such a stupid syntax? Well, && and || can't guarantee
   that the arguments are converted to bool and that you get a bool result.
     Think "operator overloads". Here's how the macros look like:

   Note: BOOL_DETAIL_OPEN/CLOSE added to make it work on MSVC 2010
  */

#define BOOL_DETAIL_AND_HELPER(x) static_cast<bool>(x):false
#define BOOL_DETAIL_XOR_HELPER(x) !static_cast<bool>(x):static_cast<bool>(x)

#define BOOL_DETAIL_OPEN (
#define BOOL_DETAIL_CLOSE )

#define bool_and BOOL_DETAIL_CLOSE ? BOOL_DETAIL_AND_HELPER BOOL_DETAIL_OPEN
#define bool_or BOOL_DETAIL_CLOSE ? true:static_cast<bool> BOOL_DETAIL_OPEN
#define bool_xor BOOL_DETAIL_CLOSE ? BOOL_DETAIL_XOR_HELPER BOOL_DETAIL_OPEN

Comments

11

(A || B) && !(A && B)

The first part is A OR B, which is the Inclusive OR; the second part is, NOT A AND B. Together you get A or B, but not both A and B.

This will provide the XOR proved in the truth table below.

|-----|-----|-----------|
|  A  |  B  |  A XOR B  |
|-----|-----|-----------|
|  T  |  T  |   False   |
|-----|-----|-----------|
|  T  |  F  |   True    |
|-----|-----|-----------|
|  F  |  T  |   True    |
|-----|-----|-----------|
|  F  |  F  |   False   |
|-----|-----|-----------|

4 Comments

I'm not digging the performance on this approach: quick-bench.com/PgNgGN8ATrKt7el1dAaJj7QtuF4
There's no need to be defensive about it.
@xaxxon: Don't see the point in this benchmarks!? In StringCreation you used in creation of string, but in second benchmark you didn't. If you place identical code in both benchmarks, and call different XOR's for each benchmark (XOR, and XOR2) you get same benchmark results. So what have you been trying to say?
If A and B are functions in the expression (A || B) && !(A && B), you risk A or B being evaluated an unpredictable numbers of times.
7

Here is how I think you write an XOR comparison in C++:

bool a = true;   // Test by changing to true or false
bool b = false;  // Test by changing to true or false
if (a == !b)     // THIS IS YOUR XOR comparison
{
    // do whatever
}

Proof

XOR TABLE
 a   b  XOR
--- --- ---
 T   T   F
 T   F   T
 F   T   T
 F   F   F

a == !b TABLE
 a   b  !b  a == !b
--- --- --- -------
 T   T   F     F
 T   F   T     T
 F   T   F     T
 F   F   T     F

The proof is that an exhaustive study of inputs and outputs shows that in the two tables, for every input set the result is always the identical in the two tables.

Therefore, the original question being how to write:

return (A==5) ^^ (B==5)

The answer would be

return (A==5) == !(B==5);

Or if you like, write

return !(A==5) == (B==5);

1 Comment

!a != !b seems to be nicer because it converts your arguments to bool for you.
6

Use a simple:

return ((op1 ? 1 : 0) ^ (op2 ? 1 : 0));

Comments

1
return ((A==5) != (B==5))


+------+------+--------+-----+
| A==5 | B==5 | op(==) | !op |
+------+------+--------+-----+
|    0 |    0 |      1 |   0 |
|    0 |    1 |      0 |   1 |
|    1 |    0 |      0 |   1 |
|    1 |    1 |      1 |   0 |
+------+------+--------+-----+

Comments

0

I use "xor" (it seems it's a keyword; in Code::Blocks at least it gets bold) just as you can use "and" instead of && and "or" instead of ||.

if (first xor second)...

Yes, it is bitwise. Sorry.

10 Comments

I'm guessing that those are hidden #defines from somewhere. I'm pretty sure "and" and "xor" aren't keywords in ansi C... ( at least not C79)
@Brian Postow: I don't know what C79 is, but in C++98 and and xor are standard library macros. Thay are not from "somewhere", they are from <iso646.h>. These macros are also in C99 (not sure about C89/90).
@Brian Postow: ... xor stands for bitwise xor though, while and is logical and.
I mistyped C89 as C79... and and xor etc are not in my copy of K&R. I don't think I've ever used iso686.h, at least not knowingly... and so, yes, they are #defines from somewhere, you just happen to know where that somewhere is B-)
They are certainly in C99 using that header. In C++, they are integrated into the language as "alternative tokens", and you can do struct A { compl A() { } }; to define a destructor, for example.
|
-1
#if defined(__OBJC__)
    #define __bool BOOL
    #include <stdbool.h>
    #define __bool bool
#endif

static inline __bool xor(__bool a, __bool b)
{
    return (!a && b) || (a && !b);
}

It works as defined. The conditionals are to detect if you are using Objective-C, which is asking for BOOL instead of bool (the length is different!)

4 Comments

This violates the double underscore rule.
@TamásSzelei Not necessarily as the compiler does not see that as it si preprocessed away, and in Objective-C world double underscores are fairly common.
Good point about the preprocessor, although to me it's still code smell this way (why use a macro instead a typedef anyway?). Also, the question was not about Objective-C.
@TamásSzelei Well I used to have a habit of sharing header files around across multiple languages, and usually all headers come from Objective-C. My new code don't smell too much now, but the double underscore are still used from time to time to adhere with ObjC habits.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.