속성
속성 (Properties)
D에서는 모든 심볼(symbol), 타입(type), 표현식(expression)에 대해 조회할 수 있는 내장 속성(property)이 있어요. .init, .sizeof, .stringof, .mangleof 등과 같은 속성은 타입이나 표현식의 크기·기본값·이름·링키지 표현 등을 얻는 데 사용돼요. 이 문서는 공통 속성부터 타입별 속성, 사용자 정의 속성까지 다루어요.
출처: Properties
본문
공통 속성 (Common Properties)
모든 심볼, 타입, 표현식에는 조회할 수 있는 속성이 있어요:
| 속성 | 설명 |
|---|---|
.mangleof |
타입의 'mangled' 표현을 나타내는 문자열 |
.stringof |
타입의 소스 표현(source representation)을 나타내는 문자열 |
예제:
int.mangleof는 문자열"i"를 산출해요.int.stringof는 문자열"int"를 산출해요.(1+2).stringof는 문자열"1 + 2"를 산출해요.
타입 속성 (Type Properties)
모든 타입은 조회할 수 있는 속성을 가져요. 모든 표현식도 이 속성들을 가지며, 이는 표현식의 타입 속성과 동일해요. 이 속성들은 다음과 같아요:
| 속성 | 설명 |
|---|---|
.init |
초기화 값 (initializer) |
.sizeof |
바이트 단위 크기 |
.alignof |
정렬 크기 (alignment size) |
예제:
int.init는0을 산출해요.int.sizeof는4를 산출해요.(3).sizeof는4를 산출해요 (3이int이기 때문).
숫자 속성 (Numeric Properties)
정수형 (Integral Types) 속성:
| 속성 | 설명 |
|---|---|
.max |
최대값 |
.min |
최소값 |
예제:
byte.min은-128을 산출해요.ubyte.max는255를 산출해요.
부동소수점형 (Floating Point Types) 속성:
| 속성 | 설명 |
|---|---|
.infinity |
무한대 값 |
.nan |
NaN(Not a Number) 값 (다른 NaN 값도 생성될 수 있어요) |
.dig |
십진 정밀도 자릿수 |
.epsilon |
값 1에 더해지는 가장 작은 증가분 |
.mant_dig |
가수(mantissa)의 비트 수 |
.max_10_exp |
10^max_10_exp가 표현 가능한 최대 int 값 |
.max_exp |
2^(max_exp-1)이 표현 가능한 최대 int 값 |
.min_10_exp |
10^min_10_exp가 정규화된 값으로 표현 가능한 최소 int 값 |
.min_exp |
2^(min_exp-1)이 정규화된 값으로 표현 가능한 최소 int 값 |
.max |
무한대가 아닌 가장 큰 표현 가능한 값 |
.min_normal |
0이 아닌 가장 작은 표현 가능한 정규화된 값 |
예제:
float.nan은 부동소수점 NaN 값을 산출해요.(2.5F).nan은 부동소수점 NaN 값을 산출해요.
복소 부동소수점형 (Complex Floating Point Types) 추가 속성:
| 속성 | 설명 |
|---|---|
.re |
실수부 (real part) |
.im |
허수부 (imaginary part) |
파생 타입 속성 (Derived Type Properties)
다음을 참고하세요:
- Array Properties
- Associative Array Properties
- Vector Properties
- Class Properties
- Enum Properties
- Struct Properties
.init 속성
.init는 기본 초기화 값(default initializer)인 상수 표현식을 산출해요. 타입에 적용하면 그 타입의 기본 초기화 값이고, 변수나 필드에 적용하면 그 변수나 필드 타입의 기본 초기화 값이에요. 각종 타입의 기본값은 아래와 같아요:
| 타입 | .init 값 |
|---|---|
char |
'\xff' |
dchar |
'\xffff' |
wchar |
'\xffff' |
| Enum | 첫 번째 멤버 값 |
| 정수 (Integers) | 0 |
| 부동소수점 (Floating Point) | NaN |
| 참조 타입 (Reference Types) | null |
| Struct | 각 필드의 기본값 |
| Union | 첫 번째 멤버 값 |
Rationale: (근거) 가능하다면 타입의 기본값은 유효하지 않은 값(invalid value)이어야 해요.
int a;
int b = 1;
static assert(int.init == 0);
static assert(a.init == 0);
static assert(b.init == 0);
struct Foo
{
int a;
int b = 7;
}
static assert(Foo.init.a == 0);
static assert(Foo.init.b == 7);
.init vs 기본 초기화 (Default Initialization)
.init는 정적으로 초기화된 객체를 산출하는데, 이는 값 타입의 기본 초기화와 다를 수 있어요:
- 중첩 struct
S의 경우,S.init의 컨텍스트 포인터는null이에요. - struct
S에@disable this();가 있으면T.init가 논리적으로 올바르지 않은 객체를 반환할 수 있어요.
마찬가지로 struct의 정적 배열도 .init과 기본 초기화 사이에서 다른 동작을 보일 수 있어요.
.stringof 속성
.stringof는 자신의 접두부(prefix)의 소스 표현(source representation)인 상수 문자열을 산출해요. 타입에 적용하면 그 타입의 문자열이고, 표현식에 적용하면 그 표현식의 소스 표현이에요. 표현식은 평가되지 않아요.
module test;
import std.stdio;
struct Dog { }
enum Color { Red }
int i = 4;
void main()
{
writeln((1+2).stringof); // "1 + 2"
writeln(test.stringof); // "module test"
writeln(Dog.stringof); // "Dog"
writeln(int.stringof); // "int"
writeln((int*[5][]).stringof); // "int*[5][]"
writeln(Color.Red.stringof); // "Red"
writeln((5).stringof); // "5"
writeln((++i).stringof); // "i += 1"
assert(i == 4); // `++i` was not evaluated
}
Implementation Defined: (구현 정의 사항) 타입이나 표현식의 문자열 표현은 달라질 수 있어요.
Best Practices: (모범 사례) 코드 생성을 위해
.stringof를 사용하지 마세요. 대신identifier특성(trait)이나std.traits.fullyQualifiedName같은 Phobos 헬퍼 함수를 사용하세요.
.sizeof 속성
e.sizeof는 표현식 e의 바이트 크기를 알려줘요. 멤버의 크기를 얻을 때는 this 객체가 필요하지 않아요:
struct S
{
int a;
}
static assert(S.a.sizeof == 4);
static assert(Object.sizeof == (void*).sizeof);
.sizeof를 클래스 객체에 적용하면 클래스 인스턴스 크기가 아니라 클래스 참조의 크기를 반환해요. __traits(classInstanceSize)도 참고하세요.
.alignof 속성
.alignof는 표현식이나 타입의 정렬 크기(aligned size)를 알려줘요. 예를 들어 정렬 크기가 1이면 바이트 경계(byte boundary)에 정렬된다는 뜻이고, 4면 32비트 경계에 정렬된다는 뜻이에요. 예제는 align 속성을 참고하세요.
Implementation Defined: (구현 정의 사항) 실제 정렬 크기.
Best Practices: (모범 사례) 외부에서 정해진 레이아웃에 맞춰야 하는 객체를 배치할 때 특히 주의하세요. 데이터 정렬 불일치(data misalignment)는 특히 해로운 버그를 초래할 수 있어요. 올바른지 확인하는
assert를 넣을 가치가 있는 경우가 많아요.
.mangleof 속성
망글링(mangling)은 심볼이 생성된 객체 파일에서 텍스트 형태로 어떻게 표현되는지를 말해요. .mangleof는 적용된 타입이나 심볼의 표현에 대한 문자열 리터럴을 반환해요. D 링키지의 타입과 심볼 망글링은 Name Mangling에 정의돼 있어요.
Implementation Defined: (구현 정의 사항) 심볼에 선행 밑줄(
_)이 추가되는지 여부, 그리고 non-D 링키지 타입·심볼의 망글링. C 및 C++ 링키지의 경우 이는 일반적으로 연관 C/C++ 컴파일러가 하는 것과 일치해요.
.classinfo 속성
.classinfo는 클래스 객체의 동적 타입(dynamic type)에 대한 정보를 제공해요. 타입 object.TypeInfo_Class에 대한 참조를 반환해요. .classinfo를 인터페이스에 적용하면 그 인터페이스의 정보를 제공하며, 인터페이스가 인스턴스일 수 있는 클래스의 정보는 주지 않아요.
.tupleof 속성
.tupleof는 struct나 class의 모든 비정적(non-static) 필드의 심볼 시퀀스를 제공해요. 튜플 안의 필드 순서는 필드가 선언된 순서와 일치해요.
클래스의 경우 숨겨진 필드와 기반 클래스의 필드는 제외돼요.
흔한 사용 사례는 foreach 루프로 필드를 순회하는 것이에요:
struct Vector3
{
int x, y, z;
}
void test()
{
Vector3 v = Vector3(5, 10, 15);
float sum = 0;
foreach(num; v.tupleof)
{
sum+= num;
}
writeln(sum); //30
}
사용자 정의 속성 (User-Defined Properties)
사용자 정의 속성은 Property Functions를 사용해 만들 수 있어요.