确定命名空间中可见的成员

时间:2014-07-24 10:11:33

标签: 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;
    }
}
namespace fallbacks {
    using Foo::bar;
}

namespace Spam {
    using namespace fallbacks;
}

int main() {
    Spam::bar();
}

输出

SPAM::BAR

据我所知,在这种情况下,如果Spam包含该成员,它将引用它。但是如果没有,那么将找到using指令的名称并引用fallbacks :: bar。

但是我找不到任何可靠的来源来支持上述陈述。

2 个答案:

答案 0 :(得分:5)

该标准的

第3.4.3节描述了限定名称查找。特别是,部分 3.4.3.2 描述了命名空间成员的查找。

  

3.4.3.2.2:对于名称空间X和名称m,   命名空间限定的查找集S(X,m)定义如下:让   S'(X,m)mX和内联的所有声明的集合   命名空间集X(7.3.1)。如果S'(X,m)不为空,则S(X,m)为空   S'(X,m);否则,S(X,m)是所有名称空间的S(N_i,m)的并集   由N_i中的 using-directives 及其内联命名空间集提名的X

(来源: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,则将搜索在Spam中通过bar指令声明的任何名称空间或using,并且递归应用此逻辑,直到:< / p>

  1. 找到包含bar
  2. 的命名空间
  3. 可能的搜索路径已用尽,在这种情况下,程序格式不正确。

答案 1 :(得分:1)

在3.4.3.2 C ++标准的命名空间成员的以下段落中描述了限定名称的相应名称查找

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中的using指令及其内联命名空间集指定的所有名称空间Ni的S(Ni,m)的并集。

3鉴于X :: m(其中X是用户声明的命名空间),或者给定:: m(其中X是全局命名空间),如果S(X,m)是空集,则程序生病-formed。否则,如果S(X,m)只有一个成员,或者引用的上下文是using-declaration(7.3.3),则S(X,m)是m的必需声明集。否则,如果使用m不允许从S(X,m)中选择唯一声明,则该程序格式不正确。

在你的情况下,如果要遵循引号&#34; 设S0(X,m)是X中m的所有声明和X的内联命名空间集(7.3.1)的集合。如果S0(X,m)不为空,则S(X,m)为S0(X,m); &#34; S(垃圾邮件,栏)由垃圾邮件中的一个条形声明组成。此声明是垃圾邮件中唯一的声明。所以这个名字会被找到。