Is it possible to override raw pointer comparison?

A

Ash

Why is this ok:
bool operator==(Foo* a, Foo& b) { return true; }

and if I have:
Foo* f1; Foo* f2;
then
f1 == *f2
is valid and calls the above function.

but the following (to try to override equality when called using two
raw pointers: f1 == f2):
bool operator==(const Foo* a, const Foo* b) { return true; }
doesn't compile?
(g++ tells me "test2.cpp:9: error: ‘bool operator==(const Foo*, const
Foo*)’ must have an argument of class or enumerated type")

Is it not possible to override the comparison of two pointers (f1 ==
f2) or have I simply not got the exact signature right?
 
N

Neelesh

Why is this ok:
bool operator==(Foo* a, Foo& b) { return true; }

and if I have:
Foo* f1; Foo* f2;
then
f1 == *f2
is valid and calls the above function.

but the following (to try to override equality when called using two
raw pointers: f1 == f2):
bool operator==(const Foo* a, const Foo* b) { return true; }
doesn't compile?
(g++ tells me "test2.cpp:9: error: ‘bool operator==(const Foo*, const
Foo*)’ must have an argument of class or enumerated type")

Is it not possible to override the comparison of two pointers (f1 ==
f2) or have I simply not got the exact signature right?

g++ is telling exactly what the issue is: operator overloading is
allowed only when atleast one operand is a user defined type (either a
class or an enumeration type). A "pointer" is not a user defined type
(even if it is a pointer to a class type) and hence it is not possible
to overload any operator that takes two pointers, eg. operator== or
operator= or operator- etc.
 
A

Ash

g++ is telling exactly what the issue is: operator overloading is
allowed only when atleast one operand is a user defined type (either a
class or an enumeration type). A "pointer" is not a user defined type
(even if it is a pointer to a class type) and hence it is not possible
to overload any operator that takes two pointers, eg. operator== or
operator= or operator- etc.

I suspected as much, but in which case I don't udnerstand why the
first case:
bool operator==(Foo* a, Foo& b) { return true; }
is ok? Where's the logic of the C++ standards body in allowing this,
which is an operation on a pointer and not when both operands are?
 
I

Ian Collins

Ash said:
I suspected as much, but in which case I don't udnerstand why the
first case:
bool operator==(Foo* a, Foo& b) { return true; }
is ok? Where's the logic of the C++ standards body in allowing this,
which is an operation on a pointer and not when both operands are?

Foo& is a user defined type.
 
N

Neelesh

I suspected as much, but in which case I don't udnerstand why the
first case:
bool operator==(Foo* a, Foo& b) { return true; }
is ok?

Well, a pointer is different than a reference, and C++ standard allows
operator overloading when atleast one operand is a class or
enumeration type or a reference to a class or enumeration type.
Where's the logic of the C++ standards body in allowing this,
which is an operation on a pointer and not when both operands are?

The exact paragraph from the C++ standard is this:
[13.5/6] An operator function shall either be a nonstatic member
function or be a nonmember function and have at least one parameter
whose type is a class, a reference to a class, an enumeration, or a
reference to an enumeration.
 
B

Bo Persson

Ash said:
I suspected as much, but in which case I don't udnerstand why the
first case:
bool operator==(Foo* a, Foo& b) { return true; }
is ok? Where's the logic of the C++ standards body in allowing this,
which is an operation on a pointer and not when both operands are?

The logic behind this is that the comparison of two pointers is
already defined by the language. You cannot add another one.

To overload a function or operator, the set of parameters must be
different from those of existing functions and operators with the same
name.


Bo Persson
 
A

Alf P. Steinbach

* blargg:
Ian said:
Ash said:
Why is this ok:

bool operator==(Foo* a, Foo& b) { return true; }

and if I have:

Foo* f1; Foo* f2;

then

f1 == *f2

is valid and calls the above function.

but the following (to try to override equality when called using two
raw pointers: f1 == f2):

bool operator==(const Foo* a, const Foo* b) { return true; }

doesn't compile? [...]
operator overloading is
allowed only when atleast one operand is a user defined type (either a
class or an enumeration type). [...]
I suspected as much, but in which case I don't udnerstand why the
first case:

bool operator==(Foo* a, Foo& b) { return true; }

is ok? Where's the logic of the C++ standards body in allowing this,
which is an operation on a pointer and not when both operands are?
Foo& is a user defined type.

