ein*_*ica 4 c++ scope namespaces language-lawyer
考虑以下程序:
namespace foo {
namespace sub {
int f();
} // namespace sub
} // namespace foo
namespace bar {
namespace sub {
int g() {
using namespace foo;
return sub::f() + 1;
}
} // namespace sub
} // namespace bar
Run Code Online (Sandbox Code Playgroud)
我希望这可以编译,但是 - 它没有:
$ g++-6 -c a.cpp
a.cpp: In function ‘int bar::sub::g()’:
a.cpp:12:9: error: ‘f’ is not a member of ‘bar::sub’
return sub::f() + 1;
^~~
a.cpp:12:9: note: suggested alternative:
a.cpp:3:5: note: ‘foo::sub::f’
int f();
^
Run Code Online (Sandbox Code Playgroud)
也没有运气与铿锵:
$ clang++-6.0 -c a.cpp
a.cpp:12:9: error: no member named 'f' in namespace 'bar::sub'; did you mean 'foo::sub::f'?
return sub::f() + 1;
^~~~~~
foo::sub::f
a.cpp:3:5: note: 'foo::sub::f' declared here
int f();
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
它也知道我想要的功能!
现在,我明白,如果我同时拥有a foo::sub::f和a ,那么事情可能会模棱两可bar::sub::f.但是 - 即使我明确要求使用函数,为什么还要bar::sub"隐藏" ?foo::subfoo::sub
要清楚答案可能是什么:
动机:我编写了我的代码,以便函数之前的最后一个命名空间是方法名称的一部分,在某种意义上,如果没有预先添加命名空间,你将无法理解函数的作用.因此,我希望能够说出来,而不是sub_f()像我所说的那样.没有预先设置更长的名称空间路径,这样做很难做到.Csub::f()
[namespace.udir]说(强调我的):
-2- using-directive指定指定命名空间中的名称可以在using-directive出现在using-directive之后的范围内使用.在非限定名称查找(6.4.1)期间,名称看起来好像是在最近的封闭命名空间中声明的,其中包含using-directive和指定的命名空间. [注意:在此上下文中,"包含"表示"直接或间接包含". - 结束说明]
在您的示例中,"指定命名空间中的名称"只是foo::sub因为它是在命名空间中声明的唯一名称foo,而"包含using-directive和指定命名空间的最近的封闭命名空间"是全局命名空间.所以foo::sub出现(为了名称查找的目的)就好像它在全局命名空间中一样,如下所示:
namespace sub {
int f();
} // namespace sub
namespace bar {
namespace sub {
int g() {
return sub::f() + 1;
}
} // namespace sub
} // namespace bar
Run Code Online (Sandbox Code Playgroud)
现在应该更明显的是sub::f找不到任何东西.sub::f通过查找来查找起始的名称sub.它没有在封闭的命名空间(它bar::sub)中找到它,因此它在下一个最里面的封闭范围(它是bar)中查找并找到它sub.此时,对于sub停止的名称查找,它不会查找使用指令foo::sub可以看到的全局命名空间.
名称查找的下一步尝试在找到f的范围内查找sub,但f在找到的命名空间中没有,因此名称查找失败.
using-directives不像为命名空间的每个成员添加using声明那样工作,它们比using声明"弱".这样做的原因是,在命名空间中真正声明的名称优先于使用using指令可见的名称.罗德里戈对相关问题的回答更详细地解释了这一点.