Why is a private member visible when initializing a static variable?
Asked Answered
E

2

5

This compiles:

class Node{
    int m = 0;

    static unsigned f(){
        return 1;
    }

public:
    static unsigned a;
    static unsigned b;
};

unsigned Node::a = sizeof(m); // <= !!!
unsigned Node::b = f();       // <= !!!

int main(){
}

Why? I know sizeof is not function but still, aren't m and f() private?

It is definitely not a bug, because the code compiles on GCC, MSVC, Clang and Intel C++.

Update: Also, note that it is just sizeof(m) and not sizeof(Node::m); same with f() instead of Node::f(). (Koenig's lookup?)

Expertism answered 24/8, 2023 at 8:23 Comment(5)
What book on C++ did you read? Consider looking into this C++ reference and taking inspiration from existing C++ open source codeWellthoughtof
yes. member is privateExpertism
I'll update the questionExpertism
While this is for namespace symbols, it seems to be the same here.Drillstock
@Someprogrammerdude this is what I think so, but I can not be 100% sure.Expertism
W
9

Access to private members is allowed in non-inline definitions of static data members, because the initializer part of the definition (that is, the RHS of the =) is in the scope of the class, according to the Standard ("Note 1", below):

11.4.9.3 Static Data Members       [class.static.data]


3   The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void.
[Note 1: The initializer in the definition of a static data member is in the scope of its class ([basic.scope.class]). — end note]


Note that, in reference to your last (update) paragraph, because the initializer is in the class scope, unqualified/un-scoped variables, such as m and f() in your case, will by default refer to class members (if such exist); so, the f() call in your code is entirely equivalent to Node::f().

Wittie answered 24/8, 2023 at 9:5 Comment(2)
As for the last sub-question, I can find a quote for that in an earlier (C++17) Draft Standard but not (so far) in the latest, online Draft I linked in my answer. It's 12.2.3, #3 in this Draft C++17 Standard ...Wittie
... 3 If an unqualified-id (8.4) is used in the definition of a static member following the member’s declarator-id, and name lookup (6.4.1) 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 8.4 for restrictions on the use of non-static data members and non-static member functions. — end note ]Wittie
D
1

See [class.access.general]/6, emphasis mine:

All access controls in [class.access] affect the ability to name a class member from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's member-specification. [Note 5: This access also applies to implicit references to constructors, conversion functions, and destructors. — end note]

The definition of Node::a, being a member of Node, has access to all names to which Node has access.

Descender answered 24/8, 2023 at 22:17 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.