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