Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why declare int a constexpr

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?

like image 558
NoSenseEtAl Avatar asked Dec 01 '13 06:12

NoSenseEtAl


2 Answers

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>

like image 158
Howard Hinnant Avatar answered Jan 03 '23 12:01

Howard Hinnant


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.

like image 30
Vittorio Romeo Avatar answered Jan 03 '23 10:01

Vittorio Romeo