#ifndef TRIBOOL_H #define TRIBOOL_H #include namespace Tribool { class Tribool { public: struct IndeterminateType { }; typedef bool (*IndeterminateKeywordType)(Tribool, IndeterminateType); public: Tribool(); Tribool(bool value); Tribool(const IndeterminateKeywordType& value); explicit operator bool() const; Tribool operator!() const; Tribool operator&&(const Tribool& other) const; friend Tribool operator&&(const Tribool& lhs, bool rhs); friend Tribool operator&&(bool lhs, const Tribool& rhs); friend Tribool operator&&(const IndeterminateKeywordType& lhs, const Tribool& rhs); friend Tribool operator&&(const Tribool& lhs, const IndeterminateKeywordType& rhs); Tribool operator||(const Tribool& other) const; friend Tribool operator||(const Tribool& lhs, bool rhs); friend Tribool operator||(bool lhs, const Tribool& rhs); friend Tribool operator||(const IndeterminateKeywordType& lhs, const Tribool& rhs); friend Tribool operator||(const Tribool& lhs, const IndeterminateKeywordType& rhs); Tribool operator==(const Tribool& other) const; friend Tribool operator==(const Tribool& lhs, bool rhs); friend Tribool operator==(bool lhs, const Tribool& rhs); friend Tribool operator==(const IndeterminateKeywordType& lhs, const Tribool& rhs); friend Tribool operator==(const Tribool& lhs, const IndeterminateKeywordType& rhs); Tribool operator!=(const Tribool& other) const; friend Tribool operator!=(const Tribool& lhs, bool rhs); friend Tribool operator!=(bool lhs, const Tribool& rhs); friend Tribool operator!=(const IndeterminateKeywordType& lhs, const Tribool& rhs); friend Tribool operator!=(const Tribool& lhs, const IndeterminateKeywordType& rhs); static inline bool Indeterminate(Tribool x, Tribool::IndeterminateType = Tribool::IndeterminateType()) { return x.m_value == Tribool::TriboolValue::Indeterminate; } private: class TriboolValue { public: enum type { True, False, Indeterminate }; }; private: TriboolValue::type m_value; }; template inline std::basic_ostream& operator<<(std::basic_ostream& out, Tribool x) { if (!Tribool::Indeterminate(x)) { out << static_cast(x); } else { typename std::basic_ostream::sentry cerberus(out); if (cerberus) { if (out.flags() & std::ios_base::boolalpha) out << "indeterminate"; else out << 2; } } return out; } template inline std::basic_ostream& operator<<(std::basic_ostream& out, bool (*)(Tribool, Tribool::IndeterminateType)) { return out << Tribool(Tribool::Indeterminate); } template std::basic_istream& operator>>(std::basic_istream& in, Tribool& x) { if (in.flags() & std::ios_base::boolalpha) { typename std::basic_istream::sentry cerberus(in); if (cerberus) { typedef std::basic_string string_type; string_type falsename = "false"; string_type truename = "true"; string_type indeterminatename = "indeterminate"; typename string_type::size_type pos = 0; bool falsename_ok = true; bool truename_ok = true; bool indeterminatename_ok = true; while ((falsename_ok && pos < falsename.size()) || (truename_ok && pos < truename.size()) || (indeterminatename_ok && pos < indeterminatename.size())) { typename Traits::int_type c = in.get(); if (c == Traits::eof()) return in; bool matched = false; if (falsename_ok && pos < falsename.size()) { if (Traits::eq(Traits::to_char_type(c), falsename[pos])) matched = true; else falsename_ok = false; } if (truename_ok && pos < truename.size()) { if (Traits::eq(Traits::to_char_type(c), truename[pos])) matched = true; else truename_ok = false; } if (indeterminatename_ok && pos < indeterminatename.size()) { if (Traits::eq(Traits::to_char_type(c), indeterminatename[pos])) matched = true; else indeterminatename_ok = false; } if (matched) ++pos; if (pos > falsename.size()) falsename_ok = false; if (pos > truename.size()) truename_ok = false; if (pos > indeterminatename.size()) indeterminatename_ok = false; } if (pos == 0) { in.setstate(std::ios_base::failbit); } else { if (falsename_ok) x = false; else if (truename_ok) x = true; else if (indeterminatename_ok) x = Tribool::Indeterminate; else in.setstate(std::ios_base::failbit); } } } else { long value; if (in >> value) { switch (value) { case 0: x = false; break; case 1: x = true; break; case 2: x = Tribool::Indeterminate; break; default: in.setstate(std::ios_base::failbit); break; } } } return in; } } // namespace Tribool #endif // TRIBOOL_H