La ejecución de funciones en tiempo de compilación (o evaluación de funciones en tiempo de compilación , o expresiones constantes generales ) es la capacidad de un compilador , que normalmente compilaría una función en código de máquina y la ejecutaría en tiempo de ejecución , para ejecutar la función en tiempo de compilación . Esto es posible si los argumentos de la función se conocen en tiempo de compilación, y la función no hace ninguna referencia ni intenta modificar ningún estado global (es una función pura ).
Si se conoce el valor de solo algunos de los argumentos, el compilador aún puede realizar algún nivel de ejecución de la función en tiempo de compilación ( evaluación parcial ), posiblemente produciendo un código más optimizado que si no se conocieran los argumentos.
Ejemplos de
El sistema de macros Lisp es un ejemplo temprano del uso de la evaluación en tiempo de compilación de funciones definidas por el usuario en el mismo lenguaje.
La extensión de Metacode a C ++ (Vandevoorde 2003) [1] fue un sistema experimental temprano para permitir la evaluación de funciones en tiempo de compilación (CTFE) y la inyección de código como una sintaxis mejorada para la metaprogramación de plantillas de C ++ .
En versiones anteriores de C ++ , la metaprogramación de plantillas se usa a menudo para calcular valores en tiempo de compilación, como:
plantilla < int N > struct Factorial { enum { valor = N * Factorial < N - 1 > :: valor }; };plantilla <> struct Factorial < 0 > { enumeración { valor = 1 }; };// Factorial <4> :: valor == 24 // Factorial <0> :: valor == 1 void Foo () { int x = Factorial < 0 > :: valor ; // == 1 int y = Factorial < 4 > :: valor ; // == 24 }
Usando la evaluación de funciones en tiempo de compilación, el código usado para calcular el factorial sería similar a lo que se escribiría para la evaluación en tiempo de ejecución, por ejemplo, usando C ++ 11 constexpr.
#include constexpr int Factorial ( int n ) { return n ? ( n * Factorial ( n - 1 )) : 1 ; }constexpr int f10 = Factorial ( 10 );int main () { printf ( "% d \ n " , f10 ); return 0 ; }
En C ++ 11 , esta técnica se conoce como expresiones constantes generalizadas ( constexpr
). [2] C ++ 14 relaja las restricciones sobre constexpr - permitiendo declaraciones locales y el uso de condicionales y bucles (la restricción general de que todos los datos requeridos para la ejecución estén disponibles en tiempo de compilación permanece).
Aquí hay un ejemplo de evaluación de la función de tiempo de compilación en C ++ 14:
// Factorial iterativo en tiempo de compilación. constexpr int Factorial ( int n ) { int resultado = 1 ; while ( n > 1 ) { resultado * = n - ; } devolver resultado ; }int main () { constexpr int f4 = Factorial ( 4 ); // f4 == 24 }
A continuación, se muestra un ejemplo de evaluación de la función de tiempo de compilación en el lenguaje de programación D : [3]
int factorial ( int n ) { if ( n == 0 ) return 1 ; return n * factorial ( n - 1 ); }// calculado en el momento de la compilación enum y = factorial ( 0 ); // == 1 enumeración x = factorial ( 4 ); // == 24
Este ejemplo especifica una función D válida llamada "factorial" que normalmente se evaluaría en tiempo de ejecución. El uso de enum
le dice al compilador que el inicializador de las variables debe calcularse en tiempo de compilación. Tenga en cuenta que los argumentos de la función también deben poder resolverse en tiempo de compilación. [4]
CTFE se puede utilizar para poblar estructuras de datos en tiempo de compilación de una manera simple (D versión 2):
int [] genFactorials ( int n ) { resultado automático = new int [ n ]; resultado [ 0 ] = 1 ; foreach ( i ; 1 .. n ) resultado [ i ] = resultado [ i - 1 ] * i ; devolver resultado ; } enum factorials = genFactorials ( 13 );void main () {}// 'factoriales' contiene en tiempo de compilación: // [1, 1, 2, 6, 24, 120, 720, 5_040, 40_320, 362_880, 3_628_800, // 39_916_800, 479_001_600]
CTFE se puede utilizar para generar cadenas que luego se analizan y compilan como código D en D.
Referencias
- ^ Daveed Vandevoorde, Edison Design Group (18 de abril de 2003). "Metaprogramación reflexiva en C ++" (PDF) . Consultado el 19 de julio de 2015 .
- ^ Gabriel Dos Reis y Bjarne Stroustrup (marzo de 2010). "Expresiones generales constantes para lenguajes de programación de sistemas. SAC-2010. El 25º Simposio ACM sobre Computación Aplicada" (PDF) .
- ^ Especificación del lenguaje D 2.0: Funciones
- ^ D 2.0 especificación del lenguaje: Atributos
enlaces externos
- Ejemplos de Rosettacode de evaluación de funciones en tiempo de compilación en varios lenguajes