Typ des Zeigers auf das Mitglied der Basisklasse

Ich habe ein Problem mit Mitgliedszeigern. Der folgende Code kann nicht mit Oracle Solaris Studio 12.2 CC und cygwin GCC 4.3.4 kompiliert werden, funktioniert jedoch mit Microsoft Visual C ++ 2010:

struct A {
  int x;
};

struct B : public A {
};

template<typename T> class Bar {
public:
  template<typename M> void foo(M T::*p);
};

int main(int, char *[]) {
    Bar<B> bbar;
    bbar.foo(&B::x);
    return 0;
}

In der vorletzten Zeile finden beide oben genannten Compiler keine Übereinstimmung fürBar<B>::foo(int A::*). Ich schrieb einen einfachen Test, um zu bestätigen, dass der Typ des Ausdrucks&B::x ist eigentlichint A::*:

// ...

static void foo(int A::*p) {
  std::cout << "A" << std::endl;
}

static void foo(int B::*p) {
  std::cout << "B" << std::endl;
}

int main(int, char *[]) {
    foo(&B::x);  // prints "A", even on MS VC++ 2010 
    return 0;
}

Die folgende Problemumgehung funktioniert mit GCC (noch nicht mit Oracle CC getestet), schlägt jedoch mit VC ++ aufgrund von Mehrdeutigkeiten fehl:

template<typename T> class Bar {
public:
  template<typename M> void foo(M T::*p);
  template<typename M, typename _T_base> inline void foo(M _T_base::*p) {
      foo(static_cast<M T::*>(p));
  }
};

Meine Frage: Welches Verhalten ist richtig? Anscheinend macht VC ++ einen impliziten Upcast vonint A::* zuint B::* Sollten die beiden anderen Compiler nicht in Betracht ziehen, dasselbe zu tun, um den Aufruf der Memberfunktionsvorlage zu erfüllen?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage