Time to kill T() as (sometimes) working T.init alias ?

monarch_dodra monarchdodra at gmail.com
Tue Dec 11 05:22:41 PST 2012


On Tuesday, 11 December 2012 at 12:52:03 UTC, Dan wrote:
>
> For me it did not compile (No constructor for payload), maybe 
> you had a ctor for Payload? I think opAssign is not necessary - 
> if I remove it it still seems to work since default opAssign 
> calls postblit. I added the ctor, removed opAssign and put it 
> here: http://dpaste.dzfl.pl/6ecfe675
>
> Other than that - is there still a subtle bug?
>
> Thanks,
> Dan

Strange, it had compiled for me this morning. Wonder what 
happened...

Anyways, this just highlights one of D's inconsistencies:
Payload  a = Payload(1, 1); //Legal
Payload* p1 = new Payload(1, 1); //Illegal???
Payload* p2 = [Payload(1, 1)].ptr; //Dirty workaround.

Yeah... You can use the "dirty workaround": 
http://dpaste.dzfl.pl/c0258f66

Anyways, opAssign is *definitely* necessary. Without it, 
assignment would be equivalent to aliasing, and you wouldn't have 
actual COW (both instances would end up modified). What's more, 
if the current object had a handle on another payload, you 
wouldn't release it, causing it to duplicate for no reason (but 
that's moot considering COW is already broken). In my example, it 
works because no-one actually *calls* opAssign.

The bug is this (on topic)
//----
S s2 = S(2);
S s0 = S();
s0 = s2; //Crap.
//----
Here, you aren't actually calling "this(int = 0)". Nope. What you 
are actually calling is... nothing! This means s0 does not have 
an actual payload. This means that in theory, on every write, you 
need to check the count... and check there is actually a payload 
there first :D ! Yay extra useless checks and increased lazy 
initialization on every call!

> There is a fair amount of boilerplate bookeeping. What if the 
> struct had two, three, or more maps

Depends on the required granularity. I'd say ideally, you'd put 
all three maps in the same "Payload" struct, so things would not 
actually be more complicated.

If you try to make each map individually COW, it would only be 
slightly more complex. You *would* take a further performance hit 
having to call "ensureUnique" on *each* map every modifying call. 
Furthermore, you may also take a performance hit in terms of 
locality of reference. But that'd be WAY premature to really 
worry about.

What you have to keep in mind is that a "triple COW" design would 
only make sense if you have functions that modify one of your 3 
maps. If they are always modified together, it'd make no sense to 
use "triple COW".

//----
When everything is said and done, most of that code can be 
templated, or mixed-in.


More information about the Digitalmars-d mailing list