20

考虑这段代码:

#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

哪个是正确的行为,为什么?

4

2 回答 2

15

g++ 在这里是标准兼容的,而 Visual C++ 不是:

14.6.2 Dependent names [temp.dep]

3 In the definition of a class or class template, the scope of a dependent base class (14.6.2.1) is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.

Replacing f() with this->f() will find the base member.

于 2016-08-30T13:40:13.457 回答
6

在函数的函数定义中,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 似乎有一个错误。

于 2016-08-30T13:06:03.240 回答