Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Name lookup differences between g++ and MSVS

Tags:

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?

like image 693
oz1cz Avatar asked Aug 30 '16 12:08

oz1cz


People also ask

What is two phase name lookup?

Two-phase lookup consists of two parts: The lookup for non-dependent names during template definition, and the lookup for dependent names during template instantiation. Under /Zc:twoPhase-, the compiler doesn't do argument-dependent lookup separately from unqualified lookup.

What is conformance mode in Visual Studio?

Conformance mode on-by-default for new projects. This mode disables non-conforming C++ constructs that have existed in MSVC for years.

How do I change the version of C++?

Select the Configuration Properties > C/C++ > Language property page. In C++ Language Standard (or for C, C Language Standard), choose the language standard to support from the dropdown control, then choose OK or Apply to save your changes.

How can I change C++ compiler in Visual Studio?

In Visual Studio You can set compiler options for each project in its Visual Studio Property Pages dialog box. In the left pane, select Configuration Properties, C/C++ and then choose the compiler option category.


2 Answers

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.

like image 167
TemplateRex Avatar answered Oct 30 '22 12:10

TemplateRex


In the function definition of the function g the name f is considered as a function declared outside the class (within the class definition this name is not declared; f is a dependent name).

template <typename T>
class X : public Base<T> {
  public:
    void g() {
        T t;
        f(t);
    }
};

So the compiler uses the ADL lookup.

However if to write an explicit call of a member function

class X : public Base<T> {
  public:
    void g() {
        T t;
        this->f(t);
    }
};

then the call of the function f will be considered as a call of the member function of the base class..

Thus it seems that MS VC++ 2015 has a bug.

like image 26
Vlad from Moscow Avatar answered Oct 30 '22 12:10

Vlad from Moscow