Boost logo

Boost :

Subject: Re: [boost] [optional] operator<(optional<T>, T) -- is it wrong?
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2014-12-01 04:31:40


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

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

I actually tend to agree. I know that as things are now, std::less and
operator< have different meaning and I think we need to play by those
rules, but that to me has always been a bit wonky, too. If std::less were
simply called std::order, that would make things much better. To be honest,
though, even separate from that, I'm also in the camp with whoever it was
that said that we should simply accept that operator< isn't necessarily
"less" but rather is a generalization of less that is considered to mean
"order," and which just so happens to be less when in the domain of the
built-in arithmetic types. Even then there are still problems, though,
because floating point types have things like NaNs that behave in a way
that means that neither operator< nor std::less provide order, which is a
much bigger horror than < not strictly meaning "less," IMO. At least for
pointers we have std::less appropriately specialized. As things are now,
you can't even use std::sort on a range of floats or doubles with the
default order if there is a chance that you have NaNs, otherwise you have
undefined behavior (and it's not even benign undefined behavior in common
implementations).

With respect to the standard, we have to always be careful to make sure
operator< is defined in terms of operator< (similar for other operators)
and std::less and family are defined in terms of themselves. Requirement
specifications need to accurately reflect this, too. It's unfortunate that
even the standard library messes this stuff up when it can on both
accounts. It's all unnecessarily confusing and error prone. Tony made very
positive progress with respect to optional ordering, but ultimately I think
the standard should change at a more basic level as well. There are very
few people out there who actually care or know enough to properly define
these operations with respect to generic composite types, and the standard
is partly to blame for that.

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

I think the specific problem in the original example could actually be
remedied with a compiler error, though, while still providing operator< for
optional<T>, optional<T> if it is still desired. In the example, the person
compared a T with an optional<T>. It was suggested by someone that even if
operator overloads for optional<T>, T were removed, that the code would
still compile because of the implicit conversion, which isn't actually
true. The code would not compile when the operator is specified to be a
template as opposed to an inline friend. It seems to me that the least
controversial and least-likely way to break valid code and yet also make
sure that the problem-case produces an error, if that is desirable, is to
just remove any optional<T>, T overloads and make the optional<T>,
optional<T> overloads templates.

-- 
-Matt Calabrese

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