On Monday, 8 October 2012 at 08:53:39 UTC, simendsjo wrote:
You can create a wrapper struct that includes an invariant:

import std.stdio;

struct Image
{
    int width;

    void doSomething()
    {
    }

    void modifiesWidth()
    {
        --width;
    }
}

void func(Image img)
{
    struct ImgWrapper
    {
        Image* img;
        this(ref Image img)
        {
            this.img = &img;
        }

        invariant()
        {
            assert(img.width == 512);
        }

        void opDispatch(string s)()
        {
            mixin("img."~s~"();");
        }
    }

    auto wrapper = ImgWrapper(img);
    wrapper.doSomething();
    wrapper.modifiesWidth(); // assertion failure
}

void main()
{
    Image img = { 512 };
    func(img);
}

There is a difference between invariants and what I call states. States clear things up when you actually need to do a runtime check and when not. Invariants are always checked, because you don't care about performance in debug mode. A Number<positive> is positive already and will stay positive while you can access it. De facto you cannot change a Number<positive> to a negative number.

Reply via email to