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