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)
    }