Head Const

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Thu Feb 18 21:46:24 PST 2016


On Thursday, 18 February 2016 at 22:40:32 UTC, Walter Bright 
wrote:
> On 2/18/2016 4:16 AM, Jonathan M Davis wrote:
>> headconst may solve the extern(C++) problem, but it really 
>> doesn't solve the
>> problems we have with const.
>
> 'mutable' doesn't really solve a problem, it just means that 
> C++ 'const' is a documentation aid, not a guarantee.

It's still a guarantee for those members that aren't mutable. 
It's allowing casting away const and mutating that totally blows 
the guarantees out of the water. You can actually look at the 
type to see which members are mutable and know what might change, 
and usually it's stuff like mutexes that are perfectly okay to 
change, whereas with casting, you'd have to look at every spec of 
code that uses the object to see what it does if you want to be 
sure that a const object or particular member isn't mutated.

And while I very much like the fact that D doesn't consider 
casting away const and mutating to be defined behavior and that 
it has stronger guarantees than C++, the reality of the matter is 
that in many cases, it ultimately provides far worse guarantees 
than C++. While C++'s const does have too many backdoors, at 
least when you use it, it catches accidental mutation (e.g. 
getting the arguments reversed when calling copy from the 
algorithm header will result in an error). But if you're forced 
to drop const entirely as tends to happen in D, then you don't 
get that. So, for some code, the stricter const in D is great, 
but for a lot of it, it makes things worse. In spite of the 
stronger guarantees, you ultimately end up with less protection. 
And since the compiler actually lets you cast away const and 
mutate in D to your heart's content without complaining at all 
(even if it's technically undefined behavior), there are plenty 
of folks that do it, because D doesn't provide mutable, and they 
assume that because you can cast away const, mutating it must be 
fine, just like with C++. So, while in principle, D's const 
provides better guarantees, in practice, it really doesn't. 
Casting away const would have to be illegal for it really provide 
those guarantees. And because it's so restrictive, it frequently 
gets avoided anyway. So, even if it doesn't get circumvented, it 
still fails to provide good guarantees, because it's not used.

At least if we added @mutable, we'd be providing a controlled 
means of escaping const in the cases where it's needed, avoiding 
issues with immutable like you'd potentially get if you cast away 
const and mutated. And any code which didn't use @mutable would 
be able to rely on the full guarantees that we have now (the only 
problem being folks that cast away const and mutated, thinking 
that it was okay, but they'd have less incentive to if they had 
@mutable).

In principle, I agree that having something like @mutable does 
weaken const, but in practice, it does a much better job of 
catching bugs, because then you're actually able to use const 
with more complicated objects. And unlike casting away const, 
@mutable is easily detected and accounted for.

D's const simply doesn't work once you start doing stuff like 
putting allocators or reference counts into the mix. And while 
maybe we could not care about that when we thought that it was 
fine to use the GC with everything, I think that we have a much 
harder time holding that position now. As principled as D's 
current position on const may be, it's highly impractical.

- Jonathan M Davis


More information about the Digitalmars-d mailing list