考虑以下代码片段
#include <iostream>
#include <memory>
namespace Foo {
void bar() {
std::cout<<"FOO::BAR"<<std::endl;
}
}
namespace Spam {
void bar() {
std::cout<<"SPAM::BAR"<<std::endl;
}
}
namespace fallbacks {
using Foo::bar;
}
namespace Spam {
using namespace fallbacks;
}
int main() {
Spam::bar();
}
输出
SPAM::BAR
我知道在这种情况下,如果垃圾邮件包含该成员,它将引用该成员。但是,如果没有,则会找到 using 指令的名称并引用 fallbacks::bar。
但我找不到任何可靠的来源来支持上述说法。
最佳答案
该标准的
第 3.4.3 节 描述了限定名称查找。特别是,部分 3.4.3.2 描述了命名空间成员的查找。
3.4.3.2.2: For a namespace
X
and namem
, the namespace-qualified lookup setS(X,m)
is defined as follows: LetS'(X,m)
be the set of all declarations ofm
inX
and the inline namespace set ofX
(7.3.1). IfS'(X,m)
is not empty,S(X,m)
isS'(X,m)
; otherwise,S(X,m)
is the union ofS(N_i,m)
for all namespacesN_i
nominated by using-directives inX
and its inline namespace set.
(来源:ISO/IEC 14882:2011:C++ 标准)
给出如下例子:
int x;
namespace Y {
void f(float);
void h(int);
}
namespace Z {
void h(double);
}
namespace A {
using namespace Y;
void f(int);
void g(int);
int i;
}
namespace B {
using namespace Z;
void f(char);
int i;
}
namespace AB {
using namespace A;
using namespace B;
void g();
}
void h()
{
AB::g(); // g is declared directly in AB,
// therefore S is { AB::g() } and AB::g() is chosen
AB::f(1); // f is not declared directly in AB so the rules are
// applied recursively to A and B;
// namespace Y is not searched and Y::f(float)
// is not considered;
// S is { A::f(int), B::f(char) } and overload
// resolution chooses A::f(int)
AB::f(’c’); // as above but resolution chooses B::f(char)
AB::x++; // x is not declared directly in AB, and
// is not declared in A or B , so the rules are
// applied recursively to Y and Z,
// S is { } so the program is ill-formed
AB::i++; // i is not declared directly in AB so the rules are
// applied recursively to A and B,
// S is { A::i , B::i } so the use is ambiguous
// and the program is ill-formed
AB::h(16.8); // h is not declared directly in AB and
// not declared directly in A or B so the rules are
// applied recursively to Y and Z,
// S is { Y::h(int), Z::h(double) } and overload
// resolution chooses Z::h(double)
}
(来源:ISO/IEC 14882:2011:C++ 标准)
在您的示例中,如果 Spam
包含 bar
,则集合 S
包含 {Spam::bar}
查找停止。如果命名空间 Spam
不包含 bar
,则通过 using
指令在 Spam 中声明的任何命名空间或 bar
将被搜索,并递归应用此逻辑,直到:
- 发现一个命名空间包含
bar
,或者 - 可能的搜索路径已经用尽,在这种情况下程序是病式的。
关于c++ - 确定哪个成员在 namespace 中可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24930921/