Library of Assembled Shared Sources
|
a three-state boolean value with { true, false and lass::num::unknown } More...
#include <tri_bool.h>
Related Symbols | |
(Note that these are not member symbols.) | |
const TriBool | unknown (TriBool::sUnknown) |
constant to be used as new keyword like true and false | |
a three-state boolean value with { true, false and lass::num::unknown }
Inspired by Boost three-state boolean logic library 'boost::tribool' by Doug Gregor (grego.nosp@m.d@cs.nosp@m..rpi..nosp@m.edu).
Booleans are great to express binary states, to express if something is true or false. But they lack the concept of Not-A-Number (NaN
). Indeed, with traditional booleans, there's no way to express that you don't know, that the boolean value is invalid. That's when this TriBool comes into action. TriBool adds one extra state to the traditional true
and false:
unknown
. As said, this unknown
acts like the NaN
for floating point values and behaves much the same way (though not entirely the same!).
The first thing to know is that the value unknown
can not come into existance as long as all your operands are in a known state (true
or false
). You have to inject an unknown
value yourself, and this section merely describes how it will flow through your code.
rule: In TriBool unary expressions, if the argument is unknown
, then the result will yield unknown
too..
Check out operator!
Indeed, if a
is unknown
, then !a
is unknown
too.
rule: In TriBool binary expressions, if at least one of the operands is unknown
, then the result yields unknown
, except if one of the operands is known (true
or false
) and provides enough information to result in a known state.
The first part is obvious. In an expression a
==
b
, if one of the operands is unknown
, we can not possible know if a
and b
are equal or not. It will yield unknown
. However, there are two situations in which a binary expression with an unknown operands still results in a known state. These are:
false
&&
unknown
yields false
. Indeed, for an AND operation to yield true
, both operands must be true
. Since we know at least one of them is false
, we can know for sure the result is false
too.true
||
unknown
yields true
. Indeed, for an OR operation to yield true
, at least one of the operands must be true
. Since we know the left operand is true
we know for sure we have at least one operand that is true, hence the result is true
.Since AND and OR are commutative, this is also valid for unknown
&&
false
and unknown
||
true
. In all other cases, a binary expression with at least one unknown
operand will yield unknown
.
unknown
behaves much like NaN
, but that's not really true. If you compare two operands that are NaN
, you'll get false
as result (a known state), where as if both operands are unknown
, it will not result false
but unknown!
a!=b
||
a==b
does not always yield true!
It will be unknown
if one of the operands is unknown.Care must be taken when TriBool variables are used in boolean context like if/else
statements (and for
and while
loops ...). For instance, the following examples are not equivalent (as they would be for plain old boolean logic). Notice what happens if a
is unknown!
The discrepancy is due to the fact there isn't an unambigious way to reduce the three states of a TriBool to the two states of the if/else
statement, or the traditional boolean logic. In the former, the if
block tests if a
is true
and the else
block gets the other two states. In the latter, the if
block tests if a
is false
and again the else
block gets the other two states. So, in any case, if a
is unknown, you'll end up in the else
block.
If you want to test for the three different cases in an if/else
construction, your code will typically look like the following:
This is equivalent to:
a
is in a unknown state by comparing it to the constant unknown
. You might expect it to yield true
if a
is indeed, unknown, but it will always return unknown
instead. After all, it cannot know if both sides are equal, since at least one is unknown (unknown
itself). To test if a
TriBool is indeed unknown, you have to use the method TriBool::isUnknown()
.Definition at line 199 of file tri_bool.h.