In C++11 and C++14, why do I need constexpr
in the following snippet:
class Foo {
static constexpr double X = 0.75;
};
whereas this one produces a compiler error:
class Foo {
static const double X = 0.75;
};
and (more surprisingly) this compiles without errors?
class Foo {
static const double X;
};
const double Foo::X = 0.75;
A static member function cannot be declared with the keywords virtual , const , volatile , or const volatile . A static member function can access only the names of static members, enumerators, and nested types of the class in which it is declared.
A constant variable must be initialized at its declaration. To declare a constant variable in C++, the keyword const is written before the variable's data type. Constant variables can be declared for any data types, such as int , double , char , or string .
We can define class members static using static keyword. When we declare a member of a class as static it means no matter how many objects of the class are created, there is only one copy of the static member. A static member is shared by all objects of the class.
In C++03 we were only allowed to provide an in class initializer for static member variables of const integral of enumeration types, in C++11 we could initialize a static member of literal type in class using constexpr. This restriction was kept in C++11 for const variables mainly for compatibility will C++03 we can see this from closed issue 1826: const floating-point in constant expressions which says:
A const integer initialized with a constant can be used in constant expressions, but a const floating point variable initialized with a constant cannot. This was intentional, to be compatible with C++03 while encouraging the consistent use of constexpr. Some people have found this distinction to be surprising, however.
CWG ended up closing this request as not a defect(NAD), basically saying:
that programmers desiring floating point values to participate in constant expressions should use constexpr instead of const.
For reference N1804
the closest draft standard to C++03 publicly available in section 9.4.2
[class.static.data] says:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.
and the draft C++11 standard section 9.4.2
[class.static.data] says:
If a non-volatile 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.19). 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. [...]
this is pretty much the same in the draft C++14 standard.
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