Re: [boost] Please don't define a fake"operator<"just for ordered containers

std::less is ambiguous. It could be that you wanted merely the function object representation of operator<, or it could be that you wanted the default map/set ordering relation. It is not clear which of the two std::less is supposed to be.
If shared_ptr doesn't support operator< it's not a problem, is it?
The context is:
- If we had a separate relation for set/map we would use that for settable/mappable objects. - Why is a separate relation better than just using less<>? - Because it is evident from the design of the standard library that less<> isn't meant for that, not consciously, at least.
"What should shared_ptr do" is a separate question. Under the current status quo, it defines operator< to order pair< shared_ptr<>, int > as well. Under a revised standard, it may well need to do something else, depending on how the standard is changed. Why would we have a separate default relation for set/map then std::less? std::less is intended to map to operator <() on the type _or_ to a total ordering for the type if operator <() is not defined. That's what the standard says - it is intentional (Alex would have had operator <() defined even for types such as complex - but couldn't get that through the standard - he was especially concerned with pointer comparisons to separate containers because this is very useful. Not being able to change the language he at least got the change for std::less (not being there this is probably a misrepresentation of history - but the Alex's intent was that a total ordering should be present nearly everywhere) - he was using operator <() even in the cases he new it was "wrong", because there is no operator [glyph for < with a loop at the small end]. I convinced him
Christoph Ludwig posted the correct reason why std::complex should not have an operator < () defined - sorry, my follow up using addition was poorly constructed. What I am proposing is that std::less should be defined for std::complex. that std::less<> is a reasonable way to spell [glyph for < with a loop at the small end.] For pair<shared_ptr<>, int> - what makes shared_ptr special? This doesn't work pair<T*, int> today - I don't see why we should special case shared_ptr - especially in a way which should likely change in the future. Rather I'd recommend specializing std::less - note that you could also specialize std::less<> for std::pair<shared_ptr<>, T> (and the two other variants) if this is _really_ a big concern. I haven't run across a need to order pairs with shared_ptr (nor a pair with pointers for that matter). As for what I expect std::greater<> et al. to do - I had that in my earlier 6 point note - they _better_ be defined consistently with std::less. std::less is supposed to be operator <, unless operator < is not defined in which case std::less provides a total ordering. It isn't ambiguous. Sean

Sean Parent wrote:
For pair<shared_ptr<>, int> - what makes shared_ptr special? This doesn't work pair<T*, int> today - I don't see why we should special case shared_ptr - especially in a way which should likely change in the future. Rather I'd recommend specializing std::less - note that you could also specialize std::less<> for std::pair<shared_ptr<>, T> (and the two other variants) if this is _really_ a big concern. I haven't run across a need to order pairs with shared_ptr (nor a pair with pointers for that matter).
I think I have a basic understanding of your logic, but let's think about practicality for a moment. I'm not saying logical and philosophical reasons are not appropriate for this discussion, but let's try and not think about them for a second. The ordering defined by the operator< overload for shared_ptr has the following important property: it is independent of shared_ptr's template parameter. You can order shared_ptr<void> objects, if you like. Or, a shared_ptr<void> and a shared_ptr<int>. Can you think of any problems that operator< could cause, in its current definition? In my mind, since you can't use T in your ordering semantics, you have no reasons to define your own ordering for shared_ptr. Therefore, you have no other use for operator<, and therefore if the one defined by the library causes no problems, we should keep it because it is practical. --Emil

"Sean Parent" <sparent@adobe.com> skrev i meddelandet news:BC803577-3DC2-4D20-BB64-84E72A501CEB@adobe.com...
Christoph Ludwig posted the correct reason why std::complex should not have an operator < () defined - sorry, my follow up using addition was poorly constructed.
What I am proposing is that std::less should be defined for std::complex.
Disagree. That could potentially break other template programming using std::less, to support std::unary_negate etc. Suddenly this would "work" for std::complex, when it shouldn't.
Why would we have a separate default relation for set/map then std::less? std::less is intended to map to operator <() on the type _or_ to a total ordering for the type if operator <() is not defined.
No, that's just for pointers. 20.5.7/8 says: "For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not." It doesn't mention std::complex or any other composite types.
For pair<shared_ptr<>, int> - what makes shared_ptr special?
The fact that it is a pointer? I don't care much if it doesn't have an ordering.
std::less is supposed to be operator <, unless operator < is not defined in which case std::less provides a total ordering. It isn't ambiguous.
Where does the standard say that? If you want to have an ordered collection of otherwise unordered data, the relation must be an application specific attribute. So define an appropriate functor, and use that with std::map, etc. Bo Persson

Sean Parent wrote:
Why would we have a separate default relation for set/map then std::less? std::less is intended to map to operator <() on the type _or_ to a total ordering for the type if operator <() is not defined. That's what the standard says - it is intentional (Alex would have had operator <() defined even for types such as complex - but
That is also how I interpret his intent based on what is currently in the standard, and that is why I maintain that *under the current standard*, the appropriate way to make a type ordered (even if only for the associatives) is via defining operator<.
couldn't get that through the standard - he was especially concerned with pointer comparisons to separate containers because this is very useful. Not being able to change the language he at least got the change for std::less (not being there this is probably a misrepresentation of history - but the Alex's intent was that a total ordering should be present nearly everywhere) - he was using operator <() even in the cases he new it was "wrong", because there is no operator [glyph for < with a loop at the small end]. I convinced him that std::less<> is a reasonable way to spell [glyph for < with a loop at the small end.]
OK, let's get back to:
Why would we have a separate default relation for set/map then std::less?
and:
As for what I expect std::greater<> et al. to do - I had that in my earlier 6 point note - they _better_ be defined consistently with std::less.
If the standard was written with this in mind, greater<>, less_equal<> and greater_equal<> would have been defined in terms of less<>. It is not reasonable to provide four customization points that the user is supposed to keep in sync. For me the fact that less_equal returns x <= y is strong evidence that it is not supposed to be a customization point, but a function object alias of operator<=.
For pair<shared_ptr<>, int> - what makes shared_ptr special?
Why should it be special? If a type K is ordered, pair<K, int> should also be.
participants (4)
-
Bo Persson
-
Emil Dotchevski
-
Peter Dimov
-
Sean Parent