Immediate Functions in C++


Sign up for FREE 1 month of Kindle and read all our books for free.

Immediate functions or the functions which have consteval keyword before their return type has been introduced with the release of C++ 20 , consteval functions are the functions that must be evaluated at compile time to produce a constant. It serves the same functionality as constexpr function but with little more restriction.

So , before understanding the consteval functions let's have a look at constexpr functions.

Immediate Function is a new feature introduced in C++20 in 2020.

What is constexpr ?

The sole reason to use constexpr functions in our program is performance improvement which we do by doing computations at compile time rather than at run time. once a program is compiled and finalized, it is run multiple times by users and some constants in our code get's evaluated each time code is run by the user so rather than computing these constants at run time we can evaluate these constants at compile time once and use it multiple times during execution of the program. The goal with constexpr functions is to spend time in compilation and save time at run time.

let's take a example --

let's say we want the fibonacci no. of some value , if the value is fixed then we can declare the function calculating fibonacci no. as constexpr , as a result the fibonacci no. would be calculated at compile time rather then at run time and as a result this would make our code execution faster.

let's see this with a example ---

#include<iostream> 
using namespace std; 
  
constexpr long int fib(int n) 
{ 
    return (n <= 1)? n : fib(n-1) + fib(n-2); 
} 
  
int main () 
{ 
    // value of res is computed at compile time.  
    const long int res = fib(30); 
    cout << res; 
    return 0; 
}

When the above program is run on GCC, it takes 0.003 seconds .

If we remove const from below line, then the value of fib(5) is not evaluated at compile time, because result of constexpr is not used in a const expression.

if we measure the time taken after removing the const keyword then it comes out to be 0.017 seconds , therefore using constexpr makes our code execution faster.

So, if the same code is run multiple times using the executable file then we save a lot of execution time during running of the program cause we have already spent time in evaluation of constant during run time only once.

However constexpr function are little deceiving , they behave as normal functions if some code in their evaluation requires some values that are generated at run-time so in the above code even if we would have changed the function evaluation as -

const long int res = fib( rand() %30 ) ;
// instead of  const long int res = fib(30); 

here , fib function would work but as normal function and it would generate the output at run time (not compile time) because rand() function generates the no. at run-time only.

so , if we do not want our code to compile at all and we want our compiler to tell us that we are using some code in our function which is being evaluated at run-time rather then at compile time then we need to use Immediate function and the keyword we use to declare immediate functions is consteval.

How is consteval different from constexpr ?

consteval serves the same functionality as constexpr but we cannot use consteval as normal functions if some code in consteval generates some values at run-time then consteval gives compile time error

let's take a example

#include<iostream>
using namespace std ;


constexpr int fibonacci(int N){
if (N <= 1) return N;
return fibonacci(N - 1) + fibonacci(N - 2);
}
int main() {
// This works with our consteval function
int val = fibonacci(22);
// This does not! , it only works with constexpr function and there it is treated as normal function 
// val = fibonacci(rand() % 20 ) ;

cout << "The fibonacci number is: " << val << '\n';

  return 0 ;

}

The above code would works fine , but if we uncomment the code which has the rand() function in it then this would give compile time error because rand() function generates no. at run-time only and consteval cannot work as normal functions(unlike constexpr functions which can behave as normal functions if required).

let's take another example

#include<iostream>
using namespace std ;


constexpr int Util(){
 
   int x ;
   cin>>x ;
   
   return x * 3 ;
 
}
int main() {

 val = Util() ;
 // In the above function declaration of Util if we use constexpr then it works 
 // fine and acts as normal function but if we use consteval function then above
 // program doesn't compile at all.
  

cout << "Third multiple of the no. you entered is " << val << '\n';

  return 0 ;

}

From the above two examples we can say that if we want some functions in our program to run at compile time only or don't compile at all and tell us that we have done some error in the code of the function which should have been evaluated at compile time then we can use immediate functions ( functions with consteval) to avoid any confusions and make sure that our given function is evaluated at compile time only.

Conclusion

consteval function (or immediate function ) is a more restrictive form of consexpr function which ensures that our function doesn't behave as normal function and it's evaluated at compile time only diffrentiating it with constexpr function.