Expert C++
上QQ阅读APP看书,第一时间看更新

constexpr

The constexpr specifier declares that the value of the function is possible to evaluate at compile time. The same definition applies to variables as well. The name itself consists of const and expression. This is a useful feature because it allows optimizing your code to the fullest. Let's take a look at the following example:

int double_it(int number) {
return number * 2;
}

constexpr int triple_it(int number) {
return number * 3;
}

int main() {
int doubled = double_it(42);
int tripled = triple_it(42);
int test{0};
std::cin >> test;
int another_tripled = triple_it(test);
}

Let's see how the compiler modifies the main() function in the preceding example. Supposing the compiler won't optimize the double_it() function on its own (for example, making it an inline function), the main() function will take the following form: 

int main() {
int doubled = double_it(42);
int tripled = 126; // 42 * 3
int test = 0;
std::cin >> test;
int another_tripled = triple_it(test);
}

 constexpr is not a guarantee that the function value will be computed at compile time; however, the compiler is able to do so if the input of the constexpr function is known at compile time. That's why the preceding example transformed directly to a computed value of 126 for the  tripled variable and had no effect on the another_tripled  variable as the input is not known to the compiler (and nor us).

C++20 introduces the consteval specifier, allowing you to insist on the compile-time evaluation of the function result. In other words, a consteval function produces a constant expression at compile time. The specifier makes the function an immediate one, which will produce an error if the function call cannot lead to a constant expression.  The  main()  function cannot be declared as  constexpr .

C++20 also introduces the constinit specifier. We use constinit to declare a variable with static or thread storage duration. We will discuss thread storage duration in Chapter 8Concurrency and Multithreading. The most notable difference with constinit is that we can use it with objects that have no constexpr destructor. This is because constexpr requires the object to have static initialization and constant destruction. Furthermore, constexpr makes the object const-qualified while constinit does not. However, constinit requires the object to have static initialization.