Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does gcc hide overloaded functions in the global namespace?

void f() {}

namespace test
{
void f(int) {}    
void g() { f(); } // error in gcc 6.2.0
}

int main()
{
    test::g();
}

Compile it with g++ -std=c++1z main.cpp, the output is as follows:

main.cpp: In function 'void test::g()':
main.cpp:9:4: error: too few arguments to function 'void test::f(int)'
  f(); // error in gcc
    ^
main.cpp:5:6: note: declared here
 void f(int) {}

My compiler is gcc 6.2.0.

Why does gcc hide overloaded functions in the global namespace? Is this conforming to the C++ standard?

like image 963
xmllmx Avatar asked Dec 29 '16 12:12

xmllmx


1 Answers

Why does gcc hide overloaded functions in the global namespace? Is this conforming to the C++ standards?

Yes. In short, you can't overload functions through different scopes. According to the rule of unqualified name lookup, for the invoking of f() in g(), the name f could be found inside the namespace test, then the name lookup stops; overload resolution takes place after that (based on the names found). That means f() in global namespace won't be considered at all even it looks more appropriate here.

(emphasis mine)

For an unqualified name, that is a name that does not appear to the right of a scope resolution operator ::, name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

In order to compile a function call, the compiler must first perform name lookup, which, for functions, may involve argument-dependent lookup, and for function templates may be followed by template argument deduction. If these steps produce more than one candidate function, then overload resolution is performed to select the function that will actually be called.

You can use using to introduce the names into the same scope, i.e. to make them actual overloaded functions.

namespace test
{
    using ::f;        // introduce the name from global namespace
    void f(int) {}    
    void g() { f(); } // fine
}
like image 114
songyuanyao Avatar answered Oct 19 '22 09:10

songyuanyao