【发布时间】:2019-07-09 12:16:46
【问题描述】:
考虑以下程序:
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
我希望它可以编译,但是 - 它没有:
$ 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();
^
clang 也没有运气:
$ 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.
它也知道我想要哪个功能!
现在,我知道如果我在这里同时拥有 foo::sub::f 和 bar::sub::f,事情可能会变得模棱两可。但是 - 为什么 bar::sub “隐藏” foo::sub 即使我明确要求使用 foo::sub 函数?
要清楚答案可能是什么:
- 解释为什么这是(最)合理的行为,而我的期望是不合理的。
- 在 C++ 标准中采用这种方式的基本原理。
- 引用标准的一句话说这需要是这样的;也许上下文会帮助我理解为什么会这样。
动机:我已经编写了我的代码,以便函数之前的最后一个命名空间是方法名称的一部分,从某种意义上说,如果不预先添加命名空间,您将无法理解函数的作用。因此,我不想像在C 中那样说sub_f(),而是希望能够说sub::f()。事实证明,如果不预先添加更长的命名空间路径,这样做是很困难的。
【问题讨论】:
-
两个相似的
sub令人困惑,你可以在那里有相似的功能。我认为编译器告诉你要明确是正确的(尽管using namespace foo)。 -
你并没有真正明确地要求
foo::sub,你只是要求找到恰好在foo中的sub::f -
@MatthieuBrucher: 1. 我很明确 - 我说过我想使用
foo::sub函数。如果不进入单一功能级别,我不能比这更明确。 2. 如果函数名称不冲突,就不会造成混淆——至少在我明确表示的时候。 -
您没有明确要求使用
foo::sub,您只是导入了namespace foo。那是非常不同的。如果您想明确,请使用foo::sub::f。这是明确的。
标签: c++ scope namespaces language-lawyer