fieldPostBlit - what is wrong with this and workarounds

Daniel Davidson nospam at spam.com
Fri Nov 1 06:28:55 PDT 2013


On Thursday, 31 October 2013 at 19:39:44 UTC, Jonathan M Davis 
wrote:
> const and postblit fundamentally don't mix, because for it to 
> work, you have
> to violate the type system. With postblits, the struct gets 
> memcpied and then
> the postblit constructor has the chance to mutate the resulting 
> object to make
> the pieces different that need to be different. However, to do 
> that mutation
> when the object is const would mean mutating a const object 
> which violates the
> type system. What we really need is copy constructors, but they 
> haven't been
> added yet. At one point, Andrei was saying that he and Walter 
> had a solution,
> but he didn't elaborate on it. I assume that it involved 
> introducing copy
> constructors, but I don't know, and this issue has not yet been 
> resolved.
>

This makes sense, but I think we could have a simpler solution 
that does not involve a copy constructor addition. It seems the 
problem is postblit offers a hole in the system whereby 
developers could change immutable data. Because of that postblit 
and const don't mix. The simple fix would be take the 
implementation of postblit away from the developer. It seems the 
use case for postblit is really only to provide deep copy 
semantics by having developer throw in a bunch of dups where 
desired.
What if the language just provided standard postblit 
functionality not defined by the user. However it is specified, 
it should be easy to implement.

struct S {
   // blit and no postblit dup -> sharing
   int[] y;

   // blit with request for postblit dup -> no sharing
   @postblit int[] x;
}

Ideally, [].dup would be made pure. Once that is done, generic 
field by field deep copy could be done and be made pure, thus 
returning optionally immutable data. While it is true the 
generated postblit will be mutating the incipient instance - that 
is fine as it is called in a construction context and dup is 
surely idempotent. Why make the developer write a function for 
simple copy?

> Now, in your particular code example, you don't define postblit 
> constructor,
> but my guess would be that RateCurve defines one, making it so 
> that a postblit
> constructor is generated for T which uses the one for 
> RateCurve, and the S
> gets one which uses T's. And because const doesn't work with 
> postblit
> constructors, S becomes uncopyable, and if there's any code 
> that requires that
> a copy be made, then it'll fail to compile (I'm not sure 
> whether the fact that
> it's uncopyable will result in an error if no attempts to copy 
> it are made,
> but you'll definitely get an error if an attempt to copy is 
> made).
>

Your guesses are correct.

> Hopefully, this problem will be resolved, but regardless of 
> that, I would
> advise against ever having a const member variable in a struct. 
> Even if you
> don't have any postblit issues, such a struct can never be 
> assigned to, and it
> becomes essentially unusuable in any situation where you would 
> have to assign
> a value to it (e.g. if it were in an array). You can certainly 
> make a struct's
> member variable const if you want to, but you're going to run 
> into stuff that
> won't work as a result. It's far better to just provide a 
> property for it
> which is const (probably returning the member by const ref if 
> you want to
> avoid copying it when using the property) rather than making 
> the member
> variable itself const.
>
> - Jonathan M Davis

I am now convinced avoiding `const(T) t` as a member is wise 
advice. The suggestion of leaving it non-const and providing a 
const accessor is good - but it won't prevent module code from 
modifying it. I really want to make sure it is not being mutated. 
So I'm now leaning toward this approach:

struct S {
   const(T) *rc;
}

so I won't have the copy/postblit issues. Doesn't this bypass the 
problems with `const(T) t`. The new risk is that somehow that 
member variable is initialized with a stack variable.

Thanks,
Dan


More information about the Digitalmars-d-learn mailing list