4 hours ago, Kaetemi said:
If you have a structure that has a pointer to another structure, or a pointer to a pointer, or some other indirection... automatically generated equality could become some weird blend of equality and indirect identity.
I'd be fine with just automatically calling operator== on each member as the default. We already get that with the implicit copy constructor/assignment operators. If the default doesn't do what I want, I'll override it, but most classes I work with are just doing that, anyway. It's the most usual case and therefore should be the default and automatic one.
My assumption is that the standards committee, being highly concerned with the implementation of the standard libraries, often encounters cases where this is not the default situation. It seems to me that, in general, there is a distinct trend of the standards committee prioritizing library authors when adding new features and rules.
Or perhaps this is an aspect of the "zero cost abstractions" philosophy and the committee doesn't want to force (what I consider) the reasonable default on everyone on the grounds that it would be a default with potential runtime costs. But... we already have that, with copy constructors... And now I'm just speculating.
4 hours ago, Kaetemi said:
Let's say I have two lists containing lists containing lists.
My expectation here as a C++ programmer would be deep equality, because that's how the standard library types generally behave and how the vast majority of user types I have encountered in production code behave. If I wanted identity rather than equality, I would compare the pointers or similar - eg. handles, in cases where my data is double-buffered or relocatable. If you want to do something else in your own idiom, that's fine, that's why we have operator overloading, but in C++ I'm always going to expect a deep comparison and you should specifically tell me when the type is doing something different.
IMO operator overloading should be reserved for non-default cases and should not be required for holding the compiler's hand through the default ones.
4 hours ago, Kaetemi said:
Which is... coldly logical... but not intuitive.
It seems intuitive enough if you keep in mind that char* as "pointer to string" rather than "string value." I would further argue that this is the correct way to think of a char* and "a == b" in your example is the behavior that I would expect.
4 hours ago, Kaetemi said:
Another coldly logical but non-intuitive
What's unintuitive or odd about this? It's certainly not always convenient, but the idea that comparison operators are binary (and more complex conditions are created by composing them) is a simple and clear one.