Prev: shared_ptr declaration in if-statement ?
Next: sizeof: Why parentheses needed when used with data types (when not required with variables)
From: David Vandevoorde on 14 Nov 2009 12:33 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 15 Nov 2009 21:27
"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! ] |