Douglas
Gregor
dgregor -at- cs.indiana.edu
2002
2003
2004
Douglas Gregor

Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file `LICENSE_1_0.txt` or copy at http://www.boost.org/LICENSE_1_0.txt)

Three-state boolean type

# Boost.Tribool

# Introduction

The 3-state boolean library contains a single class, ``boost::logic::tribool``, along with support functions and operator overloads that implement 3-state boolean logic.

# Tutorial

## Basic usage

The ``tribool`` class acts like the built-in `bool` type, but for 3-state boolean logic. The three states are `true`, `false`, and `indeterminate`, where the first two states are equivalent to those of the C++ `bool` type and the last state represents an unknown boolean value (that may be `true` or `false`, we don't know).

The ``tribool`` class supports conversion from `bool` values and literals along with its own `indeterminate` keyword:

    tribool b(true);
    b = false;
    b = indeterminate;
    tribool b2(b);

``tribool`` supports conversions to `bool` for use in conditional statements. The conversion to `bool` will be `true` when the value of the ``tribool`` is always true, and `false` otherwise. Consequently, the following idiom may be used to determine which of the three states a ``tribool`` currently holds:

    tribool b = some_operation();
    if (b) {
      // b is true
    }
    else if (!b) {
      // b is false
    }
    else {
      // b is indeterminate
    }

``tribool`` supports the 3-state logic operators `!` (negation), `&&` (AND), and `||` (OR), with `bool` and ``tribool`` values. For instance:

    tribool x = some_op();
    tribool y = some_other_op();
    if (x && y) {
      // both x and y are true
    }
    else if (!(x && y)) {
      // either x or y is false
    }
    else {
      // neither x nor y is false, but we don't know that both are true

      if (x || y) {
        // either x or y is true
      }
    }

Similarly, ``tribool`` supports 3-state equality comparisons via the operators `==` and `!=`. These operators differ from "normal" equality operators in C++ because they return a ``tribool``, because potentially we might not know the result of a comparison (try to compare `true` and `indeterminate`). For instance:

    tribool x(true);
    tribool y(indeterminate);

    assert(x == x); // okay, x == x returns true
    assert(x == true); // okay, can compare tribools and bools

The `indeterminate` keyword (representing the indeterminate ``tribool`` value) doubles as a function to check if the value of a ``tribool`` is indeterminate, e.g.,

    tribool x = try_to_do_something_tricky();
    if (indeterminate(x)) {
      // value of x is indeterminate
    }
    else {
      // report success or failure of x
    }

All the logical operators and methods of ``tribool`` are marked as `constexpr` in C++11. It means that ``tribool`` can be used in compile time expressions:

    constexpr tribool x = (tribool(true) || tribool(indeterminate));
    static_assert(x, "Must be true!");

Some compilers may have troubles with evaluating `tribool::operator safe_bool()` at compile time.

## Renaming the indeterminate state

Users may introduce additional keywords for the indeterminate value in addition to the implementation-supplied `indeterminate` using the `BOOST_TRIBOOL_THIRD_STATE` macro. For instance, the following macro instantiation (at the global scope) will introduce the keyword `maybe` as a synonym for `indeterminate` (also residing in the `boost` namespace):

    BOOST_TRIBOOL_THIRD_STATE(maybe)
    tribool x = maybe;
    if (maybe(x)) { /* ... */ }

## `tribool` input/output

``tribool`` objects may be read from and written to streams by including the boost/logic/tribool_io.hpp header in a manner very similar to `bool` values. When the `boolalpha` flag is not set on the input/output stream, the integral values 0, 1, and 2 correspond to `tribool` values `false`, `true`, and `indeterminate`, respectively. When `boolalpha` is set on the stream, arbitrary strings can be used to represent the three values, the default being "false", "true", and "indeterminate". For instance:

    tribool x;
    cin >> x; // Type "0", "1", or "2" to get false, true, or indeterminate
    cout << boolalpha << x; // Produces "false", "true", or "indeterminate"

``tribool`` input and output is sensitive to the stream's current locale. The strings associated with false and true values are contained in the standard ``std::numpunct`` facet, and the string naming the indeterminate type is contained in the ``indeterminate_name`` facet. To replace the name of the indeterminate state, you need to imbue your stream with a local containing a ``indeterminate_name`` facet, e.g.:

    BOOST_TRIBOOL_THIRD_STATE(maybe)
    locale global;
    locale test_locale(global, new indeterminate_name<char>("maybe"));
    cout.imbue(test_locale);
    tribool x(maybe);
    cout << boolalpha << x << endl; // Prints "maybe"

If you C++ standard library implementation does not support locales, `tribool` input/output will still work, but you will be unable to customize the strings printed/parsed when `boolalpha` is set.

Test all features of the ``boost::logic::tribool`` class.

Test the use of the `BOOST_TRIBOOL_THIRD_STATE` macro.

Test tribool input/output.