Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2000-09-06 09:00:35

> I find the fact that whether or not operator< gives you the same
> ordering on two separate executions is unspecified for the same set of
> ref<> objects slightly worrying.

I think that the above should be "two separate compilations", but I may be

> For type_info::before this is not a
> problem: before is not operator<.

Depends on what your intuition leads you to assume about operator<.

before() is operator<. Why call it before() if it isn't? a type_info can
never be 'before' another type_info.

"a < b" and "a is before b" are equally applicable to type_info (and ref;
and T*.)

"a < b" is not a magnitude comparison in the general case. It isn't a
magnitude comparison even for integers: -5 < -4.

But let's assume that ref doesn't provide operator<, because it's not
"intuitive" to some subset of users. You have proposed that I specialise
less<ref> to make the associative containers work.

I think that this is much more counter-intuitive.

std::less<>()(a, b) is defined by the standard to return a < b. Therefore,

std::sort(begin, end);


std::sort(begin, end, std::less<>());

should be the same thing.

Had std::map been defined this way:

std::map<K, V, C = std::key_default_comparator<K> >

I wouldn't have had problems with providing key_default_comparator<ref>
while disabling ref::op<.

As it stands, however, I think that "extending" std::less to not use op< is
not acceptable. Pointers are an unfortunate exception because op< for them
is not required to provide a total ordering for historical and performance

> >> understanding, and the std only requires that the ordering is strict
> >> weak, which ref<> also does not satisfy.
> >
> >Why?
> struct empty
> {
> };
> ref<empty> lhs(empty()), rhs(empty());
> Is lhs < rhs, rhs < lhs, lhs == rhs, or none of these?

!(lhs < rhs)
!(rhs < lhs)

Whether lhs == rhs is debatable (in terms of op==; in terms of op< they are
equivalent.) I haven't decided on this yet.

Of course, ref<> provides a strict weak ordering only if you don't
deliberately break it by putting objects with broken op< in it. This is a
reasonable assumption, IMHO.

> >> And less<T*> is, in principle, specialised for this purpose. Would you
> >> rather that pointers had this total ordering?
> >
> >Yes. And in practice they already do on many platforms.
> That was not the question. My current platform supports operator< for
> ref<>, but I don't have to like that ;->

I answered the question. Yes, I'd rather have the total ordering. It doesn't
do any harm, is intuitive, and is a superset of the required ordering
between pointers to the same object. The "unspecifiedness" of the comparison
between pointers to different objects does not bother me. Why should it?

> >It has to be unspecified if you don't know that 'int' is an int and
> >is a double. ref does not interpret types. Neither does any.
> ref<> does interpret types, albeit in a limited fashion, otherwise you
> cannot establish any ordering.

No, it doesn't interpret types. It can only compare them for equality. The
fact that int can implicitly convert to double is well beyond that.

> The essential problem is that ref<> has a mix and match approach to its
> idea of ordering that is inconsistent: in some cases operator< is
> unspecified but provides a strict weak ordering, in others it is
> specified and provides a total ordering, and in others it is specified
> but does not provide an ordering.

ref's approach to ordering is consistent.

ref(T t) < ref(U u) iff T < U || (T == U && t < u).

Provided that t < u is strict and weak (again, a reasonable assumption),
this is a superset of the two status-quo orderings:

ref(T) < ref(U) is an unspecified total ordering different than, but with
the same properties as, type_info::before().

ref(T t1) < ref(T t2) is the strict and weak ordering between the elements
of the type T.

I don't see anything inconsistent with it.

Peter Dimov
Multi Media Ltd.

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