How will we fix opEquals?

Jonathan M Davis jmdavisProg at gmx.com
Thu Feb 10 01:57:01 PST 2011


On Thursday 10 February 2011 01:36:56 Don wrote:
> so wrote:
> >> (1) If it is a const member function, then it will have a viral effect
> >> on all objects -- any function called by opEquals will have to be
> >> marked const.
> > 
> > It doesn't look like we can solve this by switching the constness of an
> > Object.function,
> > unless we also state that every function in Object must be const and
> > accept the fact that no one would use these functions for other purposes
> > like caching, late binding etc...
> 
> I can think of many examples where opEquals would be logically pure, but
> not formally pure, but it's harder to come up with ones where it is not
> const. I guess you can have situations where a lazily-computed hash
> value is cached in the object, to speed up comparisons, but it doesn't
> seem inappropriate for casts to be required when you're doing that.
> Can you think of a use case where the calling function should know that
> opEquals() isn't truly const?

The hash problem can be semi-reasonably solved by declaring a non-const version 
of toHash along with the const one. That way, if you're not dealing with const 
objects, the hash can be cached (whicth the const version could also take 
advantage of if the non-const version had already been called or if some other 
function call had calculated the hash previously). However, without logical 
const, you can't do any sort of caching inside of a const function unless you 
either break the type system by casting away const or keep the cache outside of 
the class itself (at which point toHash couldn't be pure, which would suck). So, 
you're screwed on that point as long as toHash is const, but it _has_ to be 
const or const and immutable objects can't use it.

Actually, that brings up the question as to whether opEquals, opCmp, toHash, and 
toString/writeTo should be pure as well. It sucks if they're not, but I'm not 
sure that it's as critical. I think that I'd have to mess around with it a bit 
to decide how much of a problem that would really be. You can still declare the 
overridden versions as pure and take advantage of pure as long as you kept the 
references as being of the derived type, but you'd be screwed if you were doing 
something that required Object's functions to be pure.

Personally, I wish that there was a way to act like a logically pure function 
was actually pure. You can do that with nothrow by catching any exceptions (and 
preferably then asserting false if one actually gets thrown), but you can't do 
that with pure. I'd love it if you could just do the equivalent of that with 
pure and then call logically pure functions from actually pure ones, and if it 
isn't actually logically pure and the compiler ends up doing an incorrect 
optimization, then it's on your head. But it would make it much easier to use 
pure in situations where you _know_ that a function is logically pure, but you 
can't mark it as pure (calling C functions would be a prime example).

As for opEquals not truly being const... I can't think of any situation where 
that would be necessary other than trying to save programmers from having to use 
it, and calling functions _definitely_ care, since they can't use const objects 
with it if it's not const. So, I'm not quite sure that I understand your 
question about the calling function needing to know that opEquals isn't truly 
const.

- Jonathan M Davis


More information about the Digitalmars-d mailing list