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