Topic: Why no logical xor operator?


Author: harris.pc@googlemail.com
Date: Thu, 6 Sep 2012 13:05:20 CST
Raw View
On Friday, August 22, 2003 9:29:22 PM UTC+8, Daniel Frey wrote:
> OK, the table needs some corrections, as I showed that the guarantees
> given for bool args and bool results cannot be given by the proposed
> code. Also, there is another important property for such an idiom: If
> the arguments are integral constant expressions (ICEs), is the result
> also guaranteed to be an integral constant expression? Obviously, this
> is not given for a my_xor_func()-implementation. Another row should be
> added to reflect whether the 'b'-part is repeated in the user's code or
> not, as 'b' might be a long expression in practice, repeating it can be
> a maintenance nightmare. Note that I ask "Singular 'b'" to make "yes"
> the desirable answer. Here we go:
>
> 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:
>
> #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_and )?BOOL_DETAIL_AND_HELPER(
> #define bool_or )?true:static_cast<bool>(
> #define bool_xor )?BOOL_DETAIL_XOR_HELPER(
>
> Thanks to Paul Mensonides, Fernando Cacciola and John Torjo for feedback
> on the code on the boost list :)
>
> And please note that I never claimed someone could possibly need such
> stuff :o)
>
> Regards, Daniel
>
> --
> Daniel Frey
>
> aixigo AG - financial training, research and technology
> Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
> fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
> eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]



I had to make some changes for it to work on MSVC 2010 -- the brackets
weren't expanding correctly.
So it now looks like this:

#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_OPE=
N
#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_OPE=
N

And works great :)



--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: google@dalvander.com (Anders Dalvander)
Date: Tue, 19 Aug 2003 23:41:36 +0000 (UTC)
Raw View
Why are there no logical-xor operator (^^) in the language? Though it
would not be able to use short-circuit evaluation, and the result
would be similar to the bitwise-xor operator (^). But if you put it
like that, there is really no need for logical-or nor logical-and
either as you could use bitwise-or and bitwise-and instead (except for
the short-circuit evaluation part).

Using:
operand-implicitly-converted-to-true = oict-true
operand-implicitly-converted-to-false = oict-false

oict-true ^^ oict-true == false
oict-false ^^ oict-true == true
oict-true ^^ oict-false == true
oict-false ^^ oict-false == false

1 ^^ 2 would thus be equal to false, as 1 is implicitly converted to
true and 2 is implicitly converted to true.

1 ^ 2 would on the other hand (still) be equal to 3, and 3 could be
implicitly converted to true.

Thus, the logical-xor operator (^^) would not behave the same as the
bitwise-xor operator (^).

// Anders

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: neutron@attbi.com ("Jack Applin")
Date: Wed, 20 Aug 2003 02:52:46 +0000 (UTC)
Raw View
Anders Dalvander (google@dalvander.com) wrote:
> Why are there no logical-xor operator (^^) in the language?

My xor FAQ follows.

Jack Applin
jack@hp.com

------------------------------------------------------------------------

People often ask why there isn't a logical exclusive-or operator.
After all, the && and || operators exist, so perhaps ^^ should, too.

What would ^^ do?  Presumably, it would be as similar as possible
to && and ||, so we should study their attributes:

1) Left-to-right evaluation
    f() && g() calls f() before g()

2) Short-circuit evaluation
    f() && g() doesn't call g() if f() is false.

3) Sequence point
    *p++ && *p++ is well-defined

4) Treating the arguments as boolean values
    (1 && 2)==1, whereas (1 & 2)==0.
    (3 && "hello")==1, whereas (3 & "hello") is a syntax error

5) A boolean result
    (5 && 6)==1, whereas (5 & 6)==4.
    In C++, the operands and result of && and || are bool, not int,
    but the essence is the same.

The mythical ^^ operator can't do (2), but the others are possible.

Proposed code    left-to-right?  sequence point?  bool args?  bool result?
--------------   --------------  ---------------  ----------  ------------
a ^ b                  no              no             no          no
a != b                 no              no             no          yes
(!a)!=(!b)             no              no             yes         yes
my_xor_func(a,b)       no              no             yes         yes
a ? !b : b             yes             yes            yes         no
a ? !b : !!b           yes             yes            yes         yes

The fact that you can achieve the same effect using a ? !b : !!b doesn't
end the discussion.  A ^^ operator might be useful for clarity and brevity.

"I've never needed a ^^ operator."  It's hard to say--our tools guide our
thinking.  Nobody uses ^^ now, because it's not available.  If it were
available, perhaps it would get used.

Does anybody have any quotes from Bjarne Stroustrup on this?

