#include <complex>
struct S
{
static std::complex<double> constexpr c;
};
gcc generates an error because an initializer is missing. Clang and MSVC do not generate an error.
As far as I know a constexpr static data member must have an initializer, even if it is of class type that has a constructor that can be called without arguments (as in this case). Unfortunately I don't have the latest C++ standard to back up my assumption.
So the correct code should initialize with a constructor, for instance:
struct S
{
static std::complex<double> constexpr c {};
};
Can anyone prove which compiler is right and which is wrong?
A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later. So, what does constexpr mean?
Static data members are initialized when they are defined, outside of any member function, exactly like the initialization of ordinary (non-class) global variables.
Static Data Member Initialization in C++ For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator, then the variable name. Now we can assign some value.
Static data members in C++ Static data members are class members that are declared using static keywords. A static member has certain special characteristics. These are: Only one copy of that member is created for the entire class and is shared by all the objects of that class, no matter how many objects are created.
GCC is wrong.
GCC uses the C++14 rules for constexpr
variables, which requires an initializer to be provided. This is changed per P0386 (bold text is newly added text):
In 9.2.3.2p3, change:
If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (5.20).
A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ]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. An inline static data member can be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see D.X). Declarations of other static data members shall not specify a brace-or-equal-initializer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With