Compile time function execution


Compile-time function execution is the ability of a compiler, that would normally compile a function to machine code and execute it at run time, to execute the function at compile time. This is possible if the arguments to the function are known at compile time, and the function does not make any reference to or attempt to modify any global state.
If the value of only some of the arguments are known, the compiler may still be able to perform some level of compile-time function execution, possibly producing more optimized code than if no arguments were known.

Examples

The Lisp macro system is an early example of the use of compile-time evaluation of user-defined functions in the same language.
The Metacode extension to C++ was an early experimental system to allow compile-time function evaluation and code injection as an improved syntax for C++ template metaprogramming.
In earlier versions of C++, template metaprogramming is often used to compute values at compile time, such as:

template
struct Factorial ;
template <>
struct Factorial<0> ;
// Factorial<4>::value 24
// Factorial<0>::value 1
void Foo

Using compile-time function evaluation, code used to compute the factorial would be similar to what one would write for run-time evaluation e.g. using C++11 constexpr.

  1. include
constexpr int Factorial
constexpr int f10 = Factorial;
int main

In C++11, this technique is known as generalized constant expressions. C++14 relaxes the constraints on constexpr – allowing local declarations and use of conditionals and loops.
Here's an example of compile time function evaluation in C++14:

// Iterative factorial at compile time.
constexpr int Factorial
int main

Here's an example of compile time function evaluation in the D programming language:

int factorial
// computed at compile time
enum y = factorial; // 1
enum x = factorial; // 24

This example specifies a valid D function called "factorial" which would typically be evaluated at run time. The use of enum tells the compiler that the initializer for the variables must be computed at compile time. Note that the arguments to the function must be able to be resolved at compile time as well.
CTFE can be used to populate data structures at compile-time in a simple way :
int genFactorials
enum factorials = genFactorials;
void main
// 'factorials' contains at compile-time:
//

CTFE can be used to generate strings which are then parsed and compiled as D code in D.