Class static variable initialization order

I have a class A which has two static variables. I'd like to initialize one with another, unrelated static variable, just like this:

#include <iostream>
class A
{
public:
    static int a;
    static int b;
};

int A::a = 200;
int a = 100;
int A::b = a;
int main(int argc, char* argv[])
{
    std::cout << A::b << std::endl;

    return 0;
}

The output is 200. So, could anyone tell me why?


Solution 1:

That's correct according to the lookup rules. [basic.lookup.unqual]/13 says:

A name used in the definition of a static data member of class X (after the qualified-id of the static member) is looked up as if the name was used in a member function of X. [ Note: [class.static.data] further describes the restrictions on the use of names in the definition of a static data member.  — end note ]

Since the unqualified a is looked up as if you are inside a member function, it must find the member A::a first. The initialization order of A::a and A::b doesn't affect the lookup, though it affects how well defined the result is.

Solution 2:

So, could anyone tell me why?

This is clearly stated in basic.scope.class/4, emphasis mine:

The potential scope of a declaration that extends to or past the end of a class definition also extends to the regions defined by its member definitions, even if the members are defined lexically outside the class (this includes static data member definitions, nested class definitions, and member function definitions, including the member function body and any portion of the declarator part of such definitions which follows the declarator-id, including a parameter-declaration-clause and any default arguments).

Thus, when you have

int A::a = 200;
int a = 100;
int A::b = a; // note the '::' scope resolution operator
              // OUTPUT: 200

a actually refers to A::a because the class scope is extended by A::b.

Unlike if you have:

int A::a = 200;
int a = 100;
int b = a; // note b is not A::b
           // i.e. without the '::', scope resolution operator
           // OUTPUT: 100

a would refer to the (global) ::a since b here is not a member of class A,
i.e. no class scope extension.

Solution 3:

c++draft/class.static

If an unqualified-id is used in the definition of a static member following the member's declarator-id, and name lookup ([basic.lookup.unqual]) finds that the unqualified-id refers to a static member, enumerator, or nested type of the member's class (or of a base class of the member's class), the unqualified-id is transformed into a qualified-id expression in which the nested-name-specifier names the class scope from which the member is referenced. [ Note: See [expr.prim.id] for restrictions on the use of non-static data members and non-static member functions. — end note ]

It says the unqualified-id is transformed into a qualified-id expression in your situation.

int A::b = a;

You can set qualified-id but has no nested-name-specifier like this.

int A::b = ::a;

Solution 4:

Because the name look up resolves the a as A::a. If you want to do this you will need to resolve the scope manually:

int A::b = ::a;
        // ^ Global scope resolution

Live Example