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

时间:2016-12-29 12:28:49

标签: c++ gcc compiler-errors namespaces language-lawyer

void f() {}

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

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

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) {}

我的编译器是gcc 6.2.0。

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

1 个答案:

答案 0 :(得分:12)

  

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

是。简而言之,您不能通过不同的范围重载功能。根据{{​​3}}的规则,在f()中调用g()时,可以在命名空间f中找到名称test,然后查找名称停止; unqualified name lookup之后发生(基于找到的名称)。这意味着全局命名空间中的f()根本不会被考虑,即使它看起来更合适。

(强调我的)

  

对于不合格的名称,这是一个不显示的名称   右侧的范围解析运算符::,名称查找检查   范围如下所述,直到找到至少一个声明   任何类型,此时查找停止,没有其他范围   检查。

     

为了编译函数调用,编译器必须首先执行   名称查找,对于函数,可能涉及参数依赖   查找,对于函数模板,可以跟随模板   论证演绎。 如果这些步骤产生多个候选人   函数,然后执行重载分辨率以选择功能   实际上会被调用。

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

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