Subject: Re: [boost] [optional] operator<(optional<T>, T) -- is it wrong?
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2014-12-01 11:29:53
On Mon, Dec 1, 2014 at 3:22 AM, Olaf van der Spek <ml_at_[hidden]> wrote:
> On Mon, Dec 1, 2014 at 2:31 AM, Matt Calabrese <rivorus_at_[hidden]> wrote:
> >> I think this kind of reasoning isn't very fruitful.
> >> Optional is not a string, string is not an optional. One having
> >> operator< does not imply the other should have it to.
> > Hmm? What isn't reasonable is arbitrarily deciding what should and should
> > not have a default ordering (not talking about operator< since that's a
> True, but it's NOT an arbitrary decision, is it?
It is arbitrary until and unless people actually explain what they feel is
the difference between cases that they consider "reasonable" and
"unreasonable." This is particularly true when one container that uses a
lexicographical compare is considered "reasonable" while another container
that uses a lexicographical compare is considered "unreasonable." Why you
want a default order is generally analogous in both situations and denying
one while not the other without any objective rationale is a very weak
decision. All types can be ordered and all types that have more than one
value can be ordered in multiple ways. No particular ordering is is
applicable in all situations for any type -- even integers. That does not
mean that a default is unimportant since frequently you require ordering
for a datastructure or algorithm to work, but the actual ordering may be
unimportant to the user or to the implementation. This is the whole point,
which I mentioned in every single reply.
> > much more controversial matter). The notion of default ordering is useful
> > because many datastructures and algorithms can make use of it,
> What std datastructures use it?
The ones that we've been talking about for the entire thread in almost
every reply. I'm not going to repeat again.
> those in the standard. There is absolutely nothing wrong with ordering
> > tuples or optionals or variants, or any type at all.
> That's what you keep saying but you don't back it up.
Again, I have done so multiple times in this thread, both with concrete
examples and with reference to why it is important in more generic code.
You can choose to put your fingers in your ears if you want, but that
changes nothing. Frankly, it's sort of unfortunate that the usefulness of
ordering for /any/ type needs to be re-explained in the context of C++,
since it's such a fundamental concept that has been talked about many times
before, not just by myself in this thread but by key C++ people, i.e.
Stepanov. Especially when you are creating a generic composite type that
you expect people to use, you should be conscious of ordering.
> The only thing you
> > accomplish by not having a default ordering is that you arbitrarily make
> > the type difficult to use with these datastructures and algorithms. The
> Having to explicitly pass in a comparator is not difficult is it?
As explained, it is both needless and can also be an arbitrary decision
even in non-generic code, let alone in generic code where all you usually
care about is that an ordering exists rather than what that particular
ordering is. Ideally you always forward the comparator along when writing
generic code that needs ordering, using a default of std::less just as the
standard does for its generic containers, and yet the default is still
useful. In fact, default comparators are so useful in the standard library
that plenty of C++ programmers don't even know that the comparators are
template arguments at all, yet they get along fine. I doubt that explicitly
passing the comparator is "not difficult" to them. Regardless, stating that
explicitly passing an argument where a default can be used is "not
difficult" is a cop-out since you can always say the same thing regarding
any default in any context. In this particular context, that hypothetical
lack of a default comparator for the types in question has already led to
the recommendation of preferring entirely different associative
datastructures over passing in an explicit comparator in this very thread
(ironically, the other containers that were recommended also depend on a
subjective default, only it's the default hashing function instead of the
default ordering function).
You should not be afraid to have your types be ordered when they can be
ordered. Most decisions in development have a subjective aspect to them and
precisely which default ordering comparator you provide is just one of
those many decisions. The fact that a default is subjective (and it always
is, even for arithmetic types), does not mean that a default is not useful.
Why do we use less as a default for arithmetic types with respect to a set?
Wouldn't greater be just as sensible? What about the other orderings? We
only accept that it is "reasonable" now to have less be the default
ordering because that was the decision that was made decades ago and people
are used to it. It. Is. Just. A. Default.
-- -Matt Calabrese
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk