Congratulations to the D Team!

Jonathan M Davis jmdavisProg at gmx.com
Tue Jul 10 19:33:37 PDT 2012


On Wednesday, July 11, 2012 03:30:43 Jakob Ovrum wrote:
> Honestly, I think the ideal would be to give people the
> alternative of having a mutable opEquals etc. These methods only
> need to be logically constant (of course, they don't *need* to be
> even that, to the joy of operator overloading abusers worldwide),
> which means no help from the compiler, as it should be - just
> plain mutable, with the programmer providing the guarantee.
> 
> There was work in this direction but I understand it was ripe
> with issues of its own, however I don't understand how any other
> path could even be considered when it's just moving from one end
> of the scale to the other.
> 
> Yes, Object *needs* to work with const, this is imperative. But
> does it need to compromise on implementations relying on
> mutability? I was hoping the answer was "no". Obviously such an
> override would not work with const references, but some classes
> really don't lean themselves to immutability at all, alleviating
> the need for const. I can also imagine that if both were allowed,
> someone would leverage the ability to use caching in the mutable
> overload, then falling back to eager computation in the const
> overload.

Yeah. It seems to me that a reasonable approach would be to give Object two 
versions of opEquals, opCmp, toString, and toHash - a const and non-const 
version of each. The non-const version then calls the const version. So, the 
normal thing to do is have your class work with const and override the const 
version. If the non-const version on Object gets called, then the const 
version in the derived class gets called, and if the derived type is used 
directly, then it'll always use the const version, because that's what the 
derived type has.

On the other hand, for a class which doesn't work with const, it does this:

1. Override the non-const versions of opEquals, opCmp, toString, and toHash, 
giving them the implementations which you want.

2. Override the const versions of opEquals, opCmp, toString, and toHash and 
make their bodies assert(0).

That way, those 4 functions can be used normally as long as the object isn't 
assigned to a const reference, and if it is, then you get an Error. So, as 
long as the programmer completely avoids const with that class, it works just 
fine. And as long as the druntime functions which use those 4 functions do not 
require const (which is easy to do with either templates or inout), it should 
be perfectly possible to use such a class without it ever being const or ever 
needing to be const.

In addition, these may be possible (untested, so I'm not 100%) sure to make it 
harder to construct a const or immutable instance of the derived class:

1. @disable const and immutable versions of the class' constructors.

2. Create an alias this to an @disabled function which does an implicit 
conversion to const (probably won't work, but we could also probably make it 
possible if it doesn't currently work).

3. Create opCasts to const and immutable which are @disabled.

If all of those work, then the only way to get a const reference to the 
derived class is if it's used with a base class reference (which would 
probably only be Object given what the derived class is doing).

So, it then takes a bit of work to be able to have and use an object which 
cannot be const, but it's very doable, and a concise set of instructions on 
dlang.org would make it easy and straightforward to know what to do to create 
a class which can't be const. Maybe I'm missing something, but I don't see any 
reason why this can't work.

In addition, I see no reason to require that opEquals, opCmp, toString, or 
toHash be const, pure, @safe, _or_ nothrow for structs. As long as the 
druntime functions which use those functions are appropriately templated 
(which is pretty much required for them to work with structs, since they don't 
all derive from a single type), the constness, pureness, @safeness, and 
nothrowness of those functions in druntime can depend on whether the struct 
being used with them has those functions as const, pure, @safe, and/or 
nothrow.

So, with that, we can have const work wonderfully without requiring it, even 
if it does take a bit of work to get around it with classes. So, what am I 
missing here? Why doesn't this work? Or has Walter just not properly 
considered this option?

- Jonathan M Davis


More information about the Digitalmars-d mailing list