2011-07-03 14 views
12

Ben Derleme zamanı değerlendirme

enum chars = digits ~ uppercase; 

dize derleme sırasında birleştirilmiş olacak yazarsam? Yapacağını farz ediyorum. Bir dize ile birebir değiştirin veya CTFE fonksiyonu herhangi önemli performans farklılıkları ölçemez Eğer (hatta yüz milyon kere çağırarak). Enum'u const ile değiştirirsem bir fark alırım. Buna böyle yazmanın etkisiz olduğu söylendi. Bir tür uygun olduğunu düşünmüş ve verimsizlik görmüyorum. (Btw, satır yinelemeli denir bir fonksiyonu olan).

tam kod

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]; 
} 

Düzenleme (farklı tabanı olan bir sayı sistemine dönüştürülmesi): Söz

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

İşaret dizgisini sıfırlamayı unutmuştunuz ('scope (exit) 'işaretini = =" ";' bunun için), 'toBase (-10,10)' takiben 'toBase (10,10)' verecek aynı sonuç –

+0

Sağ. Ha ha ha, ilk defa bir statik değişken kullanıyorum. Zor. Bu kapsam (çıkış) şey gerçekten yararlı değil mi? Biraz bir kapsam çıkış olarak nitelemek gelmez yinelemeli çağrı şaşırdım. – fwend

+1

Geçerli bir kapsam çerçevesi yığınının üstüne atıldığında bir kapsam (çıkış) yürütülür (try ... son olarak gerçekten fazladan girinti olmadan) özyineleme bu –

cevap

9

enum örneklemi benzeri yorumlara yanıt olarak güncellenen kod, alakalı değil her zaman derleme zamanında değerlendirilir (ve derleme zamanında değerlendirme imkansız olduğunda derleme hataları atılır)

böylece birleştirme derleme zamanında yapılır ve değişmez bir versiyon zamanında dize derleme zamanında birleştirilmiş olup olmadığını kendiniz de kontrol

5

Tek yön kodunda saklanan ve başvuruda bulunulan kod derlemek ve incelemektir nesne dosyası. Dosyanızı varsayarsak test.d denir:

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 $....... ....... 

(Bu Linux üzerinde olduğu; diğer platformlarda, nesne dosyasını incelemek için farklı araçlar gerekir:

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

... şöyle bir çıktı üretir .)

size enumconst veya string, siz (muhtemelen) alacak hiçbir çıkış değiştirirseniz: grep bulmak için birleştirilmiş dize olacaktır.

Fakat derleyici enum kullanılmasa bile derleme zamanında dizeleri arada olabilir. Şimdi

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); 
} 

derlemek ve nesne dosyasını inceleyin: Bu programı düşünün Biz x, y ve z tüm statik değişmezdir görüyoruz

% 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........ 

. enum derleme zamanı değerlendirmenin bir garanti iken, (Mark a, b ve cconst yerine enum olarak, ve sen. Farklı davranış görebilirsiniz) Böylece, enum yokluğu derleme zamanı değerlendirme engellemez.