T.init, struct destructors and invariants - should they be called?

Stanislav Blinov stanislav.blinov at gmail.com
Sun Nov 18 14:38:09 UTC 2018


On Sunday, 18 November 2018 at 13:05:28 UTC, FeepingCreature 
wrote:
> Ping: Resurrecting this thread because @thewilsonator 
> resurrected my spec pr.
>
> https://github.com/dlang/dlang.org/pull/2410

Rebuking Simen's response then :)

On Friday, 6 July 2018 at 23:37:30 UTC, Simen Kjærås wrote:

> The union brings back the exact problems we're trying to avoid. 
> It also makes it impossible to handle types where 
> hasElaborateAssign is true and this() is @disabled at the same 
> time. There's also the issue that at best it will do the wrong 
> thing when you @disable this() and init, but you probably 
> shouldn't do that anyway.

https://issues.dlang.org/show_bug.cgi?id=19321
https://github.com/dlang/dmd/pull/5830

Unions have been "fixed" for some time now. Use them, no need for 
hacks with ubyte.

struct Nullable(T) {
     private union U {
         T value = T.init;
     }
     private U _u;
     private @property ref _payload() inout { return _u.value; }
     private bool _hasValue;

     @property @trusted
     ref T value() {
         assert(_hasValue);
         return _payload;
     }

     @property @trusted
     void value(T val) {
         cleanup();
         _hasValue = true;
         _payload = val;
     }

     @property
     void value(typeof(null)) {
         cleanup();
         _hasValue = false;
     }

     @trusted
     private void cleanup() {
         if (!_hasValue) return;
         destroy(_payload);
         _hasValue = false;
     }

     this(T val) {
         value = val;
     }

     ~this() {
         cleanup();
     }

     this(typeof(null) val) {
         value = val;
     }

     void opAssign(T val) {
         value = val;
     }

     void opAssign(typeof(null) val) {
         value = val;
     }
}

struct S
{
     Object obj;
     invariant
     {
         assert(this.obj !is null);
     }
     @disable this();
     @safe
     this(Object obj)
     {
         this.obj = obj;
     }
     @safe void opAssign(S) { /* ... */ }
     @safe ~this() {}
}

@safe unittest {
     Nullable!S a; // Look ma, no assert!
}



More information about the Digitalmars-d mailing list