Boost logo

Boost :

Subject: Re: [boost] [optional] operator<(optional<T>, T) -- is it wrong?
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2014-11-30 19:58:18


On Sun, Nov 30, 2014 at 3:22 PM, Gavin Lambert <gavinl_at_[hidden]>
wrote:

>
>> 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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk