From: Adam Badura on
> How would you actually use such a function?

Like I am using any other functions or functors.

> How would it be implemented more efficiently than we can do for ourselves?

This can be told just about every thing including entire STL for
example. So I do not consider it an argument.

> How would you determine which ordering was to be
> used (many types have more then one logical ordering, and often include
> equivalence sets)?

Just like it is done with default comparison operators and
functors. I
don't see any problem here.

> Even std::string has multiple orderings depending on the collation rules.

And yet somehow this does not prevent us from comparing
std::string with
operator < for example...

> How would you deal with types that have no ordering?
> What about types that have equivalence sets but no ordering?

Again just like with comparison operators and functors. There
would be
no overload/specialization/whatever dedicated for them and any use of
generic compare function for them would result in compilation error.

> It may seem a very simple thing to do but in fact it is very complicated
> and far from trivial to provide generically.

I don't think so. After all "red floyd" posted and example
implementation.

And that is just all. A good generic fallback. But types like
std::string might use a smarter code to prevent suboptimal double
comparison. Compiler might even use extra machine code to provide
faster
versions for arithmetic types for example. But the bright side is that
user
of "compare" no longer cares. Using "compare" you ask what you want
directly: "what is the order relation of those to objects from
totally
ordered space?". And asking questions directly is a great thing
because it
makes it easier to give decent replay as fast as possible.

Adam Badura

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Adam Badura on
> How would you actually use such a function?

Like I am using any other functions or functors.

> How would it be implemented more efficiently than we can do for ourselves?

This can be told just about every thing including entire STL for
example. So I do not consider it an argument.

> How would you determine which ordering was to be
> used (many types have more then one logical ordering, and often include
> equivalence sets)?

Just like it is done with default comparison operators and
functors. I
don't see any problem here.

> Even std::string has multiple orderings depending on the collation rules.

And yet somehow this does not prevent us from comparing
std::string with
operator < for example...

> How would you deal with types that have no ordering?
> What about types that have equivalence sets but no ordering?

Again just like with comparison operators and functors. There
would be
no overload/specialization/whatever dedicated for them and any use of
generic compare function for them would result in compilation error.

> It may seem a very simple thing to do but in fact it is very complicated
> and far from trivial to provide generically.

I don't think so. After all "red floyd" posted and example
implementation.

And that is just all. A good generic fallback. But types like
std::string might use a smarter code to prevent suboptimal double
comparison. Compiler might even use extra machine code to provide
faster
versions for arithmetic types for example. But the bright side is that
user
of "compare" no longer cares. Using "compare" you ask what you want
directly: "what is the order relation of those to objects from
totally
ordered space?". And asking questions directly is a great thing
because it
makes it easier to give decent replay as fast as possible.

Adam Badura

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Adam Badura on
> I'd wager the answer is simple: your generic "compare" function would
> simply be implemented in terms of op== and op< (or >), at which point,
> you'd have one more (trivial) function name for small-ish number of
> use cases.

Yes. A generic fallback might be implemented so. Just like the
implementation provided by "red floyd".
But types like std::string, build-in types and even containers
might
provide a more efficient implementations.
In the end you might as well say it about std::swap which after
all is
just a simple copy construction and assignment.

> For strings and raw memory, there are low-level (C) functions already

Yes. But they cannot be used in generic code as they do not work
with
any type.

> (seems to be your case). But they don't work well in face of +/-
> complex types that majority of C++ code is supposed to have.

Yet somehow swap works well...

> BTW, it looks like you're thinking in terms of qsort, which I'd
> consider strange for idiomatic C++ code. With C++, if you want
> ordering, just use set/multiset/map/multimap and/or populate your
> vectors using lower/upper_bound. I can't see why do you need a
> comparison function then.

For example when implementing some algorithms or containers.

Adam Badura

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Tony Delroy on
> Adam Badura wrote:
> > Why C++ does not contain a generic compare function? Such function
<snip>
> > [lack] results in the need to compare those string twice while a simple
> > "compare" function would give us full information at the cost of one
> > comparison.

On Jan 8, 3:06 am, Francis Glassborow
<francis.glassbo...(a)btinternet.com> wrote:
> I wonder if you have thought this through. How would you actually use
> such a function?

As Adam wrote, it's useful when comparing two containers (e.g.
strings), where you scan over some long common part, then find a
distinguishing character. There's a fair chance that you may know
exactly which of <, == and > apply at that point, so it would be nice
to have a good way to return that information. If you only indicate
say <, then a second comparison may waste time skipping the early
common elements before returning to the distinguishing ones....

Many existing "int compare(... a, ... b)" functions only promise to
return a negative, 0 or positive value, as subtracting elements may
produce that in one step more efficiently than guaranteeing -1, 0, or
1. The latter scheme does make it easy to switch on the resultant
value though...

switch (a.compare(b)) // or "a <=> b" or similar if an operator
were available
{
case -1: return "less than";
case 0: return "equal";
case 1: return "greater than";
default: std::cerr << "oops\n"; exit(EXIT_FAILURE);
}

Without a -1, 0, 1 guarantee, something like:
int compare_result = a <=> b;

if (compare_result < 0)
...
else if (compare_result == 0)
...
else // compare_result > 0
...;

In another post, I mentioned the ? : operators could be extended...

return a <=> b ?< "less than" ?= "equals" : "greater than";

I don't for one moment expect anything like this to be added to the
language, but I don't see that the objections you raise undermine this
comparison any more than the existing comparison operators (<, <=,
==, !=, >=, >).

> How would it be implemented more efficiently than we
> can do for ourselves?

It only helps efficiency in that it becomes a standard thing for
compilers to optimise. Consider this program:

int main(int argc, char* argv[])
{
return argc < 7 ? 42 : argc == 7 ? 53 : 64;
}

I picked weird numbers so they'd stand out in x86 assembly...

g++ -S -O3 compare.cc # ver. 4.4.1


cmpl $6, %edi
movl $42, %eax
jle .L3
movb $64, %al
cmpl $7, %edi
movl $53, %edx
cmove %edx, %eax
..L3:
rep
ret

f it helps the compiler a single compare statement,

A compiler might be able to perform the comparison once then use the
CPU flags to branch or load the appropriate return value without
repeating the comparison. Perhaps they do that for simple int/double
comparisons already? I've never studied. It couldn't... I don't see
much point in providing a compare(a, b) function that works for types
where the results would be meaningful (e.g. string, int, double).

How would you determine which ordering was to be
> used (many types have more then one logical ordering, and often include
> equivalence sets)? Even std::string has multiple orderings depending
> on the collation rules. How would you deal with types that have no
> ordering? What about types that have equivalence sets but no ordering?
>
> It may seem a very simple thing to do but in fact it is very complicated
> and far from trivial to provide generically.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Adam Badura on
> #include <functional>
> template <typename T>
> int compare<T>(const T& left, const T& right)
> {
> if (std::less(left, right))
> return -1;
> else if (std::less(right, left))
> return 1;
> else
> return 0;
> }

Yes. Exactly.

But if this function is not in std namespace then:
1) Standard types like string or containers will not provide more
efficient
versions.
2) Standard algorithms/containers will not use it to increase
performance.
3) Interaction of code from different vendors is harder.

Finally note that the same kind of argument might be used against
having std::swap.

Adam Badura

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]