Inherited const when you need to mutate

David Piepgrass qwertie256 at gmail.com
Tue Jul 10 08:39:45 PDT 2012


On Tuesday, 10 July 2012 at 02:43:05 UTC, Era Scarecrow wrote:
> On Tuesday, 10 July 2012 at 01:41:29 UTC, bearophile wrote:
>> David Piepgrass:
>>> This use case is pretty complex, so if I port this to D, I'd 
>>> probably just cast away const/immutable where necessary.
>>
>> You are not the first person that says similar things. So D 
>> docs need to stress more than casting away const/immutable in 
>> D is rather more dangerous than doing the same thing in C++.
...
>  Let's say a class/struct is a book with Page protectors 
> signifying 'const(ant)'. You promise to return the book to the 
> library without making any changes; Although you promised you 
> wouldn't make changes, you still take the Page protectors off 
> and make make notes on the outer edges or make adjustments in 
> the text, then return the book.
>
>  Is this wise? This isn't C++. If something shouldn't change, 
> then don't change it god damn it. If it needs to change it 
> isn't const(ant) and shouldn't suggest it is.

The difficulty, in case you missed it, is that somebody else (the 
Object class) says that certain functions are const, but in 
certain cases we really, really want to mutate something, either 
for efficiency or because "that's just how the data structure 
works". If a data structure needs to mutate itself when read, 
yeah, maybe its functions should not be marked const, but quite 
often the "const" is inherited from Object or some interface that 
(quite reasonably, it would seem) expects functions that /read 
stuff/ to be const.

And yet we can't drop const from Object or such interfaces, 
because there is other code elsewhere that /needs/ const to be 
there.

So far I have no solution to the dilemma in mind, btw. But the 
idea someone had of providing two (otherwise identical) 
functions, one const and one non-const, feels like a kludge to 
me, and note that anybody with an object would expect to be able 
to call the const version on any Object.

> Seriously, it's not that hard a concept. I guess if something 
> doesn't port well from C++ then redesign it. Some things done 
> in C++ are hacks due to the language's limitations and faults.

I was referring to a potential port from C#, which has no const. 
My particular data structure (a complex beast) contains a mutable 
tree of arbitrary size, which the user can convert to a 
conceptually immutable tree in O(1) time by calling Clone(). This 
marks a flag in the root node that says "read-only! do not 
change" and shares the root between the clones. At this point it 
should be safe to cast the clone to immutable. However, the 
original, mutable-typed version still exists. As the user 
requests changes to the mutable copy in the future, parts of the 
tree are duplicated to avoid changing the immutable nodes, with 
one exception: the read-only flag in various parts of the 
original, immutable tree will gradually be set to true.

In this case, I don't think the D type system could do anything 
to help ensure that I don't modify the original tree that is 
supposed to be immutable. Since the static type of internal 
references must either be all mutable or all immutable, they will 
be typed mutable in the mutable copy, and immutable in the 
immutable copy, even though the two copies are sharing the same 
memory.

And one flag, the read-only flag, must be mutable in this data 
structure, at least the transition from false->true must happen 
*after* the immutable copy is created; otherwise, Clone() would 
have to run in O(N) time, to mark every node read-only. This 
fact, however, does not affect the immutable copy in any way.


More information about the Digitalmars-d mailing list