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 ++标准吗?
答案 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
}