Llamada al método C++ y ambigüedad de resolución de alcance de tipo
types scope (2)
Espero que el título realmente describa lo que quería preguntar ...
Escribí un fragmento de código que se compila con gcc y funciona como pretendía. Sin embargo, no se compila con llvm y el código se ejecuta de manera diferente cuando se compila con icc!
Aquí hay un ejemplo del problema:
#include <iostream>
using std::cout; using std::endl;
class A {
public:
virtual void foo() { cout << "A::foo()" << endl; }
};
class B : public A {
public:
typedef A base;
virtual void foo() { cout << "B::foo()" << endl; }
};
int main() {
typedef B base;
base* bp = new B();
bp->base::foo();
}
salida gcc: A :: foo ()
salida icc: B :: foo ()
¿Alguien podría explicar qué dice la norma sobre este caso?
Creo que esta parte de la norma es relevante:
3.4.3.1 Miembros de la clase [class.qual]
1) Si el especificador de nombre anidado de un id calificado califica a una clase, el nombre especificado después de que el especificador de nombre anidado se busque en el alcance de la clase (10.2), excepto en los casos que se enumeran a continuación. El nombre representará a uno o más miembros de esa clase o de una de sus clases base (Cláusula 10). [Nota: Se puede hacer referencia a un miembro de la clase utilizando un id calificado en cualquier punto de su alcance potencial (3.3.7). —Endente final] Las excepciones a la regla de búsqueda de nombres de arriba son las siguientes:
- se busca un nombre de destructor como se especifica en 3.4.3;
- un id de tipo de conversión de un id de función de conversión se busca de la misma manera que un id de tipo de conversión en un acceso de miembro de clase (ver 3.4.5);
- los nombres en una plantilla-argumento de una plantilla-id son buscados en el contexto en el que ocurre la expresión-postfix completa.
- la búsqueda de un nombre especificado en una declaración de uso (7.3.3) también encuentra nombres de clase o enumeración ocultos dentro del mismo ámbito (3.3.10).
base::
en este caso parece "nominar" a una clase, por lo que la búsqueda se realiza en el ámbito de la clase. No veo cómo podría aplicarse ninguno de los casos de excepción, por lo que es el alcance de la clase, ya que dicha base
es equivalente a A
(5.1.1-8 indica que es un ID calificado en ese caso y que se aplica 3.4.3.1)
De C ++ 11, §3.4.5 / 4:
Si el id-expresión en un acceso de miembro de clase es un id-calificado del formularioclass-name-or-namespace-name::... el nombre de la clase nombre-o-espacio de nombres que sigue a. o -> el operador se busca primero en la clase de la expresión del objeto y se usa el nombre, si se encuentra. De lo contrario, se busca en el contexto de toda la expresión postfix.
No creo que pueda ser más claro. Esto encuentra B::base
, por lo que la salida debería ser A::foo()
.