Kla*_*aim 7 c++ gcc visual-c++ c++11
我认为我很了解名字查找(在观看了几个关于它的视频并阅读了很多内容之后)但我只是遇到了这个案例:
#include <iostream>
namespace test{
struct Id
{};
void do_something( const Id& ){ std::cout << "Hello, World!" << std::endl; }
class Test
{
public:
void do_something() { std::cout << "WTF!" << std::endl; }
void run()
{
Id id;
do_something( id ); // doesn't compile
}
};
}
int main()
{
test::Test my_test;
my_test.run();
}
Run Code Online (Sandbox Code Playgroud)
指向的行不会编译(在GCC4.8和VC11U2上),因为它试图使用成员函数 test::Test::do_something()
而不是命名空间作用域test::do_something( const Id& )
,这似乎是唯一可能的候选者.
显然,成员函数名称隐藏了命名空间范围的名称,这对我来说是令人惊讶的,因为我记得在其他上下文中使用几乎相似的代码而没有产生此问题(但最终条件可能会非常不同).
我的问题是:这些编译器是否符合标准?
(不幸的是,通过阅读标准文档很难理解名称查找,所以我需要专家确认)
我的问题是:这些编译器是否符合标准?
是.在重载决策决定哪些函数是可行的候选者(包括检查参数的数量)之前,编译器首先必须进行名称查找,以找到所有候选者,可行且不可行.在您的示例名称中,查找在找到成员后停止,do_something()
因此重载决策永远不会有机会决定命名空间范围是否可行.
3.4.1 [basic.lookup.unqual]/1:"在3.4.1中列出的所有情况下,搜索范围按照每个相应类别中列出的顺序搜索声明;名称查找在声明后立即结束找到了这个名字."
3.4.1 [basic.lookup.unqual]第8段列出了搜索名称的上下文,甚至还有一个能够准确回答你问题的例子.Test
在封闭命名空间之前搜索范围,并且如第1段所述,"一旦为名称找到声明,名称查找就会结束".
编译器将收集所有“候选名称”(除非涉及 ADL,否则它们将来自同一范围),然后尝试选择最佳匹配(如果有)。在任何情况下,失败的匹配都不会导致它尝试从备用范围中查找其他候选名称。
这与编译器首先执行重载解析,然后检查成员的公共/私有以查看它是否确实可访问的方式非常相似。
g++ 有一个方便的-Wshadow
选项来寻找阴影(不过我不确定它会特别警告这个选项)。