While messing with std.allocator I explored the type below. I ended up not using it, but was surprised that implementing it was quite nontrivial. Should we add it to stdlib?

Theory: http://en.wikipedia.org/wiki/Three-state_logic

struct Tristate
{
    private ubyte value;
    private static Tristate make(ubyte b)
    {
        Tristate r = void;
        r.value = b;
        return r;
    }

    enum no = make(0), yes = make(1), unknown = make(4);

    this(bool b) { value = b; }

    void opAssign(bool b) { value = b; }

    Tristate opUnary(string s)() if (s == "~")
    {
        return this == unknown ? this : make(!value);
    }

    Tristate opBinary(string s)(Tristate rhs) if (s == "|")
    {
        // | yields 0, 1, 4, 5
        auto v = value | rhs.value;
        return v == 4 ? unknown : make(v & 1);
    }

    Tristate opBinary(string s)(Tristate rhs) if (s == "&")
    {
        // & yields 0, 1, 4
        return make(value & rhs.value);
    }

    Tristate opBinary(string s)(Tristate rhs) if (s == "^")
    {
        // + yields 0, 1, 2, 4, 5, 8
        auto v = value + rhs.value;
        return v >= 4 ? unknown : make(!!v);
    }
}

unittest
{
    Tristate a;
    assert(a == Tristate.no);
    static assert(!is(typeof({ if (a) {} })));
    assert(!is(typeof({ auto b = Tristate(3); })));
    a = true;
    assert(a == Tristate.yes);
    a = false;
    assert(a == Tristate.no);
    a = Tristate.unknown;
    Tristate b;
    b = a;
    assert(b == a);
    auto c = a | b;
    assert(c == Tristate.unknown);
    assert((a & b) == Tristate.unknown);
    a = true;
    assert(~a == Tristate.no);
    a = true;
    b = false;
    assert((a ^ b) == Tristate.yes);
}

Reply via email to