Boost logo

Boost :

From: Yuval Ronen (ronen_yuval_at_[hidden])
Date: 2006-07-05 13:38:02

Daryle Walker wrote:
>> Because operator== has only one purpose in C++: comparison for equality.
>> Operator<, on the other hand, has two common roles.
>> For classes that have natural ordering, it should define this ordering,
>> and then all the other operators (> <= >=) should be defined as well.
>> Classes that doesn't have this natural ordering, often still define
>> operator< just to be able to be used in ordered containers. In such
>> cases, operator< doesn't define a natural ordering because there isn't
>> any. Instead, it just defines an ordering "that works" for ordered
>> containers, nothing more. It doesn't need to compatible with operator==
>> and !=, and defining operators >, <=, >= is misleading and should be
>> avoided.
> The later role is invalid. The reason is that the version of STL that made
> it into the Standard specifies an extra parameter for ordered containers for
> a comparison operation. It allows two containers of the same element type
> to use different comparison criteria (at compile- and/or run-time). This
> invalidates the need for a fake "operator <" since you can always package
> the comparison routine in an extra parameter. Conversely, calling code must
> not hard code use of "operator <" or "std::less<>", unless that code
> requires types with a natural ordering. (The standard algorithms have
> variants that either assume "operator <" or take in a comparison parameter.)
> Making a fake "operator <" just for ordered containers invalidates the work
> of those who added comparison parameters in standard classes/functions.

You have a point there, no doubt. On the other hand, Library writers
should supply some kind of functor to be used with their types in
conjunction with ordered containers (when appropriate, and
boost::variant is of course appropriate). How should this functor be
called? You might say there should be some convention, but there isn't
any right now, and some libraries use operator< for this purpose. Is it
that bad if operator< is the convention? I'm not sure. It's sure is
convenient to use ordered containers like that... And it seems to me
that there is no major drawback to this, because no other order operator
is provided. But I guess it's highly dependent on taste...

> The issue is different for the "==" and "!=" operators because two objects
> can have their state checked for equivalence without having a standardized
> order. The "std::complex<>" template classes are an example.

std::complex doesn't have operator<. std::tr1::shared_ptr does. So it
seems the standard isn't very helpfully consistent here...

>> boost::shared_ptr is a good example of such a class with no natural
>> ordering, with operator== and !=, with operator<, but without the other
>> operators. And shared_ptr is of TR1 strength...
> Ordering for pointers is generally defined if both pointers are part of the
> same array segment. (Either one or both of the pointers can be at the
> "one-past-the-end" point of said segment.) If two "shared_ptr" objects can
> be used for points in an array segment[1], then comparison can be allowed
> with ALL four operators ("<", ">", "<=", and ">="). Otherwise, none of
> those operators should be defined and any current existence of such
> operators should be considered a bug.

I didn't quite understand that last paragraph. shared_ptrs doesn't have
to point to objects in array (actually, they better not), but there can
be arrays of shared_ptrs. So should the shared_ptr class provide order
operators or shouldn't it? Anyway, the committee already made up it mind
about the answer to this question...

Boost list run by bdawes at, gregod at, cpdaniel at, john at