T.init, struct destructors and invariants - should they be called?
Stanislav Blinov
stanislav.blinov at gmail.com
Mon Nov 19 01:46:34 UTC 2018
On Sunday, 18 November 2018 at 19:33:44 UTC, FeepingCreature
wrote:
> On Sunday, 18 November 2018 at 15:45:51 UTC, Stanislav Blinov
> wrote:
>> Anyway, my point is that unions *are* the tool for that
>> particular job, just like you said initially. Which has little
>> to do with the actual topic :)
>> For example, I'd argue that the *actual* implementation *must*
>> `move` it's passed-by-value argument (regardless of what it
>> uses for storage), because the caller already made a required
>> copy. But that means wiping out the argument back to T.init,
>> and then we're back to square one.
>
> Right, which is why we make a *second* copy, store it in a
> Union, and moveEmplace that.
You misunderstood what I said, and as you saw in my last example
you don't need a moveEmplace for the current implementation. What
I'm saying is, the actual implementation *should* be doing this:
void opAssign(T rhs) {
// ...
move(rhs, myOwnStorage);
// ...
}
T, for all I know, could be non-copyable, i.e. a Unique. That way
the onus of making an instance falls solely on the caller, while
Nullalbe would never call or deal with any copy constructors.
Recall that D "frowns upon" self-referencing types. Although the
language can't statically disallow them, it's free to assume they
don't exist. Therefore, moving values around without calling
their copy ctors should be acceptable.
That's not a `union` problem. If you do it like this where T is
your S, you'll get an assert due to invariant. I.e. that is the
subject problem :)
> ...But to me, that indicates that @safe is broken, and I really
> don't believe in breaking an unrelated feature in order that I
> can coincidentally unbreak the original brokenness manually.
> And no, just because I put a fancy term on the brokenness
> doesn't make it any less broken. Unions let me take a @safe
> expression whose copy constructor has ran and avoid calling its
> destructor. This is useful because @safe would otherwise
> require me to run a destructor on some expressions whose
> constructor has never run. But two wrong designs don't make a
> correct design. Just because the building is on fire doesn't
> validate the decision to leave a giant jagged hole in the front
> wall.
Again, that is not a `union` problem, that's a
destructor+invariant problem. Types in .init state should be
destructible, period:
S[] a;
// can't do this:
a = new S[10];
// but still can do this:
a.length = 10;
More information about the Digitalmars-d
mailing list