Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The answer is clang is correct. However, the code could also fail as ambiguous according to the standard.</p> <p>If you look at 11.2p5 it has a relevant note (yes, I know notes are non-normative):</p> <blockquote> <p>[ Note: This class can be explicit, e.g., when a qualified-id is used, or implicit, e.g., when a class member access operator (5.2.5) is used (including cases where an implicit “this->” is added). <strong>If both a class member access operator and a qualified-id are used to name the member (as in <code>p-&gt;T::m</code>), the class naming the member is the class denoted by the nested-name-specifier of the qualified-id (that is, T)</strong>. —end note ]</p> </blockquote> <p>What this note means, is that if you add <code>this-&gt;</code> to <code>C::x = 2;</code> then <code>C</code> is the class naming the member and <a href="http://liveworkspace.org/code/F2wWf%240" rel="nofollow">gcc 4.7.2 correctly fails when this is the case</a>.</p> <p>Now the question is <strong>Who is the class naming the member for</strong> <code>C::x</code>? The <code>naming class</code> is specified by the same <code>11.2p5</code>:</p> <blockquote> <p>The access to a member is affected by the class in which the member is named. <strong>This naming class is the class in which the member name was looked up and found.</strong></p> </blockquote> <p>Now, name lookup for class members is specified in 10.2, and after reading all of it, I have concluded that <code>x</code> is the <strong>union</strong> of subobject sets as per:</p> <blockquote> <p>Otherwise, the new S(f, C) is a lookup set with the shared set of declarations and the union of the subobject sets.</p> </blockquote> <p>Which means that according to member lookup rules <code>x</code> can be either from <code>B</code> <em>or</em> <code>A</code>! This makes the code ill-formed as: <code>Name lookup can result in an ambiguity, in which case the program is ill-formed.</code> However, this ambiguity <strong>can</strong> be resolved as per 10.2p8:</p> <blockquote> <p>Ambiguities can often be resolved by qualifying a name with its class name.</p> </blockquote> <p>And from the <a href="https://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?sortby=rev&amp;r1=97677&amp;r2=97676&amp;pathrev=97677" rel="nofollow">Clang source</a>, we can see that is what they chose to do:</p> <pre><code>// If the member was a qualified name and the qualified referred to a // specific base subobject type, we'll cast to that intermediate type // first and then to the object in which the member is declared. That allows // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as: // // class Base { public: int x; }; // class Derived1 : public Base { }; // class Derived2 : public Base { }; // class VeryDerived : public Derived1, public Derived2 { void f(); }; // void VeryDerived::f() { // x = 17; // error: ambiguous base subobjects // Derived1::x = 17; // okay, pick the Base subobject of Derived1 // } </code></pre> <p>However, note the <code>can</code> in the wording of the above quote: <code>often can be resolved</code>. This means that <strong>they do not necessarily have to be resolved</strong>. So, I think according to the standard the code should fail as ambiguous or as a private member access failure.</p> <p><strong>EDIT</strong></p> <p>There is some contention about the interpretation of <code>can</code> and as to whether a ambiguity occurs here. I found <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#39" rel="nofollow">Defect report 39. Conflicting ambiguity rules</a> talks about this issue.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload