Topic: Overloading resolution


Author: hf@informatik.uni-karlsruhe.de (Harald Fuchs)
Date: 01 Aug 1994 12:57:06 GMT
Raw View
I have a problem with the resolution of overloaded member functions in
conjunction with inheritance.  Consider the following example:

 1 struct A {};
 2 struct B: public A {};
 3 struct C: public B {};
 4
 5 struct X {
 6   void f (A);
 7   void f (B);
 8 };
 9
10 main () {
11   X x;
12   A a;
13   B b;
14   C c;
15   x.f (a);
16   x.f (b);
17   x.f (c);
18 }

One compiler accepted this program and called X::f(B) on line 17 (as I
expected), another one found no match.  I was about to file a bug
report, but after inspecting the ARM I'm not so sure: page 318
mentions only pointer and reference conversions, but not object
slicing.  Who's right?
--
Harald Fuchs <hf@informatik.uni-karlsruhe.de>




Author: jason@cygnus.com (Jason Merrill)
Date: Mon, 1 Aug 1994 20:42:45 GMT
Raw View
>>>>> Harald Fuchs <hf@informatik.uni-karlsruhe.de> writes:

> I have a problem with the resolution of overloaded member functions in
> conjunction with inheritance.  Consider the following example:

>  1 struct A {};
>  2 struct B: public A {};
>  3 struct C: public B {};
>  4
>  5 struct X {
>  6   void f (A);
>  7   void f (B);
>  8 };
>  9
> 10 main () {
> 11   X x;
> 12   A a;
> 13   B b;
> 14   C c;
> 15   x.f (a);
> 16   x.f (b);
> 17   x.f (c);
> 18 }

> One compiler accepted this program and called X::f(B) on line 17 (as I
> expected), another one found no match.  I was about to file a bug
> report, but after inspecting the ARM I'm not so sure: page 318
> mentions only pointer and reference conversions, but not object
> slicing.  Who's right?

The first compiler.  'c' can be converted to a B using the B copy
constructor.

Jason




Author: hf@informatik.uni-karlsruhe.de (Harald Fuchs)
Date: 02 Aug 1994 14:58:57 GMT
Raw View
In article <JASON.94Aug1134245@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:

>>>>>> Harald Fuchs <hf@informatik.uni-karlsruhe.de> writes:
>> I have a problem with the resolution of overloaded member functions in
>> conjunction with inheritance.  Consider the following example:

>> 1 struct A {};
>> 2 struct B: public A {};
>> 3 struct C: public B {};
>> 4
>> 5 struct X {
>> 6   void f (A);
>> 7   void f (B);
>> 8 };
>> 9
>> 10 main () {
>> 11   X x;
>> 12   A a;
>> 13   B b;
>> 14   C c;
>> 15   x.f (a);
>> 16   x.f (b);
>> 17   x.f (c);
>> 18 }

>> One compiler accepted this program and called X::f(B) on line 17 (as I
>> expected), another one found no match.  I was about to file a bug
>> report, but after inspecting the ARM I'm not so sure: page 318
>> mentions only pointer and reference conversions, but not object
>> slicing.  Who's right?

> The first compiler.  'c' can be converted to a B using the B copy
> constructor.

... or it can be converted to an A using the A copy constructor.
While I agree that the behavior of the first compiler (it was g++,
BTW) sounds logical to me, I would like to have the exact chapter and
verse in the ARM (something like "a conversion from C to B is to be
preferred over a conversion from C to A") in order to file a bug
report.
--
Harald Fuchs <hf@informatik.uni-karlsruhe.de>




Author: jason@cygnus.com (Jason Merrill)
Date: Wed, 3 Aug 1994 08:41:23 GMT
Raw View
>>>>> Harald Fuchs <hf@informatik.uni-karlsruhe.de> writes:

> In article <JASON.94Aug1134245@deneb.cygnus.com>, jason@cygnus.com (Jason Merrill) writes:
>>>>>>> Harald Fuchs <hf@informatik.uni-karlsruhe.de> writes:
>>> I have a problem with the resolution of overloaded member functions in
>>> conjunction with inheritance.  Consider the following example:

>>> 1 struct A {};
>>> 2 struct B: public A {};
>>> 3 struct C: public B {};
>>> 4
>>> 5 struct X {
>>> 6   void f (A);
>>> 7   void f (B);
>>> 8 };
>>> 9
>>> 10 main () {
>>> 11   X x;
>>> 12   A a;
>>> 13   B b;
>>> 14   C c;
>>> 15   x.f (a);
>>> 16   x.f (b);
>>> 17   x.f (c);
>>> 18 }

>>> One compiler accepted this program and called X::f(B) on line 17 (as I
>>> expected), another one found no match.  I was about to file a bug
>>> report, but after inspecting the ARM I'm not so sure: page 318
>>> mentions only pointer and reference conversions, but not object
>>> slicing.  Who's right?

>> The first compiler.  'c' can be converted to a B using the B copy
>> constructor.

> ... or it can be converted to an A using the A copy constructor.
> While I agree that the behavior of the first compiler (it was g++,
> BTW) sounds logical to me, I would like to have the exact chapter and
> verse in the ARM (something like "a conversion from C to B is to be
> preferred over a conversion from C to A") in order to file a bug
> report.

Well, let's see.  Calling f(B) involves this conversion sequence:

lval C -s-> lval B -l-> rval B

Calling f(A) involves this conversion sequence:

lval C -s-> lval A -l-> rval A

In both sequences, the dominant conversion is the standard conversion from
an lvalue of a derived type to an lvalue of a base type.  Since B is
derived from A and C is derived from B, converting from C to B is better
than converting from C to A.

Oh, and disregard what I said before about the copy constructor.  What
we're actually dealing with here is an lvalue conversion, not a
user-defined conversion.  If it were the latter, it would be dominant and
the call would be ambiguous.

This analysis is based on X3J16/94-0{080,110,111}, and not on anything in
the ARM or WP; the notion of lvalue conversions is very recent.

Jason