Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Why can I initialize a static const char but not a static const double in a class definition?

Here are two line of code:

static const double RYDBERG_CONST_EV = 13.6056953;
static const char CHAR_H_EDGE = '-';

The second line compiles without errors, the first line does not compile. (Error: 'constexpr' needed for in-class initialization of static data member...)

The solution is apparently to add the keyword constexpr before the type. This is required because double is not an "integral type". But why does the behaviour differ between integer and floating point types?

like image 386
FreelanceConsultant Avatar asked Feb 01 '16 21:02

FreelanceConsultant


1 Answers

I don't believe that there is a good reason for this except that it has grown historically.

The exception for integral types was desirable in pre-C++11 because people wanted to use them as array sizes. This goes along with the other exception for integral constants being treated as constant expressions. An exception that doesn't exist for floating-point types.

const int    ni = 10;
const float  nf = 10.0f;
int numbers1[(unsigned) ni];  // perfectly fine in all versions of C++
int numbers2[(unsigned) nf];  // error in all versions of C++

When C++11 introduced constexpr, it could do anything the special-casing for const integral types could do and much more. And it works the same way for any literal type. So, given a superior tool, there was no need to dilate the existing rules for integral types to floating-point.

Today, the special-casing of integral types is mostly a left-over from the earlier darker days. It cannot be removed from the language because doing so would break existing code that relies on this special-casing but there would be little gains from complicating the language even further by adding more exceptions that would be entirely unneeded today thanks to constexpr. People should be expected to migrate to constexpr and not worry about the old cruft any more. I believe that this was a very reasonable decision but you could certainly argue that another decision should have been made.

Addendum

As T.C. has commented, there has been a (non)-defect report about this issue where the committee confirmed that the behavior won't be changed and people are supposed to start using constexpr.

1826. const floating-point in constant expressions

Section: 5.20 [expr.const] Status: NAD Submitter: Ville Voutilainen Date: 2014-01-04

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.

It was also observed that allowing const floating point variables as constant expressions would be an ABI-breaking change, since it would affect lambda capture.

One possibility might be to deprecate the use of const integral variables in constant expressions.

Additional note, April, 2015:

EWG requested CWG to allow use of const floating-point variables in constant expressions.

Rationale (May, 2015):

CWG felt that the current rules should not be changed and that programmers desiring floating point values to participate in constant expressions should use constexpr instead of const.

like image 136
5gon12eder Avatar answered Sep 29 '22 09:09

5gon12eder