Различия в поиске имен между g++ и MSVS
Рассмотрим этот код:
#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();
}
Код предназначен для изучения того, как поиск имени работает в C++.
Если я скомпилирую эту программу с GNU C++ (версия 6.1.0), она напечатает:
N::f
::f
Но если я скомпилирую его с Microsoft Visual Studio 2015, он напечатает:
Base::f
Base::f
Какое поведение правильно и почему?
2 ответа
g++ соответствует стандарту здесь, а Visual C++ нет:
14.6.2 Зависимые имена [temp.dep]
3 В определении класса или шаблона класса область действия зависимого базового класса (14.6.2.1) не проверяется при поиске неквалифицированного имени ни в точке определения шаблона или члена класса, ни во время создания шаблона класса. или член.
Замена f()
с this->f()
найдет базового члена.
В определении функции функции g
имя f
рассматривается как функция, объявленная вне класса (в определении класса это имя не объявлено; f является зависимым именем).
template <typename T>
class X : public Base<T> {
public:
void g() {
T t;
f(t);
}
};
Таким образом, компилятор использует поиск ADL.
Однако, если написать явный вызов функции-члена
class X : public Base<T> {
public:
void g() {
T t;
this->f(t);
}
};
тогда вызов функции f
будет рассматриваться как вызов функции-члена базового класса.
Таким образом, кажется, что MS VC++ 2015 имеет ошибку.