Ctor, setters and invariant

Simen Kjærås simen.kjaras at gmail.com
Sat Mar 2 12:05:03 PST 2013


On Sat, 02 Mar 2013 11:02:08 +0100, simendsjo <simendsjo at gmail.com> wrote:

> invariant is called when a method enters. This creates problems if the  
> constructor calls a setter:
>
> import std.exception;
> struct S {
>    private int _i;
>    public:
>    this(int i) {
>      this.i = i;
>    }
>    @property void i(int v) {
>      enforce(v > 1);
>      _i = v;
>    }
>    invariant() {
>      assert(_i > 1);
>    }
> }
> unittest {
>    S(10);
> }
> void main() {}
>
>
> In this example, invariant is called at the start if the property i  
> called through the constructor. Calling setters in constructors is  
> sometimes a good way to make sure everything is initialized properly,  
> but as invariant is called, this becomes impossible.
>
> Is it possible that invariant() is only called at the end of ctor  
> instead of at the beginning and end of each setter when called from the  
> ctor? The ctor will often have the object in an invalid state while  
> constructing the object, so calling invariant() while in ctor will  
> almost always create problems.
>
> Or does anyone know a better way to solve this that doesn't require code  
> duplication?


import std.exception;
struct S {
   private int _i;
   private bool inConstructor = true;
   public:
   this(int i) {
     this.i = i;
     this.inConstructor = false;
   }
   @property void i(int v) {
     enforce(v > 1);
     _i = v;
   }
   invariant() {
     if (inConstructor) return;
     assert(_i > 1);
   }
}
unittest {
   S(10);
}
void main() {}

Not perfect, but it works.

-- 
Simen


More information about the Digitalmars-d-learn mailing list