Search code examples
c++c++11name-lookup

C++ class member name lookup issues (regarding the wording of standard n3225)


I am very confused about the standard 10.2/13,

[ Note: Even if the result of name lookup is unambiguous, use of a name found in multiple subobjects might still be ambiguous (4.11, 5.2.5, 5.3.1, 11.2).—end note ] [ Example:

struct B1 {
  void f();
  static void f(int);
  int i;
};
struct B2 {
  void f(double);
};
struct I1: B1 { };
struct I2: B1 { };
struct D: I1, I2, B2 {
  using B1::f;
  using B2::f;
  void g() {
    f(); // Ambiguous conversion of this
    f(0); // Unambiguous (static)
    f(0.0); // Unambiguous (only one B2)
    int B1::* mpB1 = &D::i; // Unambiguous
    int D::* mpD = &D::i; // Ambiguous conversion
  }
};

I cannot see why this is unambiguous int B1::* mpB1 = &D::i; // Unambiguous

Visual C++, Gcc and CLang all say that it is ambiguous access to D::i!

The wording seems to be related to the core issue #39 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#39, and the final proposal is here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1626.pdf

I now find that the new algorithm-based wordings (10.2/3-10.2/6) are even more confusing because none of the note in 10.2/9, 10.2/10, 10.2/11, and 10.2/13 fully complies to 10.2/3-10.2/6. I can take 10.2/9-10.2/11 as exceptions, but I am especially confused about 10.2/13. I have no idea on the intention of 10.2/13.

How should the example in 10.2/13 be looked-up according to the 10.2/3-10.2/6? What's the intention of 10.2/13, i.e., what's the situation that 10.2/13 is considered as an exception of 10.2/3-10.2/6?

Please give me some hints. Thank you very much.


After some thinking, I think the intention of 10.2/13 is clearer to me.

int B1::* mpB1 = &D::i; // Unambiguous

This should be unambiguous and the current compilers are wrong on this. This is unambiguous because pointer to class members initialization doesn't involve in accessing the object yet.

int D::* mpD = &D::i; // Ambiguous conversion

This actually means when convert from int B1::*mpB1 to int D::*mpD, the conversion is ambiguous due to ambiguous base classes.


Solution

  • This:

    int B1::* mpB1 = &D::i; // Unambiguous
    

    Is unambiguous because the result is being assigned to a pointer to member of class B.
    So it don't matter which i is chosen as the offset is relative to a B member (not the parent D class).

    So it is unambiguous to you and me but I don't think the compiler can handle it.