Is there a difference between the following definitions?
const double PI = 3.141592653589793; constexpr double PI = 3.141592653589793; If not, which style is preferred in C++11?
Is there a difference between the following definitions?
const double PI = 3.141592653589793; constexpr double PI = 3.141592653589793; If not, which style is preferred in C++11?
I believe there is a difference. Let's rename them so that we can talk about them more easily:
const double PI1 = 3.141592653589793; constexpr double PI2 = 3.141592653589793; Both PI1 and PI2 are constant, meaning you can not modify them. However only PI2 is a compile-time constant. It shall be initialized at compile time. PI1 may be initialized at compile time or run time. Furthermore, only PI2 can be used in a context that requires a compile-time constant. For example:
constexpr double PI3 = PI1; // error but:
constexpr double PI3 = PI2; // ok and:
static_assert(PI1 == 3.141592653589793, ""); // error but:
static_assert(PI2 == 3.141592653589793, ""); // ok As to which you should use? Use whichever meets your needs. Do you want to ensure that you have a compile time constant that can be used in contexts where a compile-time constant is required? Do you want to be able to initialize it with a computation done at run time? Etc.
const int N = 10; char a[N]; works, and array bounds must be compile-time constants.PI1 to a compile-time integral constant for use in an array, but not for use as a non-type integral template parameter. So the compile-time convertibility of PI1 to an integral type seems a little hit & miss to me.enum initializer are the only two notable differences between const and constexpr (and neither works for double anyway).1 / PI1 and 1 / PI2 may yield different results. I don't think this technicality is quite as important as the advice in this answer however.constexpr double PI3 = PI1; works correctly for me. (MSVS2013 CTP). What am I doing wrong?No difference here, but it matters when you have a type that has a constructor.
struct S { constexpr S(int); }; const S s0(0); constexpr S s1(1); s0 is a constant, but it does not promise to be initialized at compile-time. s1 is marked constexpr, so it is a constant and, because S's constructor is also marked constexpr, it will be initialized at compile-time.
Mostly this matters when initialization at runtime would be time-consuming and you want to push that work off onto the compiler, where it's also time-consuming, but doesn't slow down execution time of the compiled program
constexpr would lead to a diagnosis should the compile-time computation of the object be impossible. What is less clear is whether a function expecting a constant parameter could be executed at compile-time should the parameter be declared as const and not as constexpr: ie, would constexpr int foo(S) be executed at compile-time if I call foo(s0) ?foo(s0) would be executed at compile-time, but you never know: a compiler is allowed to do such optimizations. Certainly, neither gcc 4.7.2 nor clang 3.2 allow me to compile constexpr a = foo(s0);constexpr indicates a value that's constant and known during compilation.
const indicates a value that's only constant; it's not compulsory to know during compilation.
int sz; constexpr auto arraySize1 = sz; // error! sz's value unknown at compilation std::array<int, sz> data1; // error! same problem constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr Note that const doesn’t offer the same guarantee as constexpr, because const objects need not be initialized with values known during compilation.
int sz; const auto arraySize = sz; // fine, arraySize is const copy of sz std::array<int, arraySize> data; // error! arraySize's value unknown at compilation All constexpr objects are const, but not all const objects are constexpr.
If you want compilers to guarantee that a variable has a value that can be used in contexts requiring compile-time constants, the tool to reach for is constexpr, not const.
A constexpr symbolic constant must be given a value that is known at compile time. For example:
constexpr int max = 100; void use(int n) { constexpr int c1 = max+7; // OK: c1 is 107 constexpr int c2 = n+7; // Error: we don’t know the value of c2 // ... } To handle cases where the value of a “variable” that is initialized with a value that is not known at compile time but never changes after initialization, C++ offers a second form of constant (a const). For Example:
constexpr int max = 100; void use(int n) { constexpr int c1 = max+7; // OK: c1 is 107 const int c2 = n+7; // OK, but don’t try to change the value of c2 // ... c2 = 7; // error: c2 is a const } Such “const variables” are very common for two reasons:
Reference : "Programming: Principles and Practice Using C++" by Stroustrup
One more example to understand the difference between const and constexp.
int main() { int n; cin >> n; const int c = n; // OK: 'c' can also be initialized at run time constexpr int e = n; // Error: 'e' must be initialized at compile time } Note: constexpr normally evaluated at compile-time, but they are not guaranteed to do so unless they're invoked in a context where a constant expression is required.
constexpr int add(int a, int b) { return a + b; }; int main() { int n = add(4, 3); // may or may not be computed at compile time constexpr int m = add(4,3); // must be computed at compile time } constexpr -> Used for compile time constant. This is basically used for run time optimization.
const -> Used for run time constant.