Search code examples
c++templatesbase-classname-lookupdependent-name

Name lookup differences between g++ and MSVS


Consider this code:

#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();
}

The code is intended to investigate how name lookup works in C++.

If I compile this program with GNU C++ (version 6.1.0), it prints:

N::f
::f

But if I compile it with Microsoft Visual Studio 2015, it prints:

Base::f
Base::f

Which is the correct behaviour, and why?


Solution

  • g++ is Standard compliant here, and Visual C++ not:

    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.