Рассмотрим этот код:
#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
Какое поведение правильно и почему?
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 имеет ошибку.