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).
The member declaration
int b[A::a];
is not in the potential scope ofA::a
(3.3.7p1), while the body ofvoid A::foo()
is in the potential scope (3.3.7p1b1):3.4.3.1p1 references the potential scope rule in a 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:
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.
The error is because when
int b[A::a];
is being processed,A
does not yet have a symbola
. 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 ofa
.You can see this by reversing the order of the lines:
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)