c++ - studio - Diferencias de búsqueda de nombres entre g++ y MSVS
visual studio installer (2)
Considere este código:
#include <iostream>
namespace N {
class A {};
void f(A a) { std::cout << "N::f/n"; }
}
void f(int i) { std::cout << "::f/n"; }
template <typename T>
class Base {
public:
void f(T x) { std::cout << "Base::f/n"; }
};
template <typename T>
class X : public Base<T> {
public:
void g() {
T t;
f(t);
}
};
int main()
{
X<N::A> x1;
x1.g();
X<int> x2;
x2.g();
}
El código está destinado a investigar cómo funciona la búsqueda de nombres en C ++.
Si compilo este programa con GNU C ++ (versión 6.1.0), se imprime:
N::f
::f
Pero si lo compilo con Microsoft Visual Studio 2015, se imprime:
Base::f
Base::f
¿Cuál es el comportamiento correcto y por qué?
En la definición de la función de la función g
el nombre f
se considera una función declarada fuera de la clase (dentro de la definición de la clase este nombre no se declara; f es un nombre dependiente).
template <typename T>
class X : public Base<T> {
public:
void g() {
T t;
f(t);
}
};
Así que el compilador usa la búsqueda ADL.
Sin embargo, si para escribir una llamada explícita de una función miembro
class X : public Base<T> {
public:
void g() {
T t;
this->f(t);
}
};
entonces la llamada de la función f
se considerará como una llamada de la función miembro de la clase base.
Por lo tanto, parece que MS VC ++ 2015 tiene un error.
g ++ es compatible con el estándar aquí, y Visual C ++ no:
14.6.2 Nombres dependientes [temp.dep]
3 En la definición de una clase o plantilla de clase, el alcance de una clase base dependiente (14.6.2.1) no se examina durante la búsqueda de nombre no calificado en el punto de definición de la plantilla de clase o miembro o durante una instanciación de la plantilla de clase o miembro.
Reemplazando f()
con this->f()
encontrará el miembro base.