Optional type - how to correctly reset a wrapped immutable T

Simen Kjærås simen.kjaras at gmail.com
Mon Mar 26 07:46:21 UTC 2018


On Sunday, 25 March 2018 at 23:00:11 UTC, Simen Kjærås wrote:
> On Sunday, 25 March 2018 at 21:26:57 UTC, aliak wrote:
>> struct Optional(T) {
>>   Unqual!T value;
>>   opAssign(T t) {
>>     value = cast(Unqual!T)(t);
>>   }
>> }
>
> Consider this case:
>
> Optional!(immutable int) a = some(3);
> immutable int* p = &a.value;
> a = some(5);

Of course, if Optional offers no way to get a reference to the 
wrapped value (say, if a.value is an @property function that 
doesn't return ref T), then using Unqual internally is safe*.

Someone with knowledge of the internal layout of Optional might 
use tricks like *cast(immutable(int)*)&a, but in that case 
they're breaking the type system anyway, and one simply cannot 
negotiate with terrorists.

*actually, this may not be 100% true, in cases where T.opAssign 
does weird things. Consider:

struct Foo {
     int* p;

     void opAssign(Foo rhs) {
         p = rhs.p;
         (*p)++;
     }
}

unittest {
     immutable a = Foo(new int(3));
     assert(*a.p == 3); // Passes
     Optional!(immutable(Foo)) b;
     b = a;
     assert(*a.p == 3); // Fails
}

There actually is a workaround for this, using destroy() and 
move() instead of assignment. I'm unsure if there are other 
corner cases to consider.


--
   Simen


More information about the Digitalmars-d-learn mailing list