Subject: Re: [boost] [optional] operator<(optional<T>, T) -- is it wrong?
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2014-12-01 02:12:44
On 1/12/2014 16:57, Matt Calabrese wrote:
> On Sun, Nov 30, 2014 at 5:49 PM, Gavin Lambert <gavinl_at_[hidden]>
>> Most containers do not implement ordering relations of the container
> Yes they do. All of the standard containers provide lexicographical
I stand corrected. I must admit to being unaware that these existed; I
think I missed them in the C++ library docs I was looking at as they
listed non-member functions in a completely separate location. Perhaps
that does undermine some of my arguments. :)
> As for why one might take advantage of such an ordering? I already gave you
> an example in this thread where I personally used the ordering of variants,
> though you mysteriously ignored it and again are make a claim that ordering
> is simply "meaningless." I have more examples if you want, since I actually
> use variants and tuples pretty much every day. So is ordering meaningful?
> Of course it is. It is in my concrete example and it is in more abstract,
> generic code where tuples and variants tend to manifest themselves either
> internally for storage or when producing results. As someone who actually
> uses these types in practice and who uses ordering of them, I am flat out
> telling you that ordering them is, in fact useful, and it does, in fact,
> make sense.
Perhaps "meaningless" was the wrong word. I meant something closer to
"unobvious", as in the ordering relationship is less visible to a casual
reader of the code, and could be easily misinterpreted or broken by a
future programmer. Still, I suppose that's what unit tests are for
(when they actually exist).
> That said, why do you think that it would be hard to remove the ordering
> once present? If order here were /actually/ meaningless as you repeatedly
> claim, then it would trivial to remove, since nobody would be using it in
> meaningful code.
If a library has defined operator<(T,T), then that operator exists and
there is (as far as I am aware) no way to remove it short of editing the
library code. Conversely if the library has not defined the operator,
there is nothing (bar namespace etiquette, perhaps) preventing the
application from doing so itself, as long as it doesn't need private
data to do so.
I suppose that could be resolved by an application that really wants to
get rid of the ordering relation defining a new class that delegates the
original and mirrors its interface apart from that group of
methods/operators, but this seems like a massive headache for everybody
and doesn't really solve unintended mixups.
> The thing is, absolutely none of this talk of requirements really applies
> here, though, since as I pointed out, the ordered and unordered containers
> are completely different datastructures and so comparison of their
> requirements is misleading. In the case at hand, the types /can/ be
> ordered, so whether or not those types have a /default/ order should have
> no bearing on whether you use an ordered or unordered set. Both of those
> choices are perfectly valid and the decision to choose one or the other has
> nothing to do with defaults.
As I said, the idea was that while you *could* define a default sort,
that would be surprising in many cases (eg. given a variant<int,
double>, 78 would be less than 42.5), so putting it into an ordered
container will not necessarily have the expected ordering. I suppose
there are still performance benefits from being able to eg. binary
search based on some order, even if it's not the final display order,
> No, people were misusing /operators/ not std::less -- particularly the
> mixed-type operators. We are not talking about operators here as I've tried
> to restate in several replies just to be clear. We are talking about
> default ordering for a type (I.E. specifying a std::less specialization or
> some proposed std::order).
I'm not sure I want to live in a world where std::less wasn't equivalent
to operator<, where the latter exists. (At least at the library layer;
if the application wants to mess with it that's their own business.)
>> My generalisation was that even op< on two optional<T>s is suspicious as
>> some people don't seem to agree where "none" sorts, or even what "none"
>> means in some cases -- and because others were arguing that it was
>> inconsistent to define one op< without the other.
> Here's where I tend to disagree (I'll go back to talking about order in
> general, though, so that we don't get derailed regarding operators that
> should or should not exist). Specifying ordering for any type at all is
> always a subjective decision. If someone sees an order comparison with an
> optional, no matter how that function is spelled, should that programmer A)
> make an assumption about ordering and not look it up or B) look up the
> ordering? Whether the function is spelled operator< or std::less or
> std::order seems unimportant to me in that particular respect. In every one
> of those cases the programmer would have to look up what the order is if
> they wanted to use it in a specific way. Because of that, I don't think
> it's a valid rationale to exclude the function. You always need to know
> what any function does when you use it. A default ordering function isn't
> particularly special.
The case in question is where you were using it without realising it; in
the stated example perhaps when code that used to have int parameters
was changed to optional<int> without amending the operator use accordingly.
That's a programmer error, of course, but it would have been nice if it
were also a compiler error. (Sometimes it's less obvious, when there
are layers of typedefs and metafunctions in the way, especially when
these come from external code.)
Admittedly the compiler can't catch everything and it's a philosophical
question on how much "hand holding" the library should do to help avoid
mistakes, but this question did arise in the context of making a "safer"
API for optional.
Perhaps I ran too far with the ball, but sometimes that's how you learn
where the lines in the sand are. (Have I mixed enough metaphors yet?)