From: David Vandevoorde on
On Nov 13, 3:42 pm, David Vandevoorde <daveed.vandevoo...(a)gmail.com>
wrote:
[...]
> Now, if ordinary inheritance is used instead, we find the same types
> again, but this time the DefaultPolicies in which we find P3 (three
> times) are base classes of Policy3_is.

Correction: are NOT base classes of Policy3_is. Hence...

> So the dominance rule does not
> apply and the compiler cannot choose between the two P3 types.

Daveed


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

From: Trevor Vaughan on

"David Vandevoorde" <daveed.vandevoorde(a)gmail.com> wrote:

> Virtual inheritance ensures that there is only one base class
> DefaultPolicies (in the original example; see also Figure 16.1 in
> the book). When you write Policies::P3 in the BreadSlicer template,
> a lookup is performed and finds two types P3: The one in Policy3_is
> (found once) and the one in DefaultPolicies (found three times, via
> Discriminator<..., 2>, Discriminator<..., 3>, and Discriminator
> <..., 4>). However, DefaultPolicies is always a base class of
> Policy3_is, so the "domination rule" applies and the type from the
> more derived class is selected (i.e., Policy3_is).
>
> Now, if ordinary inheritance is used instead, we find the same
> types again, but this time the DefaultPolicies in which we find P3
> (three times) are NOT base classes of Policy3_is. So the dominance
> rule does not apply and the compiler cannot choose between the two
> P3 types.

I think I get it now:

---BEGIN CODE---

#include <iostream>

struct A
{
typedef int T;
};

struct B1 : /*virtual*/ A
{
typedef double T;
};

struct B2 : /*virtual*/ A
{
};

struct C : B1, B2
{
};

int main()
{
C::T x = 42;
std::cout << "x = " << x << std::endl;

return 0;
}

---END CODE---

Output on g++-4:

(1) With B1 and B2 both inheriting virtually from A, the program
compiles OK and prints: x = 42

(2) With either occurrence of 'virtual' (or both) commented out, the
following compiler error is generated:

main.cpp: In function 'int main()':
main.cpp:23: error: reference to 'T' is ambiguous
main.cpp: 5: error: candidates are: typedef int A::T
main.cpp:10: error: typedef double B1::T
[etc.]

(This time the g++ error is actually helpful!)

As I now understand it...

Lookup of C::T in main() finds both B1::T and A::T (the latter via
B2). With non-virtual inheritance, B1::T hides its own inherited
A::T, but cannot hide B2's inherited A::T, so both B1::T and A::T are
visible and C::T is therefore ambiguous.

But if both B1 and B2 inherit A virtually, the domination rule
applies and the most-derived declaration (in this case, B1::T) hides
all the others, even where these others are reachable "along a path
through the sub-object lattice that does not pass through the hiding
declaration." (to quote the C++98 Standard, Section 10.2/6)

Is this explanation correct?

I had noted that the _C++ Templates_ book refers to this Section of
the Standard in relation to the domination rule (footnote 2 on page
289), but, having never seen the Standard, I didn't realise that this
"domination rule" refers to virtual inheritance.

Since my original post I have discovered a draft version (2 Dec 1996)
of (most of) the C++98 Standard on Bjarne Stroustrup's web site:
ftp://ftp.research.att.com/pub/c++std/WP/CD2. But without Daveed's
explanation I doubt that I would ever have fathomed what Section
10.2/6 is getting at. (Stroustrup also has a draft C++0x Standard at:
http://www.research.att.com/~bs/SC22-N-4411.pdf. The domination rule
is now a Note in Section 10.2/10-11.)

Thanks to Daveed Vandevoorde and Joe Smith for your help.

P.S.
The _C++ Templates_ footnote referenced above (p. 289) also mentions
that there is a discussion of this issue in Section 10.1.1 of the
ARM. As I don't have access to a copy of this book, I will be
grateful if anyone who does can provide a short summary of the ARM's
rationale for the dominance rule.

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