Tipo de puntero al miembro de la clase base

Tengo un problema con respecto a los punteros de los miembros. El siguiente código no se compila utilizando CC de Oracle Solaris Studio 12.2 y cygwin GCC 4.3.4, pero funciona con 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;
}

En la penúltima línea, ambos compiladores mencionados anteriormente no pueden encontrar una coincidencia paraBar<B>::foo(int A::*). Escribí una prueba simple para confirmar que el tipo de expresión&B::x es en realidadint 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;
}

La siguiente solución funciona con GCC (aún no se ha probado con Oracle CC) pero falla con VC ++ debido a la ambigüedad:

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));
  }
};

Mi pregunta: ¿Qué comportamiento es correcto? Aparentemente, VC ++ realiza una transmisión implícita desdeint A::* aint B::* para satisfacer la llamada a la plantilla de función miembro, ¿no deberían los otros dos compiladores considerar hacer lo mismo?

Respuestas a la pregunta(1)

Su respuesta a la pregunta