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