On Sun, Nov 30, 2014 at 3:22 PM, Gavin Lambert
Strings are ok -- ordinal ordering is a reasonable default, though admittedly sometimes other orders need to be selected by the application. But this is fine as is.
Why? What makes the string default ordering "reasonable" and complex or variant not? There are a lot of ways to order strings that might even be more sensible in more cases than the current default (I.E. having different cases be adjacent in the ordering, such as "a" and "A"). It's only a default and you can't expect that default to apply to all situations. The same goes for complex or variant or any other type. The existence of multiple orderings should not imply that a default ordering should be left out. Quite literally all types that have more than one value have multiple orderings. This is fine and does not conflict with there being a default. It's perfectly acceptable to need an ordering and yet not know or care what that ordering is. If tuples have a default ordering (I'm not sure, because I haven't used
them), then yes, I would regard that as a bug.
They do have a default ordering, and while I agree that there is a mistake in the internals of the tuple definition of its order, I think that a default ordering existing for them is, in fact, a good thing (the problem I have with tuple ordering is that it defines all of the operators around < rather than the corresponding operators of the underlying types, and it also does not specialize std::less and family IIRC. Tony's suggestion for optional does things correctly and is what tuple should have done.). Anyway, why specifically do you consider a tuple having a default ordering as a bug? All it is is a lexicographical order, just like std::string and just like the other containers of the standard library. It just happens to be heterogenous and of a fixed size. Why do you consider it not "reasonable" to have a default ordering as a lexicographical ordering for tuples and yet consider it "reasonable" to have a default ordering as a lexicographical ordering for std::string? The distinction that is being made seems entirely arbitrary unless you or someone else can (1) specify unambiguously what that supposed difference actually is including how you would generalize that distinction, and (2) explain why such a difference is actually important with respect to defining a default ordering via std::less (or a proposed std::order). I don't buy the distinction being worthwhile either in practice or in theory. As far as I can tell it is arbitrary, inconsistent, and without any objective rationale. Okay, so what happens if you reverse the situation and don't provide a
default ordering: First, people can no longer use the type in datastructures like sets unless they provide an explicit ordering, even if they don't care what the ordering is. So here the user needs to do more to accomplish the same end result. What exactly does the user gain?
This is because they are using the wrong data structure. It *should* fail because there is no sensible default ordering for tuples or optionals or variants. In which case they should take the hint that they should be using an unordered container instead, such as unordered_map or unordered_set.
I'm sorry, but that is simply bad programming advice. Putting a tuple in a set is not using the "wrong" datastructure. A tuple can be correctly ordered just like any other type and the same is true of optionals or variants. There not being a single default order that everyone would expect without referencing documentation is completely separate from the choice of whether a programmer should use a set or an unordered set. Claiming that this should be a reason to choose one datastructure over another is horrible.
Now, flipping things around, what would happen if the library designer said
"I don't want to choose a default"? As a user of the library, the only effect is that I now need to do more work to accomplish my same goal for any place that can take advantage of a default ordering. What exactly is the tangible benefit here?
For one thing, it makes your code immune to a change in the default ordering as a result of a library upgrade or switching to a different type (eg. when switching from boost to std, if these made different choices).
Let's be clear. By having a default I'm not saying that it's up to the vendor to choose a default that can change between implementations, I'm saying that it should be specified what that default is. If there is some breaking change between standards, then it's no different from any other potentially breaking change. This is what we already do for the types with ordering in the standard (I.E. the containers). For another, it makes you actually think about what you're doing, and
whether you actually *want* ordering.
What's with the "want" here? Why would you not want an order? I can see not needing it for a certain application and not minding if it's there, but you make it sound like it's somehow a bad thing for it to even exist. If you personally don't need it then you don't have to use it. I'm just saying that those particular types, as key types, should *not*
have a default order relation (as there is no meaningful definition of one -- anything is entirely arbitrary), and so while authors should *prefer* to use unordered containers, if desired they can use an ordered container by defining the desired ordering explicitly themselves.
No. Just no. Please stop saying that people should "prefer" unordered containers simply because there's no default ordering that everyone would agree on. This reasoning is baseless and is a horrible recommendation for when to use one kind of associative container over another. There being or not being a default should not influence such a decision. If it does, then IMO we've failed in the design. -- -Matt Calabrese