C++ 确定命名空间中哪个成员可见
考虑下面的代码片段C++ 确定命名空间中哪个成员可见,c++,C++,考虑下面的代码片段 #include <iostream> #include <memory> namespace Foo { void bar() { std::cout<<"FOO::BAR"<<std::endl; } } namespace Spam { void bar() { std::cout<<"SPAM::BAR"<<std::endl; }
#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();
}
我理解,在这种情况下,如果垃圾邮件包含该成员,它将引用它。但是,如果没有,那么将找到using指令的名称并引用fallbacks::bar
但我找不到任何真实的来源来支持上述说法。本标准第3.4.3节描述了限定名称查找。特别是,部分描述了命名空间成员的查找 3.4.3.2.2:对于名称空间
X
和名称m
命名空间限定的查找集S(X,m)
定义如下:Let
S'(X,m)
是X
中m
的所有声明和内联
X
(7.3.1)的命名空间集。如果S'(X,m)
不为空,则S(X,m)
为空
S'(X,m)
;否则,S(X,m)
是所有名称空间的S(N_i,m)
的并集
N_i
通过使用X
中的指令及其内联命名空间集指定
< P>(来源:ISO/IEC 1488∶2011:C++标准)< /P>
给出了以下示例:
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)
}
< P>(来源:ISO/IEC 1488∶2011:C++标准)< /P>
在您的示例中,如果Spam
包含bar
,则集合S
包含{Spam::bar}
,并停止查找。如果名称空间Spam
不包含bar
,则将搜索通过使用指令在Spam中声明的任何名称空间或bar
,并递归应用此逻辑,直到:
找到包含条的命名空间,或
可能的搜索路径已用尽,在这种情况下,程序格式不正确
<> >在C++标准第3.4.3.2命名空间成员的以下段落中描述了限定名称的相应名称查找
2对于名称空间X和名称m,名称空间限定查找集S(X,m)的定义如下:设S0(X,m)是X中所有m声明的集合,内联名称空间集是X(7.3.1)。如果S0(X,m)不是空的,则S(X,m)是S0(X,m);否则,S(X,m)是通过使用X中的指令及其内联名称空间集中指定的所有名称空间Ni的S(Ni,m)的并集
3给定X::m(其中X是用户声明的名称空间)或给定::m(其中X是全局名称空间),如果S(X,m)是空集,则程序的格式不正确。否则,如果S(X,m)正好有一个成员,或者如果引用的上下文是使用声明(7.3.3),则S(X,m)是m的所需声明集。否则,如果m的使用不允许从S(X,m)中选择唯一声明,则程序的格式不正确
在您的例子中,如果要跟随引号“让S0(X,m)是X中m的所有声明集,内联名称空间集是X(7.3.1)。如果S0(X,m)不是空的,S(X,m)是S0(X,m);”S(Spam,bar)由Spam中bar的一个声明组成。这个声明是垃圾邮件中唯一的声明。所以这个名字会被找到 我想你被ADL或类似的东西弄糊涂了,这里没有使用Foo,也没有完全限定,所以没有bar的垃圾邮件只会导致错误。如果名称空间回退
包含使用Foo::bar
,而不是使用Spam::bar
,这个问题更有意义。这就是我的本意吗?安德鲁:是的,我的错,这就是我的本意。谢谢。这是有道理的。
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)
}