Dennis Ritchie said:

 > There are both historical and practical reasons why there is no ^^
 > operator.  The practical is: there's not much use for the operator.
 > The main point of && and || is to take advantage of their
 > short-circuit evaluation not only for efficiency reasons, but more
 > often for expressiveness and correctness. For example, in
 >
 >   if (cond1() && cond2()) ...
 >
 > it is often important that cond1() is done first, because if it's false
 > cond2() may not be well defined, or because cond1() is cheap and
 > cond2() is expensive.  Syntax to handle the situation has made it into
 > lots of languages; compare Ada's "and then'. By contrast, an ^^
 > operator would always force evaluation of both arms of the expression,
 > so there's no efficiency gain.  Furthermore, situations in which ^^ is
 > really called for are pretty rare, though examples can be created.
 > These situations get rarer and stranger as you stack up the operator--
 >
 >   if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...
 >
 > does the consequent exactly when an odd number of the condx()s
 > are true.   By contrast, the && and || analogs remain fairly plausible
 > and useful.
 >
 > Historical:  C's predecessors (B and BCPL) had only the bitwise
 > versions of | & ^.   They also had a special rule, namely that in an
 > statement like
 >
 >       if (a & b) ...
 >
 > the '&", being at the 'top level' of the expression occurring  in
 > `truth-value context' (inside the if())  was interpreted just
 > like C's &&.  Similarly for |. But not so for ^.
 >
 > One of the early bits of C evolution was the creation of separate
 > && and || operators.  This was better than the special rule, which was
 > hard to explain.
 >
 > In other words, the whole question arises because of the particular
 > method of symmetry-breaking that C chose.   Suppose I had reacted to
 > the situation of BCPL and B taking their notion of
 >
 >       if (a & b) ...
 >
 > and had people say
 >
 >       if (a) andif (b) ...
 >
 > (and similarly with "orif")  One can make a case that this kind of
 > syntax is better than && and ||,   If it had happened,
 > would people be asking for "xorif"? Probably not.
 >
 > My guess is that &, &&; |,||; ^,^^ is a false symmetry.  But it's
 > one that people seem to want, and, though it's not much help,
 > adding it wouldn't do much harm.
 >
 >       Dennis

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: stefan_heinzmann@yahoo.com (Stefan Heinzmann)
Date: Wed, 20 Aug 2003 14:19:47 +0000 (UTC)
Raw View
google@dalvander.com (Anders Dalvander) wrote in message news:<d04c84a9.0308191319.32319a05@posting.google.com>...
> Why are there no logical-xor operator (^^) in the language?

Whenever I need one, I use != on boolean operands. That means, of
course, that I might have to explicitly convert the operands to
boolean, but I don't think that this is so inconvenient as to warrant
the introduction of a new operator.

In a nutshell, your proposed operator^^, if it existed, would
informally be implemented as follows:

template<typename L, typename R>
bool operator^^(const L& lhs, const R& rhs)
{
    return bool(lhs) != bool(rhs);
}

Cheers
Stefan

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Thu, 21 Aug 2003 05:17:48 +0000 (UTC)
Raw View
Jack Applin wrote:
> Proposed code    left-to-right?  sequence point?  bool args?  bool resu=
lt?
> --------------   --------------  ---------------  ----------  ---------=
---
> a ^ b                  no              no             no          no
> a !=3D b                 no              no             no          yes
> (!a)!=3D(!b)             no              no             yes         yes
> my_xor_func(a,b)       no              no             yes         yes
> a ? !b : b             yes             yes            yes         no
> a ? !b : !!b           yes             yes            yes         yes

Consider:

#include <iostream>
using namespace std;

struct B
{
    operator bool() const { return true; }
    B operator!() const { return B(); }
};

int main()
{
    B a, b;

    cout << ( a ? !b : !!b ) << endl; // Oops...

    cout << ( a ? !static_cast<bool>(b) : static_cast<bool>(b) ) << endl;
}

This also shows how the correct version should look like :)

Regards, Daniel

--=20
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Thu, 21 Aug 2003 17:24:57 +0000 (UTC)
Raw View
An logxor (logical exclusive or) "operator" with the same precedence as
or can be implemented as a macro:

    struct xor_dummy {};

    struct xor_bool
    {
        template<typename T>
        xor_bool(const T & value) : value(value) {}
        const bool value;
    };

    template<typename T>
    xor_bool operator or(T left, xor_dummy)
    {
        return xor_bool(left);
    }

    template<typename T>
    bool operator or(xor_bool left, T right)
    {
        return left.value xor bool(right);
    }

    #define logxor or ::xor_dummy() or

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Fri, 22 Aug 2003 13:29:21 +0000 (UTC)
Raw View
OK, the table needs some corrections, as I showed that the guarantees=20
given for bool args and bool results cannot be given by the proposed=20
code. Also, there is another important property for such an idiom: If=20
the arguments are integral constant expressions (ICEs), is the result=20
also guaranteed to be an integral constant expression? Obviously, this=20
is not given for a my_xor_func()-implementation. Another row should be=20
added to reflect whether the 'b'-part is repeated in the user's code or=20
not, as 'b' might be a long expression in practice, repeating it can be=20
a maintenance nightmare. Note that I ask "Singular 'b'" to make "yes"=20
the desirable answer. Here we go:

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

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

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

#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_and )?BOOL_DETAIL_AND_HELPER(
#define bool_or )?true:static_cast<bool>(
#define bool_xor )?BOOL_DETAIL_XOR_HELPER(

Thanks to Paul Mensonides, Fernando Cacciola and John Torjo for feedback=20
on the code on the boost list :)

And please note that I never claimed someone could possibly need such=20
stuff :o)

Regards, Daniel

--=20
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]