Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constexpr static data member without initializer

#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?

like image 506
x y Avatar asked Jun 01 '18 07:06

x y


People also ask

Does constexpr need to be static?

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?

Is a static data member it can only be initialized?

Static data members are initialized when they are defined, outside of any member function, exactly like the initialization of ordinary (non-class) global variables.

How do you initialize a static data member in C++?

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.

What is static member and static member function in C++?

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.


1 Answers

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 n​on-­inline ​const static data member is of integral or enumeration type, its declaration in the class definition can specify a b​race­-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.​ A​n inline static data member can be defined in the class definition and may specify a b​race­-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 b​race­-or-­equal-initializer.​

like image 122
xskxzr Avatar answered Oct 25 '22 03:10

xskxzr