library of assembled shared sources

http://lass.cocamware.com

lass::num::TriBool Class Reference

a three-state boolean value with { true, false and lass::num::unknown } More...

#include <tri_bool.h>


Public Types

enum  State { sFalse, sTrue, sUnknown }

Public Member Functions

 TriBool (State iState=sUnknown)
 TriBool (bool iBool)
const State state () const
Statestate ()
TriBool operator! () const
 operator SafeBool () const
bool isTrue () const
bool isFalse () const
bool isUnknown () const

Private Attributes

State state_

Related Functions

(Note that these are not member functions.)

const TriBool unknown (TriBool::sUnknown)
 constant to be used as new keyword like true and false


Detailed Description

a three-state boolean value with { true, false and lass::num::unknown }

Author:
Bram de Greve [BdG]
Inspired by Boost three-state boolean logic library 'boosttribool' by Doug Gregor (gregod@cs.rpi.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!).

behaviour of unknown

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:

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.

Note:
we said 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!

in contrary to traditional boolean logic, a!=b || a==b does not always yield true! It will be unknown if one of the operands is unknown.

consequences on if/else

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!

  TriBool a;

  if (a)
  {
      foo(); // called if a is true.
  }
  else
  {
      bar(); // called if a is false OR unknown.
  }

  if (!a)
  {
      bar(); // called if a is false
  }
  else
  {
      foo(); // called if a is true OR 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.

Note:
as you might notice, there's no conversion operator to bool. That's because of the ambigious mapping from TriBool to bool as described above. But then how does if (a) works? If does need a boolean value, doesn't it? The trick is in the operator SafeBool(). It will return a non-NULL pointer if and only if the TriBool is true, what invokes the if block. If the TriBool is false or unknown, then a NULL pointer is returned instead and the else block is called.
If you want to test for the three different cases in an if/else construction, your code will typically look like the following:

  if (a)
  {
      foo(); // called if a is true
  }
  else if (!a)
  {
      bar(); // called if a is false
  }
  else
  {
      fun(); // called if a is unknown
  }

This is equivalent to:

  switch (a.state())
  {
  case TriBool::sTrue:
      foo();
      break;
  case TriBool::sFalse:
      bar();
      break;
  default:
      LASS_ASSERT(a.state() == TriBool::sUnknown);
      fun();
      break;
  }

Warning:
a common mistake is to test if a TriBool 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().
  TriBool a;

  if (a == unknown)
  {
      // BAD! unreachable code, the test will never yield true.
  }

  if (a.isUnknown())
  {
      // GOOD! this code will be reached if the state of a is unknown.
  }

Definition at line 207 of file tri_bool.h.


Member Enumeration Documentation

Enumerator:
sFalse 
sTrue 
sUnknown 

Definition at line 211 of file tri_bool.h.


Constructor & Destructor Documentation

lass::num::TriBool::TriBool ( State  iState = sUnknown  ) 

lass::num::TriBool::TriBool ( bool  iBool  ) 


Member Function Documentation

const State lass::num::TriBool::state (  )  const

State& lass::num::TriBool::state (  ) 

TriBool lass::num::TriBool::operator! (  )  const

lass::num::TriBool::operator SafeBool (  )  const

bool lass::num::TriBool::isTrue (  )  const

bool lass::num::TriBool::isFalse (  )  const

bool lass::num::TriBool::isUnknown (  )  const


Friends And Related Function Documentation

const TriBool unknown ( TriBool::sUnknown   )  [related]

constant to be used as new keyword like true and false


Field Documentation

Definition at line 233 of file tri_bool.h.


The documentation for this class was generated from the following file:

Generated on Mon Nov 10 14:22:10 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo