Initializing constexpr with const: Different treatment for int and double

3k views Asked by At

The following code fails to compile live on Ideone:

#include <iostream>
using namespace std;

int main() {
    const double kPi = 3.14;
    constexpr double kPi2 = 2.0*kPi;
    cout << kPi2;
}

The error message is:

prog.cpp: In function 'int main()':
prog.cpp:6:30: error: the value of 'kPi' is not usable in a constant expression
  constexpr double kPi2 = 2.0*kPi;
                              ^
prog.cpp:5:15: note: 'kPi' was not declared 'constexpr'
  const double kPi = 3.14;

Substituting the const declaration for kPi with constexpr, it compiles successfully.

On the other hand, when int is used instead of double, seems like const plays well with constexpr:

#include <iostream>
using namespace std;

int main() {
    const int k1 = 10;
    constexpr int k2 = 2*k1;
    cout << k2 << '\n';
    return 0;
}

Why do int and double get different treatments for initializing a constexpr with const?
Is this a bug in the Ideone compiler? Is this required by the C++ standard? Why is that?
Was the above code UB?

P.S. I tried with Visual Studio 2015 C++ compiler, and it compiles the first code snippet (initializing constexpr with const) just fine.

3

There are 3 answers

4
straceX On

Rule:"constexpr must be evaluate at compile time".

Let's look below code (generic example);

    const double k1 = size_of_array(); 

k1 is constant, the value of its initializer is not known compile time but its initializer is known until run time so k1 is not constant expression. As a result a const variable is not constexpr.

But compiler see these code:

    const int k1 = 10;  
    constexpr int k2 = 2*k1;

One exception occurs. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations [1].

You can get extra information from the links below:

  1. Constexpr - Generalized Constant Expressions in C++11
  2. const vs constexpr on variables | stackoverflow
  3. Difference between constexpr and const | stackoverflow
1
AudioBubble On

The for a constexpr to be calculated at compile time everything that is used in the initialization of that constexpr also must be calculatable at compile time. If you declare something as const it does not mean that the value will be available at compile time.

Take the following line:

const double dbl = 2.;

The double's representation is not specified by the standard so the OS will have to deal with this. So when your program is loaded by the OS there is a special assembly subroutine in your binary that will make this happen. If you use an int the representation is specified by the standard so the compiler will know how to work with it. However the same can be achieved by making the double a constexpr as well, so the compiler will compute it in compile time. In this case the double will also be a const (you cannot make something constexpr without also making it const).

So this will work:

constexpr double kPi = 3.14;
constexpr double kPi2 = 2.0*kPi;

If you use an int the compiler will set the value of that const at compile time so the constexpr will work.

Keep in mind that different compilers can interpret const as constexpr in some cases and make it work. But that is not part of the standard.

0
Alex On

Shafik Yaghmour already provided a link explaining the background.

Since I have to maintain code which has to compile with different standards, I use the following macro:

#if __cplusplus <= 199711L  // lower than C++11
  #define MY_CONST const
#else // C++11 and above
  #define MY_CONST constexpr
#endif