(to elaborate further) and operator == has no built-in meaning for
user-defined types, thus you can provide one.

Ah, well, we have a terminology problem. Or rather, the standard has one. I
don't feel like listing and discussing here all the umpteen nowhere-defined
terms that the standard uses for various groups of types, but suffice it to say
that it's an inconsistent mess.

However, even though "user-defined type" is pretty unclear, note that an
enumeration type has a built-in meaning for ==.

I think we need a term such as "customizable type", which then is an enumeration
or class type. And that we need to be clear that "built-in type" doesn't mean
whatever (very unclear) it means in the standard. But means an actual built-in
type! <g>

Then such issues can be discussed.

I think I'll start adopting that terminology.


Cheers, & hth.,

- Alf
 
J

James Kanze

* blargg:
Ah, well, we have a terminology problem. Or rather, the
standard has one. I don't feel like listing and discussing
here all the umpteen nowhere-defined terms that the standard
uses for various groups of types, but suffice it to say that
it's an inconsistent mess.

Maybe. (Probably.) However...
However, even though "user-defined type" is pretty unclear,
note that an enumeration type has a built-in meaning for ==.

Does it? I don't think so, any more than it has a built-in
meaning for short. The "usual arithmetic conversions" apply to
==, so you're counting on the conversion to int, and comparing
the int's. Which has the somewhat unexpected (and unpleasant,
IMHO) result that you can compare totally unrelated enum types
for equality. And in overload resolution (§13.6), there's no
"candidate operator function" for == with an enum.
I think we need a term such as "customizable type", which then
is an enumeration or class type.

That's what "user defined type" means: an enumeration or class
type. Except when it also includes typedef's, as in
§7.1.5.2:).
And that we need to be clear that "built-in type" doesn't mean
whatever (very unclear) it means in the standard.

Within the description of the language, the standard doesn't use
the term "built-in type" in any context where it's significant
for the meaning of the standard. Outside of non-normative
notes, its use seems to be restricted to a single sentence at
the start of §4, in which case it is used only to give a vague
and general overview of what is in the section.

The library sections are less rigorous; in §24.1, for example,
it uses the expression "of some class, enumeration, or built-in
type T", when I think (I'm pretty sure, actually) that it means
"of some object type T". (Of course, the standard doesn't
define object type either. But it does define "object", in
§1.8, so the exterpolation isn't that difficult.)
But means an actual built-in type! <g>

With regards to operator overloading, the standard doesn't use
the words "built-in type". It says that "An operator function
shall either be a non-static member function or be a non-member
function and have at least one parameter whose type is a class,
a reference to a class, an enumeration, or a reference to an
enumeration." For once, it's actually fairly clear and exact.
 
J

James Kanze

To overload a function or operator, the set of parameters must
be different from those of existing functions and operators
with the same name.

Except when it doesn't have to be different, e.g. the unary &
(address of) operator.
 
A

Alf P. Steinbach

* James Kanze:
Maybe. (Probably.) However...


Does it? I don't think so, any more than it has a built-in
meaning for short.

It does have a built-in /meaning/ to use == with enum. You can use it. :) If it
didn't have a meaning then you couldn't use it without defining it (as with a
struct).

But you do have a point in what you write below, even though it does not
contradict what you quoted.

I wasn't aware of what you write below, it's interesting.

The "usual arithmetic conversions" apply to
==, so you're counting on the conversion to int, and comparing
the int's. Which has the somewhat unexpected (and unpleasant,
IMHO) result that you can compare totally unrelated enum types
for equality. And in overload resolution (§13.6), there's no
"candidate operator function" for == with an enum.

To pit nicks, argh, pick nits, (1) the conversion is to int, unsigned int, long
or unsigned long, whichever is the first that can represent the arg type, and
(2) in §13.6 there is a candidate for == with enum arguments, namely after
promotion of arguments, there's just no candidate that has enum formal args.

But nit-picking aside, yes, interesting point.

I wonder whether the C++0x class-like enums will fix this?


[snip]
With regards to operator overloading, the standard doesn't use
the words "built-in type". It says that "An operator function
shall either be a non-static member function or be a non-member
function and have at least one parameter whose type is a class,
a reference to a class, an enumeration, or a reference to an
enumeration." For once, it's actually fairly clear and exact.

Ah. :)


Cheers,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,770
Messages
2,569,586
Members
45,088
Latest member
JeremyMedl

Latest Threads

Top