类成员限定名查找

5 c++ class language-lawyer

考虑以下代码片段:

class A
{
    int b[A::a]; //1, error
    void foo(){ int b = A::a; } //2, ok
    static const int a = 5;
}
Run Code Online (Sandbox Code Playgroud)

第 3.4.3.1/1 条(限定名称查找,类成员)说:

如果限定 id 的嵌套名称说明符指定一个类,则在类的范围内查找在嵌套名称说明符之后指定的名称(10.2)

这意味着将在类作用域中查找ain//1和 in 中的嵌套名称说明符之后的名称//2

第 10.2 条(会员姓名查询)说:

10.2/2

以下步骤定义了类作用域 C 中成员名称 f 的名称查找结果。

10.2/3

C 中 f 的查找集,称为 S(f, C)...

S(f, C) 计算如下:

10.2/4

如果 C 包含名称 f 的声明,则声明集包含在 C 中声明的满足发生查找的语言构造要求的每个 f 声明。

以下对我来说不清楚:

从我引用的引文中可以看出,对于这两者//1//2应该应用相同的成员查找规则。但实际上它是不同的。为什么我的推理是错误的?

注意:我知道类范围内的非限定名称查找规则。我在以下代码片段中理解了这种行为:

class A
{
    int b[a]; //error
    void foo(){ int b = a; } //ok
    static const int a = 5;
}
Run Code Online (Sandbox Code Playgroud)

这是因为第 3.4.1/7 和 3.4.1/8 节(非限定名称查找)中描述的行为。

M.M*_*M.M 4

该错误是因为int b[A::a];正在处理时,A还没有符号a。在编译时,仍然不完整,因为我们还没有达到类定义的A结束。}编译器不会“向前看”以查看源代码的未来行是否包含a.

您可以通过颠倒行的顺序来看到这一点:

class A
{
    static const int a = 5;
    int b[A::a]; // OK
};
Run Code Online (Sandbox Code Playgroud)

函数定义不存在同样的问题,因为内联函数体直到类定义编译之后才被编译。(抱歉,我没有方便的标准参考资料)