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.
