c++ - 确定哪个成员在 namespace 中可见

标签 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

我知道在这种情况下,如果垃圾邮件包含该成员,它将引用该成员。但是,如果没有,则会找到 using 指令的名称并引用 fallbacks::bar。

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

最佳答案

该标准的

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

3.4.3.2.2: For a namespace X and name m, the namespace-qualified lookup set S(X,m) is defined as follows: Let S'(X,m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S'(X,m) is not empty, S(X,m) is S'(X,m); otherwise, S(X,m) is the union of S(N_i,m) for all namespaces N_i nominated by using-directives in X 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 将被搜索,并递归应用此逻辑,直到:

  1. 发现一个命名空间包含bar,或者
  2. 可能的搜索路径已经用尽,在这种情况下程序是病式的。

关于c++ - 确定哪个成员在 namespace 中可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24930921/

相关文章:

c++ - 为什么我在 C++ 中用 ^ 计算指数时得不到正确的结果?

c++ - 如何让 g++ 在终端中显示执行时间?

C++,在类变量中添加条件

c++ - std::string 一次性转换为 int/double

c++ - Qt 终止由 QConcurrent::run 生成的线程

java - 单元测试需要很多接口(interface)?

c++ - 输出错误 Project Euler 50

c++ - 如何修复 C++ 中的程序崩溃问题?

c++ - 集合迭代器中的不完整类型

c++ - 堆上已分配内存的总线错误