2011-07-03 5 views
12

내가 컴파일 시간 평가

enum chars = digits ~ uppercase; 

문자열이 컴파일시에 연결된됩니다 작성하는 경우? 나는 그것이 할 것이라고 추측하고있다. 문자열 리터럴이나 CTFE 함수로 바꾸면 어떤 중요한 성능 차이도 측정 할 수 없습니다 (심지어 1 억 번이라도 부릅니다). 열거 형을 const로 바꾸면 차이가 있습니다. 나는 이렇게 쓰는 것이 비효율적이라고 들었습니다. 나는 그것이 일종의 편리하다고 생각했고 나는 비효율을 보지 못했다. (BTW, 라인은 재귀 적으로 호출되는 함수에 있습니다).

전체 코드는

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

편집 (다른 기본으로 숫자 시스템으로 변환) : 질문

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

(토큰을 재설정하는 것을 잊었을 때)'toBase (-10,10)'다음에'toBase (10,10)'이 주어지기 때문에 ('scope (exit) sign = ""; ' 같은 결과 –

+0

오른쪽. 하하하, 처음 정적 변수를 사용합니다. 교활한. 그 범위 (출구)는 정말 유용하지 않나요? 재귀 호출이 범위 종료로 적합하지 않다는 사실에 조금 놀랐습니다. – fwend

+1

현재 스택 프레임이 스택을 팝 할 때 scope (exit)가 실행될 때 (try ... finally와 같이 실제로 들었지만 여분의 들여 쓰기가없는 경우) 재귀는 수행하지 않습니다. –

답변

9

enum 인스턴스화 등에 의견에 대 한 응답에서, 업데이트 된 코드, 관련이없는 항상 (컴파일 타임에 평가가 불가능할 때 컴파일 오류가 발생 함)

그래서 연결은 컴파일 타임에 수행되고 불변 버전은 코드에 저장되고 런타임에 참조됩니다.

5

문자열이 컴파일 타임에 연결되었는지 여부를 확인하는 한 가지 방법은 코드를 컴파일하고 오브젝트 파일. 파일을 가정 test.d라고 :

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

(이 리눅스에, 다른 플랫폼에, 당신은 오브젝트 파일을 검사하기 위해 다른 도구가 필요합니다

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

는 ... 같은 것을 생산한다 .)

당신이 당신의 enumconst에 또는 string, 당신은 (아마도) 얻을 것이다 더 출력을 변경할 경우 grep를 찾을 수에 대한 연결된 문자열이 없을 것입니다.

그러나 컴파일러는 enum을 사용하지 않아도 컴파일 타임에 문자열을 연결할 수 있습니다. 지금

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

컴파일하고 오브젝트 파일을 검사 :이 프로그램을 생각해 우리는 x, yz 모든 정적 리터럴 것을 볼

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

합니다. (, bcenum 대신에 enum 대신 표시 될 수 있습니다. 따라서 enum은 컴파일 타임 평가를 보장하지만 enum이 없어도 컴파일 타임 평가를 방해하지 않습니다.

관련 문제