Skip to content

Last updated:2026-10-12

The Complete C++ const Family

Outline

  • const
  • constexpr
  • C++20
  • consteval
  • constinit

Note: all code examples in this article have been posted to the Knowledge Planet.

1. const

const is one of the earliest keywords we meet when learning C++/C. It is usually used as a cv-qualifier to indicate that an object is immutable. It does not guarantee compile-time evaluation; when exactly the evaluation happens is up to the compiler. For example:

const int a = 1; // 编译时
const auto x = getdata(); // 运行时

const can sometimes be used in compile-time constant expressions, but there are exceptions, for example:

const double count_1 = 3.3;
std::array<double, static_cast<int>(count_1)> moreDoubles1 {1.1, 2.2, 3.3};

This produces an error: the value of 'count_1' is not usable in a constant expression

But this is fine:

const int count = 3;
std::array<double, count> doubles {1.1, 2.2, 3.3};

The essence is compile-time expression evaluation, and so C++11 introduced constexpr.

2. constexpr

constexpr can be used to specify that a variable's value may appear in a constant expression; here we only need to change const to constexpr in the earlier example for it to work.

constexpr double count_2 = 3.3;
std::array<double, static_cast<int>(count_2)> moreDoubles2 {1.1, 2.2, 3.3}; 

constexpr does not necessarily execute only at compile time. Its essential meaning is that it can be computed at compile time, but if a constexpr variable or function is used at run time, it can also execute at run time.

For example, result1 and result2 are completely different: result1 is computed at compile time, while result2 is computed at run time. A question to leave you with: do you know why?

So a function specified as constexpr is not necessarily computed at compile time.

constexpr int compileTimeSum(int a, int b) {
    return a + b;
}

int main() {
    constexpr int result1 = compileTimeSum(3, 5); 
    int x = 10;
    int result2 = compileTimeSum(x, 20);  
    return 0;
}

Then who can guarantee that? Along comes C++20.

3. C++20

3.1 consteval

consteval solves the problem above: it can only be used on functions and forces every call to happen at compile time. If we now change constexpr to consteval above, what happens to result2?

It errors out: call to consteval function 'compileTimeSum(x, 20)' is not a constant expression

consteval int compileTimeSum(int a, int b) {
    return a + b;
}

int main() {
    constexpr int result1 = compileTimeSum(3, 5); 
    int x = 10;
    int result2 = compileTimeSum(x, 20);  
    return 0;
}

If consteval is used on a variable, it also errors: error: a variable cannot be declared 'consteval'.

https://en.cppreference.com/w/cpp/language/consteval

3.2 constinit

constinit forces static or thread-local variables to undergo constant initialization.

  • Cannot be used together with constexpr or consteval
  • A non-type specifier whose role is that of an assert
  • Guarantees that the variable is statically initialized
  • Can only be used with static or thread_local

For example, the following fails to compile: error: 'constinit' can only be applied to a variable with static or thread storage duration

constinit int a = 100;  
int main() {  
      ++a; 
      constinit auto b = 100;  // error
      // b has thread storage duration
      constinit thread_local auto b = 100;
}

Comments