2011-07-03 9 views
12

Si escriboevaluación en tiempo

enum chars = digits ~ uppercase; 

se pueden concatenar la cadena en tiempo de compilación? Supongo que lo hará. Si lo reemplazo con un literal de cadena o una función CTFE, no puedo medir ninguna diferencia de rendimiento significativa (incluso llamándola cien millones de veces). Me sale una diferencia si reemplazo enum con const. Me han dicho que es ineficiente escribirlo así. Pensé que era algo conveniente y no veo la ineficiencia. (Por cierto, la línea está en una función que se llama recursivamente).

El código completo (la conversión a un sistema de numeración con una base diferente)

import std.string; 

string toBase(long n, int b) 
in { 
    assert(2 <= b && b <= 35); 
} body { 
    static string sign; 
    if (n < 0) { 
     n *= -1; 
     sign = "-"; 
    } 
    enum chars = digits ~ uppercase; 
    size_t r = cast(size_t)(n % b); 
    if (n == r) { 
     return sign ~ chars[r]; 
    } 
    return toBase((n - r)/b, b) ~ chars[r]; 
} 

Editar: actualización de código, en respuesta a los comentarios, no es relevante para la cuestión

string toBase(long n, int b) 
in { 
    assert(2 <= b && b <= 35); 
} body { 
    enum chars = digits ~ uppercase; 
    long r = n % b; 
    char c = chars[cast(size_t) abs(r)]; 
    if (n == r) { 
     return (n < 0 ? "-" : "") ~ c; 
    } 
    return toBase((n - r)/b, b) ~ c; 
} 
+2

se olvidó de restablecer la cadena de signos (puede usar 'scope (exit) sign =" ";' para eso) así 'toBase (-10,10)' seguido de 'toBase (10,10)' dará el mismo resultado –

+0

Derecha. Ja ja ja, la primera vez que uso una variable estática. Difícil. Esa cosa de alcance (salida) es realmente útil ¿no? Estoy un poco sorprendido de que una llamada recursiva no califique como una salida de alcance. – fwend

+1

un osciloscopio (salir) se ejecuta cuando el marco de pila actual se saca de la pila (como intentar ... finalmente realmente pero sin la sangría adicional) la recursión no hace eso –

Respuesta

9

enum ejemplificaciones como que son siempre evaluados en tiempo de compilación (y lanzar errores de compilación cuando la evaluación es imposible en tiempo de compilación)

por lo que la concatenación se realiza en tiempo de compilación y una versión inmutable se almacena en el código y se hace referencia en tiempo de ejecución

5

Una forma de comprobar por sí mismo si la cadena se concatena en tiempo de compilación es compilar el código y examinar la archivo de objeto. Asumiendo que su archivo se llama test.d:

dmd -c test.d 
objdump test.o | grep -C3 "" 

... debería producir algo como:

Contents of section .rodata: 
0000 2d000000 00000000 00000000 00000000 -............... 
0010 01000000 00000000 00000000 00000000 ................ 
0020 30313233 34353637 38394142 43444546ABCDEF 
0030 4748494a 4b4c4d4e 4f505152 53545556 GHIJKLMNOPQRSTUV 
0040 5758595a 00000000 00000000 00000000 WXYZ............ 
0050 24000000 00000000 20000000 00000000 $....... ....... 

(Esto es en Linux; en otras plataformas, tendrá diferentes herramientas para inspeccionar el archivo de objeto .)

Si cambia de enum a const o string, usted (probablemente) obtener sin salida: no habrá cadena concatenada de grep de encontrar.

Pero el compilador puede concatenar cadenas en tiempo de compilación incluso cuando enum no se utiliza. Considere este programa:

import std.stdio; 

enum a = "Aaaa"; 
enum b = "Bbbb"; 
enum c = "Cccc"; 

void main() 
{ 
    enum x = a ~ b; 
    const y = b ~ a; 
    string z = a ~ c; 
    writeln(x, y, z); 
} 

Ahora, compilarlo, y examinar el archivo de objeto:

% dmd -c test2.d && objdump -s test2.o | egrep "(Aaaa|Bbbb)" 
0000 42626262 41616161 00000000 00000000 BbbbAaaa........ 
0020 41616161 43636363 00000000 00000000 AaaaCccc........ 
0040 41616161 42626262 00000000 00000000 AaaaBbbb........ 

Vemos que x, y y z, son literales estáticas. (Marcos a, y bc como const en lugar de enum, y puede ver un comportamiento diferente.) Por lo tanto, mientras que enum es una garantía de la evaluación en tiempo de compilación, la ausencia de enum no impide en tiempo de compilación evaluación.

Cuestiones relacionadas