为什么gcc会隐藏全局命名空间中的重载函数?

xml*_*lmx 6 c++ gcc namespaces compiler-errors language-lawyer

void f() {}

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

int main()
{
    test::g();
}
Run Code Online (Sandbox Code Playgroud)

g ++ -std = c ++ 1z main.cpp编译它,输出如下:

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) {}
Run Code Online (Sandbox Code Playgroud)

我的编译器是gcc 6.2.0.

为什么gcc会隐藏全局命名空间中的重载函数?这符合C++标准吗?

son*_*yao 12

为什么gcc会隐藏全局命名空间中的重载函数?这符合C++标准吗?

是.简而言之,您不能通过不同的范围重载功能.根据规则不合格的名称查找,为的调用f()g(),这个名字f可以命名空间内发现test,那么名称查找停止; 之后发生重载解析(基于找到的名称).这意味着f()在全局命名空间中根本不会被考虑,即使它看起来更合适.

(强调我的)

对于非限定名称,即名称不在范围解析运算符::右侧的名称,名称查找检查范围如下所述,直到它找到任何类型的至少一个声明,此时查找停止并且不会审查其他范围.

为了编译函数调用,编译器必须首先执行名称查找,对于函数,可能涉及依赖于参数的查找,对于函数模板,可以跟随模板参数推断.如果这些步骤产生多个候选函数,则执行重载解析以选择实际调用的函数.

您可以使用using将名称引入同一范围,即使它们成为实际的重载函数.

namespace test
{
    using ::f;        // introduce the name from global namespace
    void f(int) {}    
    void g() { f(); } // fine
}
Run Code Online (Sandbox Code Playgroud)

  • tl; dr:这是一个已知的C++怪癖,与派生类中的"重载"隐藏基类中的变量的原因相同[http://stackoverflow.com/q/1628768/560648],要求`在某些情况下使用Base :: foo`. (2认同)