While watching a C++11 tutorial video linked on isocpp.org I noticed something:
constexpr int windowWidth{800}, windowHeight{600};
What is the point in declaring these int
variables as constexpr
, and not just const
?
While watching a C++11 tutorial video linked on isocpp.org I noticed something:
constexpr int windowWidth{800}, windowHeight{600};
What is the point in declaring these int
variables as constexpr
, and not just const
?
Nice video Vittorio!
Here is a summary of the difference between declaring an int
const
and constexpr
:
int get_int(); // Some run time function that returns int
template <int N> // example use requiring a compile time int
struct test {};
const int w = get_int(); // initialized at run time
const int x = 5; // initialized at compile time
constexpr int y = get_int(); // error, can not initialize at compile time
constexpr int z = 6; // initialized at compile time
int
main()
{
test<w> tw; // error, w is not a compile time constant
test<x> tx; // ok, x is a compile time constant
test<y> ty; // error, there is no compile time constant named y
test<z> tz; // ok, z is a compile time constant
}
When you use constexpr
, you require that the initialization happens at compile time, lest you will get a compile time error. When you use const
, you allow the initialization to happen at run time, though it will still happen at compile time if the initializer is itself a compile time constant.
If you have a const int
, the code reviewer must look at the initialization (following back to the original if this is a copy of a const int
) to know if that const int
is a compile time constant, or a run time constant.
If you have a constexpr int
, the code reviewer can immediately assume that it is a compile time constant without analyzing how it was initialized. If that assumption turns out to be false, the compiler will flag it as an error.
<Disclaimer>
In the comments below Kerrek SB correctly points out that I've played "fast and loose" with the terminology in this answer. I've done so in an effort to make the answer short and understandable. What I'm calling "initialized at compile time" and "compile time constant" are what the standard in section 5.19 "Constant expressions" [expr.const] refers to as integral constant expressions.
Integral constant expressions are initialized with what is called constant initialization, which together with zero-initialization is referred to as static initialization ([basic.start.init]/p2).
Any deviations between what I write here and what appears in the standard are accidental, and what is in the standard is correct.
</Disclaimer>
I'm the author of the video.
Intent.
constexpr
clearly expresses the intent of a compile-time immutable value. const
doesn't really mean compile-time immutable value.
Both modifiers can be casted away, but that results in undefined behavior. Check DyP's comment for more information.
When using C++11, in my opinion, the first keyword that should come to mind when dealing with compile-time values is not const
but constexpr
.
The code would behave exactly the same without constexpr
, or with const
in place of constexpr
.
But when you take a look at the code, and see constexpr int windowWidth;
you can be 100%
sure that's an immutable constant that will never change during run-time.
In my second tutorial video, there's an addendum on constexpr
in the first three minutes, that shows constexpr
functions and more constexpr
examples/explanations.