Class member qualified name lookup

2019-06-25 22:45发布

Consider the following code snippet:

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

Clause 3.4.3.1/1 (Qualified name lookup, class members) said:

If the nested-name-specifier of a qualified-id nominates a class, the name specified after the nested-name-specifier is looked up in the scope of the class (10.2)

This implies that the name a after the nested-name-specifier both in //1 and in //2 will be looked up in the class scope.

Clause 10.2 (Member name lookup) said:

10.2/2

The following steps define the result of name lookup for a member name f in a class scope C.

10.2/3

The lookup set for f in C, called S(f, C)...

S(f, C) is calculated as follows:

10.2/4

If C contains a declaration of the name f, the declaration set contains every declaration of f declared in C that satisfies the requirements of the language construct in which the lookup occurs.

The following is unclear for me:

From the quotes I cited implies that for both //1 and //2 the same member lookup rules shall be applied. But actually its a different. Why is my reasoning wrong?

Note: I know about unqualified name lookup rules into the class scope. And I understood that behavior in the following code snippet:

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

It is because that behavior described in the sections 3.4.1/7 and 3.4.1/8 (Unqualified name lookup).

2条回答
仙女界的扛把子
2楼-- · 2019-06-25 23:20

The member declaration int b[A::a]; is not in the potential scope of A::a (3.3.7p1), while the body of void A::foo() is in the potential scope (3.3.7p1b1):

1) The potential scope of a name declared in a class consists not only of the declarative region following the name's point of declaration, but also of all function bodies, brace-or-equal-initializers of non-static data members, and default arguments in that class (including such things in nested classes).

3.4.3.1p1 references the potential scope rule in a note:

[...] [ Note: A class member can be referred to using a qualified-id at any point in its potential scope (3.3.7). — end note ] [...]

Of course, notes are non-normative, so the conclusion must be that the potential scope rule is implied by other material in the standard. I believe this other material is specifically 3.3.2p5:

After the point of declaration of a class member, the member name can be looked up in the scope of its class. [...]

By implication, prior to the point of declaration of that class member, that member name cannot be looked up in the scope of that class.

查看更多
狗以群分
3楼-- · 2019-06-25 23:28

The error is because when int b[A::a]; is being processed, A does not yet have a symbol a. At that point of compilation, A is still incomplete because we have not reached the closing } of the class definition yet. The compiler doesn't "look ahead" to see if future lines of source code contain a definition of a.

You can see this by reversing the order of the lines:

class A
{
    static const int a = 5;
    int b[A::a]; // OK
};

The function definition does not have the same problem because inline function bodies are not compiled until after compilation of the class definition. (Sorry, I don't have standard references handy for this)

查看更多
登录 后发表回答