Covariant returns
Jason Merrill
jason at cygnus.com
Thu Jul 6 17:47:00 UTC 2000
>>>>> Jim Dehnert <dehnert at baalbek.engr.sgi.com> writes:
> Suppose we have:
> class A { ... };
> class B: public A { ... };
> class V {
> ...
> virtual A* f ();
> ...
> };
> class W: virtual public V {
> ...
> virtual B* f ();
> ...
> };
> W *w;
> V *v = w;
> Suppose initially that no bases are primary. (And check my example
> before you believe anything...)
> Now, if I call w->f(), I get the basic W::f, with no adjustments.
> This is what should happen if I use the "normal" entry for f in the W
> vtable.
Yes.
> If I call v->f(), it's more complicated. I get a thunk which (a)
> adjusts v to a W*, (b) calls W::f, and (c) adjusts the resulting B*
> back to an A*. This is what should happen if I use the "normal" entry
> for f in the V-in-W secondary vtable.
Yes.
> So far, so good. The W vtable contains the overriding W::f vptr.
> The V-in-W secondary vtable contains the thunk vptr. Nothing special
> for the covariant return types, except that the thunk is messier.
Yes. I thought that Mark was suggesting that the W vtable in this case
would have two entries for f; that's what I was disagreeing with.
> I note, as an aside so far, that if W did not override V::f, we would
> have a "promoted" vptr for it in the W vtable to make it easier to
> call. But that has nothing to do with covariant return types either.
Yes.
> Next, suppose V is the primary base of W. Now they share a vtable, and
> therefore an f vptr. If the f's had the same return type, there would
> be no adjustments to be made, and that f vptr could just point to the
> overriding W::f. But because they have covariant return types, v->f()
> must still adjust on return, so the "shared" vptr must do that, and W's
> vtable needs to have another entry for the "normal" W::f vptr.
Yes, we will have two entries in the primary vtable. One is logically part
of the V-in-W vtable, one is logically part of the W vtable.
> Finally, suppose we have:
> class X: virtual public W {
> ...
> };
> Now, we specify that the vptrs from W get promoted to the X vtable.
> That presumably means both of them in the case at hand. Correct?
I disagree with this, too. Only the W copy should be promoted. The V copy
is only called through a V*, so there's no reason to promote it.
Each class' vtable only needs one entry per function, regardless of
covariant returns. The only exception comes from the case where two
classes share a vtable, but that exception is only physical; the logical
rule stands.
Jason
More information about the cxx-abi-dev
mailing list