C++을 먼저 해본 경험이 있어 템플릿 메타 프로그래밍 을 해봤다면, D 언어에도 비슷한 요소가 있기에 마음이 놓일 것입니다.
템플릿 메타 프로그래밍은 타입을 템플릿을 통해 전달해, 실행에 필요한 요소를 미리 결정하여 좀 더 일반화된 동작을 수행할 수 있는 코드를 작성하게 해줍니다.
static if
와 is
(static if
& is
)if
는 프로그램 실행 중에 어느 코드를 실행할지 결정할 때 쓰이지만, static if
는 어느 코드를 컴파일해야 할지 결정하는데 쓰입니다.
static if
에서 컴파일될 코드는 오직 컴파일 시점에만 결정되며, 프로그램 실행 중에 결정되는 건 아닙니다.
static if(is(T == int))
writeln("T 는 int 타입입니다");
static if (is(typeof(x) : int))
writeln("변수 x는 자동적으로 int로 변환되는 타입의 값입니다.");
is
표현식 을 이용해 컴파일 시점에 타입 제네릭(type generic) 조건을 확인합니다.
static if(is(T == int)) { // T는 템플릿 파라미터로, 생략된 코드에 정의되어 있습니다
int x = 10;
}
일반적으로 { }
코드 블럭은 새 스코프(scope)를 만들지만, static if
는 조건문이 참인 경우 단순히 static if
에 딸려오는 중괄호만을 제거합니다.
만약 static if
를 사용하면서도 새 스코프(scope)를 만들고자하면 { {
로 열고 } }
로 닫아주셔야합니다.
static if
는 함수나 타입 선언부 등 그 어디서든 어디에서든 이용이 가능합니다.
mixin template
)자주 반복되는 상용구 코드(boiler plate) 를 다듬을 때 mixin template
을 사용하는 걸 권합니다.
mixin template Foo(T) {
T foo;
}
...
mixin Foo!int; // { 와 }가 없어지고, int foo 변수가 선언되어 이용 가능해집니다.
mixin template
으로 if
나 반복문이 포함되는 복잡한 표현도 삽입하실 수 있습니다. C를 사용했던 분이라면, 이제 전처리기(pre-processor)와 이별하고 D 언어를 만나기 딱 좋은 타이밍입니다.
템플릿을 작성할 때, 타입이 어떤 속성들을 갖춰야하는지에 대해 여러가지 제약사항을 걸 수 있습니다.
void foo(T)(T value)
if (is(T : int)) { // foo!T 는 T가 int 타입으로
// 변환될 수 있을 때만 유효합니다
}
제약사항을 작성할 때 참 또는 거짓으로 결과가 나오는 여러 조건식을 조합할 수 있으며, 컴파일 시점에 결정될 수 있는 트레이트(trait)도 조건식에서 이용할 수 있습니다.
일례로, std.range.primitives.isRandomAccessRange
를 들 수 있습니다. 임의 접근(random access)를 지원하는 범위 탐색 타입인지 확인하는 트레이트인데, 이 임의 접근은 소스 코드 상에서 []
연산자로 표현됩니다.