8

when I want to have a static pointer as a member of a class I need constexprfor the initialisation with nullptr.

class Application {
    private:
        constexpr static Application* app = nullptr;
}

Can someone explain me why I need to do that? I cannot find the exact reason why it`s necessary that the static variable has to exist at compile time.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
Matthias Preu
  • 783
  • 2
  • 8
  • 18
  • how do you use `app` variable? – BЈовић Oct 11 '13 at 13:26
  • The pointer should work as a pointer to an instance of the Application class (respectively to an instance of a class which derives from the Application base class). I write a program with OpenGL and Freeglut and I need to "wrap" the c-interface of Freeglut (callback registration with class member function). – Matthias Preu Oct 11 '13 at 13:44

4 Answers4

10

That's because you're initialising it inside the class definition. That's only allowed for constant integral and enumeration types (always) and for constexpr data members (since C++11). Normally, you'd initialise it where you define it (outside the class), like this:

Application.h

class Application {
    private:
        static Application* app;
}

Application.cpp

Application* Application::app = nullptr;

Note that you need to provide the out-of-class definition even in the constexpr case, but it must not contain an initialiser then. Still, I believe the second case is what you actually want.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thanks for the useful comment. You wrote inside class initialisation is only allowed for constant ...-types. But it's possibly with non-constant ...-types too, isn't it? – Matthias Preu Oct 11 '13 at 13:47
  • @Meiner A `static` class data member can only be initialised inside a class if it is `constexpr` of literal type or it's `const`, not `volatile`, and is of integral or enumeration type. – Angew is no longer proud of SO Oct 11 '13 at 14:08
  • Thanks for clarification. Didn't realise that you only talk of the static in-class initialisation in the original comment. – Matthias Preu Oct 11 '13 at 14:23
  • @yau Can you clarify your edit suggestion? C++11 9.4.2/3 says that "The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an *initializer.*" – Angew is no longer proud of SO Dec 20 '14 at 20:46
  • In the case of a `constexpr static` member, if it is not [odr-used](https://en.cppreference.com/w/cpp/language/definition#ODR-use) you do not need to provide an out-of-class declaration. From C++17, if a static data member is declared, it is implicitly `inline` and it no longer needs to be declared out-of-class. – Bruno Hendrickx Dec 05 '18 at 15:20
3

If you don't want it to be constexpr (and it's not an integer) then you need to initialise it outside of the class body:

class Application
{
private:
    static Application* app;
};

Application* Application::app = nullptr;
Simple
  • 13,992
  • 2
  • 47
  • 47
  • Thanks for the comment. I don't have a preference for using constexpr or not. I'm more interested in the question why this special keyword is needed for in-class initialisation when it's not necessary for other forms of in-class initialisation. – Matthias Preu Oct 11 '13 at 13:58
1

Typically, you need to initialise a static member variable outside the class declaration, unless it is const. I think this explains it better than I could.

Community
  • 1
  • 1
Kindread
  • 926
  • 4
  • 12
  • Very interesting link. I didn't have the ODR in mind. So the reason why constexpr works is the implicit const, right? I just realise, that I can't change a static variable later when initialised as a constexpr variable. – Matthias Preu Oct 11 '13 at 14:06
0

Static variables do not need to "exist at compile time". But if you want to initialize a static variable inside the class, its value needs to be known at compile time.

However, I do not know the reason for this restriction.

Oswald
  • 31,254
  • 3
  • 43
  • 68