From 73c545cd2c70a71a72b02b9420f6ef5c9630fad5 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 12 Jul 2004 03:04:09 +0000 Subject: [PATCH] Initial checkin of tribool library [SVN r23453] --- doc/Jamfile.v2 | 9 ++ doc/tribool.boostbook | 216 +++++++++++++++++++++++++++++++++++ test/Jamfile | 35 ++++++ test/tribool_io_test.cpp | 178 +++++++++++++++++++++++++++++ test/tribool_rename_test.cpp | 123 ++++++++++++++++++++ test/tribool_test.cpp | 119 +++++++++++++++++++ 6 files changed, 680 insertions(+) create mode 100644 doc/Jamfile.v2 create mode 100644 doc/tribool.boostbook create mode 100644 test/Jamfile create mode 100644 test/tribool_io_test.cpp create mode 100644 test/tribool_rename_test.cpp create mode 100644 test/tribool_test.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..1e638c2 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,9 @@ +project boost-sandbox/utility/doc ; +import boostbook ; +import doxygen ; + +doxygen reference : ../../../boost/logic/tribool.hpp + ../../../boost/logic/tribool_fwd.hpp + ../../../boost/logic/tribool_io.hpp + ; +boostbook tribool : tribool.boostbook ; diff --git a/doc/tribool.boostbook b/doc/tribool.boostbook new file mode 100644 index 0000000..0840d8f --- /dev/null +++ b/doc/tribool.boostbook @@ -0,0 +1,216 @@ + + + + + + Douglas + Gregor + gregod@cs.rpi.edu + + + + 2002 + 2003 + 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 + + + +
+ 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 +} +
+ +
+ 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)) { /* ... */ } +
+ +
+ <code>tribool</code> 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. + + +
\ No newline at end of file diff --git a/test/Jamfile b/test/Jamfile new file mode 100644 index 0000000..ac5ec21 --- /dev/null +++ b/test/Jamfile @@ -0,0 +1,35 @@ +# Tribool library + +# Copyright (C) 2002-2003 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) + +# For more information, see http://www.boost.org/ + + +# Testing Jamfile autogenerated from XML source +subproject libs/logic/test ; + +# bring in rules for testing +SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; +include testing.jam ; + +# Make tests run by default. +DEPENDS all : test ; + +{ + # look in BOOST_ROOT for sources first, just in this Jamfile + local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ; + + test-suite logic + : + [ run libs/logic/test/tribool_test.cpp : : : : ] + + [ run libs/logic/test/tribool_rename_test.cpp : : : : ] + + [ run libs/logic/test/tribool_io_test.cpp : : : : ] + ; +} + \ No newline at end of file diff --git a/test/tribool_io_test.cpp b/test/tribool_io_test.cpp new file mode 100644 index 0000000..a7ff77c --- /dev/null +++ b/test/tribool_io_test.cpp @@ -0,0 +1,178 @@ +// Copyright Doug Gregor 2002-2003. 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) +#include +#include +#include +#include +#include +#include +#include + +int test_main(int, char*[]) +{ + using namespace boost::logic; + + tribool x; + + // Check tribool output + std::ostringstream out; + + // Output false (noboolalpha) + out.str(std::string()); + x = false; + out << x; + std::cout << "Output false (noboolalpha): " << out.str() << std::endl; + BOOST_TEST(out.str() == "0"); + + // Output true (noboolalpha) + out.str(std::string()); + x = true; + out << x; + std::cout << "Output true (noboolalpha): " << out.str() << std::endl; + BOOST_TEST(out.str() == "1"); + + // Output indeterminate (noboolalpha) + out.str(std::string()); + x = indeterminate; + out << x; + std::cout << "Output indeterminate (noboolalpha): " << out.str() + << std::endl; + BOOST_TEST(out.str() == "2"); + + const std::numpunct& punct = + BOOST_USE_FACET(std::numpunct, out.getloc()); + + // Output false (boolalpha) + out.str(std::string()); + x = false; + out << std::boolalpha << x; + std::cout << "Output false (boolalpha): " << out.str() << std::endl; + BOOST_TEST(out.str() == punct.falsename()); + + // Output true (boolalpha) + out.str(std::string()); + x = true; + out << std::boolalpha << x; + std::cout << "Output true (boolalpha): " << out.str() << std::endl; + + BOOST_TEST(out.str() == punct.truename()); + + // Output indeterminate (boolalpha - default name) + out.str(std::string()); + x = indeterminate; + out << std::boolalpha << x; + std::cout << "Output indeterminate (boolalpha - default name): " << out.str() + << std::endl; + BOOST_TEST(out.str() == "indeterminate"); + +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) + // No template constructors, so we can't build the test locale +#else + // Give indeterminate a new name, and output it via boolalpha + std::locale global; + std::locale test_locale(global, new indeterminate_name("maybe")); + out.imbue(test_locale); + out.str(std::string()); + out << std::boolalpha << x; + std::cout << "Output indeterminate (boolalpha - \"maybe\"): " << out.str() + << std::endl; + BOOST_TEST(out.str() == "maybe"); +#endif + + // Checking tribool input + + // Input false (noboolalpha) + { + std::istringstream in("0"); + std::cout << "Input \"0\" (checks for false)" << std::endl; + in >> x; + BOOST_TEST(x == false); + } + + // Input true (noboolalpha) + { + std::istringstream in("1"); + std::cout << "Input \"1\" (checks for true)" << std::endl; + in >> x; + BOOST_TEST(x == true); + } + + // Input false (noboolalpha) + { + std::istringstream in("2"); + std::cout << "Input \"2\" (checks for indeterminate)" << std::endl; + in >> x; + BOOST_TEST(indeterminate(x)); + } + + // Input bad number (noboolalpha) + { + std::istringstream in("3"); + std::cout << "Input \"3\" (checks for failure)" << std::endl; + BOOST_TEST(!(in >> x)); + } + + // Input false (boolalpha) + { + std::istringstream in("false"); + std::cout << "Input \"false\" (checks for false)" << std::endl; + in >> std::boolalpha >> x; + BOOST_TEST(x == false); + } + + // Input true (boolalpha) + { + std::istringstream in("true"); + std::cout << "Input \"true\" (checks for true)" << std::endl; + in >> std::boolalpha >> x; + BOOST_TEST(x == true); + } + + // Input indeterminate (boolalpha) + { + std::istringstream in("indeterminate"); + std::cout << "Input \"indeterminate\" (checks for indeterminate)" + << std::endl; + in >> std::boolalpha >> x; + BOOST_TEST(indeterminate(x)); + } + + // Input bad string (boolalpha) + { + std::istringstream in("bad"); + std::cout << "Input \"bad\" (checks for failure)" + << std::endl; + BOOST_TEST(!(in >> std::boolalpha >> x)); + } + +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) + // No template constructors, so we can't build the test locale +#else + + // Input indeterminate named "maybe" (boolalpha) + { + std::istringstream in("maybe"); + in.imbue(test_locale); + std::cout << "Input \"maybe\" (checks for indeterminate, uses locales)" + << std::endl; + in >> std::boolalpha >> x; + BOOST_TEST(indeterminate(x)); + } + + // Input indeterminate named "true_or_false" (boolalpha) + { + std::locale my_locale(global, + new indeterminate_name("true_or_false")); + std::istringstream in("true_or_false"); + in.imbue(my_locale); + std::cout << "Input \"true_or_false\" (checks for indeterminate)" + << std::endl; + in >> std::boolalpha >> x; + BOOST_TEST(indeterminate(x)); + } +#endif + + return 0; +} diff --git a/test/tribool_rename_test.cpp b/test/tribool_rename_test.cpp new file mode 100644 index 0000000..6114fc3 --- /dev/null +++ b/test/tribool_rename_test.cpp @@ -0,0 +1,123 @@ +// Copyright Doug Gregor 2002-2003. 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) + +// For more information, see http://www.boost.org + +#include +#include +#include + +BOOST_TRIBOOL_THIRD_STATE(maybe) + +int test_main(int,char*[]) +{ + using namespace boost::logic; + + tribool x; // false + tribool y(true); // true + tribool z(maybe); // maybe + + BOOST_TEST(!x); + BOOST_TEST(x == false); + BOOST_TEST(false == x); + BOOST_TEST(x != true); + BOOST_TEST(true != x); + BOOST_TEST(maybe(x == maybe)); + BOOST_TEST(maybe(maybe == x)); + BOOST_TEST(maybe(x != maybe)); + BOOST_TEST(maybe(maybe != x)); + BOOST_TEST(x == x); + BOOST_TEST(!(x != x)); + BOOST_TEST(!(x && true)); + BOOST_TEST(!(true && x)); + BOOST_TEST(x || true); + BOOST_TEST(true || x); + + BOOST_TEST(y); + BOOST_TEST(y == true); + BOOST_TEST(true == y); + BOOST_TEST(y != false); + BOOST_TEST(false != y); + BOOST_TEST(maybe(y == maybe)); + BOOST_TEST(maybe(maybe == y)); + BOOST_TEST(maybe(y != maybe)); + BOOST_TEST(maybe(maybe != y)); + BOOST_TEST(y == y); + BOOST_TEST(!(y != y)); + + BOOST_TEST(maybe(z || !z)); + BOOST_TEST(maybe(z == true)); + BOOST_TEST(maybe(true == z)); + BOOST_TEST(maybe(z == false)); + BOOST_TEST(maybe(false == z)); + BOOST_TEST(maybe(z == maybe)); + BOOST_TEST(maybe(maybe == z)); + BOOST_TEST(maybe(z != maybe)); + BOOST_TEST(maybe(maybe != z)); + BOOST_TEST(maybe(z == z)); + BOOST_TEST(maybe(z != z)); + + BOOST_TEST(!(x == y)); + BOOST_TEST(x != y); + BOOST_TEST(maybe(x == z)); + BOOST_TEST(maybe(x != z)); + BOOST_TEST(maybe(y == z)); + BOOST_TEST(maybe(y != z)); + + BOOST_TEST(!(x && y)); + BOOST_TEST(x || y); + BOOST_TEST(!(x && z)); + BOOST_TEST(maybe(y && z)); + BOOST_TEST(maybe(z && z)); + BOOST_TEST(maybe(z || z)); + BOOST_TEST(maybe(x || z)); + BOOST_TEST(y || z); + + BOOST_TEST(maybe(y && maybe)); + BOOST_TEST(maybe(maybe && y)); + BOOST_TEST(!(x && maybe)); + BOOST_TEST(!(maybe && x)); + + BOOST_TEST(maybe || y); + BOOST_TEST(y || maybe); + BOOST_TEST(maybe(x || maybe)); + BOOST_TEST(maybe(maybe || x)); + + // Test the if (z) ... else (!z) ... else ... idiom + if (z) { + BOOST_TEST(false); + } + else if (!z) { + BOOST_TEST(false); + } + else { + BOOST_TEST(true); + } + + z = true; + if (z) { + BOOST_TEST(true); + } + else if (!z) { + BOOST_TEST(false); + } + else { + BOOST_TEST(false); + } + + z = false; + if (z) { + BOOST_TEST(false); + } + else if (!z) { + BOOST_TEST(true); + } + else { + BOOST_TEST(false); + } + + std::cout << "no errors detected\n"; + return 0; +} diff --git a/test/tribool_test.cpp b/test/tribool_test.cpp new file mode 100644 index 0000000..5ef29e7 --- /dev/null +++ b/test/tribool_test.cpp @@ -0,0 +1,119 @@ +// Copyright Doug Gregor 2002-2003. 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) + +#include +#include +#include + +int test_main(int, char*[]) +{ + using namespace boost::logic; + + tribool x; // false + tribool y(true); // true + tribool z(indeterminate); // indeterminate + + BOOST_TEST(!x); + BOOST_TEST(x == false); + BOOST_TEST(false == x); + BOOST_TEST(x != true); + BOOST_TEST(true != x); + BOOST_TEST(indeterminate(x == indeterminate)); + BOOST_TEST(indeterminate(indeterminate == x)); + BOOST_TEST(indeterminate(x != indeterminate)); + BOOST_TEST(indeterminate(indeterminate != x)); + BOOST_TEST(x == x); + BOOST_TEST(!(x != x)); + BOOST_TEST(!(x && true)); + BOOST_TEST(!(true && x)); + BOOST_TEST(x || true); + BOOST_TEST(true || x); + + BOOST_TEST(y); + BOOST_TEST(y == true); + BOOST_TEST(true == y); + BOOST_TEST(y != false); + BOOST_TEST(false != y); + BOOST_TEST(indeterminate(y == indeterminate)); + BOOST_TEST(indeterminate(indeterminate == y)); + BOOST_TEST(indeterminate(y != indeterminate)); + BOOST_TEST(indeterminate(indeterminate != y)); + BOOST_TEST(y == y); + BOOST_TEST(!(y != y)); + + BOOST_TEST(indeterminate(z || !z)); + BOOST_TEST(indeterminate(z == true)); + BOOST_TEST(indeterminate(true == z)); + BOOST_TEST(indeterminate(z == false)); + BOOST_TEST(indeterminate(false == z)); + BOOST_TEST(indeterminate(z == indeterminate)); + BOOST_TEST(indeterminate(indeterminate == z)); + BOOST_TEST(indeterminate(z != indeterminate)); + BOOST_TEST(indeterminate(indeterminate != z)); + BOOST_TEST(indeterminate(z == z)); + BOOST_TEST(indeterminate(z != z)); + + BOOST_TEST(!(x == y)); + BOOST_TEST(x != y); + BOOST_TEST(indeterminate(x == z)); + BOOST_TEST(indeterminate(x != z)); + BOOST_TEST(indeterminate(y == z)); + BOOST_TEST(indeterminate(y != z)); + + BOOST_TEST(!(x && y)); + BOOST_TEST(x || y); + BOOST_TEST(!(x && z)); + BOOST_TEST(indeterminate(y && z)); + BOOST_TEST(indeterminate(z && z)); + BOOST_TEST(indeterminate(z || z)); + BOOST_TEST(indeterminate(x || z)); + BOOST_TEST(y || z); + + BOOST_TEST(indeterminate(y && indeterminate)); + BOOST_TEST(indeterminate(indeterminate && y)); + BOOST_TEST(!(x && indeterminate)); + BOOST_TEST(!(indeterminate && x)); + + BOOST_TEST(indeterminate || y); + BOOST_TEST(y || indeterminate); + BOOST_TEST(indeterminate(x || indeterminate)); + BOOST_TEST(indeterminate(indeterminate || x)); + + // Test the if (z) ... else (!z) ... else ... idiom + if (z) { + BOOST_TEST(false); + } + else if (!z) { + BOOST_TEST(false); + } + else { + BOOST_TEST(true); + } + + z = true; + if (z) { + BOOST_TEST(true); + } + else if (!z) { + BOOST_TEST(false); + } + else { + BOOST_TEST(false); + } + + z = false; + if (z) { + BOOST_TEST(false); + } + else if (!z) { + BOOST_TEST(true); + } + else { + BOOST_TEST(false); + } + + std::cout << "no errors detected\n"; + return 0; +}