invariant/const class storage class

Steven Schveighoffer schveiguy at yahoo.com
Wed Oct 1 10:38:17 PDT 2008


The different methods of making a class instance invariant basically depend 
on when the invariance applies.  For classes where the type is declared 
invariant, the invariant label is enforced after the memory is acquired and 
initialized, and before the constructor is called.  This doesn't seem to me 
to be a very useful construct.

Casting after the class is created makes the invariant label apply after the 
user has received the constructed class, but casting to invariant is up to 
the user.

BTW, casting to invariant is the only possible way to make useful invariant 
heap data.  One generates the data, then casts it to invariant.  Usually 
this is done with brand-new memory so there is no chance for some separate 
mutable reference to be formed.  The downside is that the assurance that the 
data is truly invariant is up to the developer.  The compiler has to take 
your word for it.

The proposed invariant constructors as defined in Andrei's functional 
document (don't have the pdf link handy, but it's on the digitalmars web 
site), I believe they had a section of code that you could set data, but 
once you started using the 'this' pointer as arguments to other functions, 
'this' implicitly switched to invariant.  I believe this would make 
invariant classes much more useful.

There is another alternative that works today.  A public static method that 
does this explicitly.  If you make the constructor private, then you can 
force the caller to use the public static method.  e.g.:

class X
{
   private this() {}
   public static invariant(X) makeInstance() { return cast(invariant(X)) new 
X();}
}

Now you can be assured that all instances of X are invariant, and you are 
free to assign data to members in the constructor, making X a useful 
construct.  It's slightly better than fully custom invariance (such as with 
Java Strings) in that the compiler and users of the class can make more 
assumptions, and not as much care needs to be taken in implementing such a 
class.

-Steve

"Nicolas Sicard" wrote
Yigal Chripun a écrit :
> I understand casting as breaking the type system. shouldn't there be a
> way to create invariant objects without the cast?
> an invariant constructor seems a good way to solve this. any plans on
> adding such a feature to D2?
>
> I think it can work like this:
>
> class A {
>   this(params) {}   // [1]
>   invariant this(params) {}  // [2]
> }
>
> // create a mutable object - will use type [1] c-tors.
> auto a = new A(params);
>
> // create an invariant object - will use type [2] c-tors.
> invariant a = new A(params);
>
> // create a const object - will use type [1] or [2] c-tors.
> const a = new A(params);
>
> in the const case, if there are two c-tors which only differ by
> invariant-ness of the c-tor using either will create ambiguity and
> therefore should be a compile-time error.
>

What should an invariant constructor do that a plain one don't, apart
from specifying immutability of the instance?
This would mean you could create instances of different types from the
same class, which is also kind of breaking the type system, isn't it?

But declaring a class invariant (for all instances) is something
interesting.





More information about the Digitalmars-d mailing list