fieldPostBlit - what is wrong with this and workarounds
Daniel Davidson
nospam at spam.com
Wed Nov 6 06:37:21 PST 2013
On Friday, 1 November 2013 at 20:29:54 UTC, Jonathan M Davis
wrote:
> On Friday, November 01, 2013 14:28:55 Daniel Davidson wrote:
>> On Thursday, 31 October 2013 at 19:39:44 UTC, Jonathan M Davis
> Deep copying is not the only reason to have a postblit. Smart
> pointers such as
> std.typecons.RefCounted require a postblit (or copy constructor
> if we had
> those) to do their job. Also, even if all you want is a deep
> copy, it's
> possible that the member being deep copied was allocated via
> something like
> malloc, in which case, the compiler couldn't take care of it
> for you.
>
So, deepCopy is a reason for postblit and I probably common for
those not wanting shared state. You have mentioned two more uses
for postblit, ref counting and dealing with something allocated
with malloc. Honestly I am not sure the impact of the latter. Are
you referring to `struct T { S *s }` where the s was allocated
with malloc? I think you give up on const/immutable when ref
counting anyway? Regardless, I imagine both of those cases are on
the less common side and are probably not too troubled by const
issues. I'm not suggesting getting rid of postblit. Neither am I
against constructors. It just sounds like adding constructors is
overkill if support for immutable language generated postblit
were available. And I think it would be easy to add.
I'm just suggesting add an annotation that marks fields to be
duped by a language generated postblit. The developer would not
need to implement the postblit and it would be clear when/where
sharing occurs. Then the language is still guaranteed immutable
correct when using the language generated postblit.
>> 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.
>
> If you do that, then rc can be mutated (and so the struct can
> be mutated), but
> what it points to can't be. So, from the sounds if it, it does
> what you want.
> Though honestly, I wouldn't worry about the rest of a module
> mutating your
> member variable just because it has access to it.
Correct - I'm not worried about rc being modified as it is pretty
easy to control that.
I was under the impression it is pretty easy to
innocently/unknowingly mutate data. Suppose a member function
passes that member `t` to any function in any other module. With
slices and maps, what is really being passed around are pointers.
Once you start passing them around in a non-const or
non-immutable context you have objects sharing the same pieces
data and eventually it could be changed, even though not in your
module.
> If you simply name member
> variables differently than the public API (e.g _rc instead of
> rc) and then
> provide a const property to access the member, then the odds
> are very low that
> you're going to accidentally access the member directly. And if
> you can't keep
> track of what's in a single module well enough to avoid this
> sort of problem,
> then your module is probably too big.
Not sure I agree because passing non-const instances to functions
anywhere in the system is now allowed if the member is non-const.
So it has less to do with the size of your module and more to do
with where you are passing it. If you are passing it around
non-const the door is wide open.
> But if you're paranoid, you can
> certainly add an extra layer indirection like you're
> suggesting. I wouldn't
> bother though.
>
> - Jonathan M Davis
Clearly I am paranoid :-)
But I think it is the case that const(T) and immutable(T) would
be just fine and your reservations would be gone if the postblit
were in fact immutable. If this were the case, wouldn't you
change your stance and recommend const(T) or immutable(T) if in
fact that is what the expectation is for the developer.
Thanks
Dan
More information about the Digitalmars-d-learn
mailing list