I have a problem regarding member pointers. The following code fails to compile using both Oracle Solaris Studio 12.2's CC and cygwin GCC 4.3.4 but works with 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;
}
At the next to last line both compilers mentioned above fail to find a match for Bar<B>::foo(int A::*). I wrote a simple test to confirm that the type of the expression &B::x is actually int 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;
}
The following workaround works with GCC (not tested with Oracle CC yet) but fails with VC++ due to ambiguity:
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));
  }
};
My question:
Which behavior is correct? Apparently VC++ does an implicit upcast from int A::* to int B::* to satisfy the call to the member function template, shouldn't the other two compilers consider doing the same?