Using Trilean

Including Trilean

To include Trilean, use the following:

#include "arctic-tern/tril.hpp"

“Maybe” Constant

Along with the normal true and false constants provided by C++, trilean offers a maybe constant. This new constant is designed to be distinct from true and false, yet usable in the same manner for trileans.

Defining and Assigning

Defining a new trilean variable is simple.

tril foo = true;
tril bar = maybe
tril baz = false;

In addition to the three constants, you can assign other booleans and trileans.

bool foo = true;
tril bar = foo;
tril baz = bar;

// foo, bar, and baz are all 'true'

Conditionals

Obviously, one can compare a trilean against of its state constants directly.

tril foo = maybe;

if(foo == true)
    // code if TRUE...
else if(foo == maybe)
    // code if MAYBE...
else if(foo == false)
    // code if FALSE...

However, one can also test a trilean in the same manner as a boolean.

tril foo = maybe;

if(foo)
    // code if TRUE...
else if(~foo)
    // code if MAYBE...
else if(!foo)
    // code if FALSE...

You will notice that, in addition to the familiar tests for “true” (if(foo)) and “false” (if(!foo)), trilean has a third unary operator, ~, for “maybe” (if(~foo)).

Important

Remember, neither the “true” or “false” conditions will ever match “maybe”.

This basic behavior is what makes trilean so useful. For example, you may want to repeat a block of code until you encounter specific scenarios to cause it to either pass or fail, using something like while(~foo).

Comparisons

Trilean can be compared to booleans and other trileans using the == and != operators.

tril foo = true;
tril bar = maybe;
bool baz = true;

if(foo == bar)
    // This fails.

if(foo != bar)
    // This passes.

if(foo == baz)
    // This passes.

if(baz == foo)
    // This passes.

if(baz == bar)
    // This fails.

Switch

The idea of allowing a trilean to cast to an integer was discussed and debated in great deal. Finally, the decision was made to prevent casting a trilean to anything but a boolean (discussed later).

This means that trileans are not compatible with switch statements. While this may be initially disappointing to anyone used to using an enumeration for three-state logic, one will notice that an if-statement covering all three states of a trilean has at least 4 less lines of boilerplate.

tril foo;

/* This code demonstrates an if statement covering all three states
 * of a trilean. */

if(foo)
{
    // Some code.
}
else if(~foo)
{
    // Some code.
}
else if(!foo)
{
    // Some code.
}

Gotchas

Casting to Bool

In order to preserve the core logic that “maybe != true” in statements like if(foo), casting a trilean to a boolean causes “maybe” to be converted to “false”.

tril foo = maybe;
bool bar = foo;

// bar is now 'false'

In most cases, it is recommended to use the certain() function.

Note

In case you were wondering, we ensured that “maybe != false” in comparisons and conditionals by separately overloading the !, !=, and == operators.