Различия в поиске имен между 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

Какое поведение правильно и почему?

20

Решение

g ++ соответствует стандарту здесь, а Visual C ++ нет:

14.6.2 Зависимые имена [temp.dep]

3 В определении класса или шаблона класса сфера действия
зависимый базовый класс (14.6.2.1) не рассматривается в течение неквалифицированного
поиск имени
либо в точке определения шаблона класса, либо
член или во время создания шаблона класса или члена.

Замена f() с this->f() найдет базового члена.

15

Другие решения

В определении функции функции 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 имеет ошибку.

6

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector