19

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.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • 5
    [issue 1826: const floating-point in constant expressions](http://stackoverflow.com/a/30742473/1708801) covers some of the history as to why floating point is treated differently. Also [interesting deprecated gcc exntension](http://stackoverflow.com/q/32813953/1708801). – Shafik Yaghmour Dec 14 '16 at 13:33
  • @ShafikYaghmour Thanks. I upvoted that post. – Mr.C64 Dec 14 '16 at 13:35
  • 1
    Seems like @ShafikYaghmour's comment should be promoted to an answer and then accepted. – TriskalJM Dec 20 '16 at 17:19
  • If @ShafikYaghmour wants to write an answer, I'd be happy to upvote and accept it. – Mr.C64 Dec 20 '16 at 20:40

3 Answers3

1

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
Alex
  • 1,602
  • 20
  • 33
1

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.

  • 1
    Perhaps `double`´s representation is not specified by the standard, but it has to be well-known at compile time by the compiler; otherwise you couldn't even have a `constexpr double`. – Spencer Feb 09 '20 at 18:26
-3

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
Community
  • 1
  • 1
straceX
  • 60
  • 4
  • This does not answer the question , which was about `const double k1 = 3.14;` and not about `const double k1 = size_of_array();` – M.M Jan 13 '17 at 05:07
  • Of course **double k1 = size_of_array();** not include in question but I gave example **compile time** and **runtime initialization** about const value. And this example about every const variable not constexpr (constant expression). And answer of this question after this given information : A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.[MSDN](https://msdn.microsoft.com/en-us/library/dn956974.aspx) – straceX Jan 13 '17 at 12:20
  • this question is about compile-time initialization of value, there is no relevance to an example about run-time initialization. Your answer makes it seem like the problem with OP's code is runtime initialization. – M.M Jan 13 '17 at 12:31
  • @M.M but it might be that using`const double` instead of `constexpr double` tells the compiler it can initialize at run time instead of compile time. Which might be necessary on some platforms. – Spencer Feb 09 '20 at 18:22