D语言中的基本类型函数都放于 traits.d 文件中,该文件每一句就提示:
Templates which extract information about types and symbols at compile time
在编译时提取有关类型和符号的信息的模板。也就是说,这里放的模板及模板函数,都是可以用于在编译时提取类型和符号信息的。
这一部分的函数是可用来进行编译时编程的。D语言中程序分为两个部分,第一部分是编译时执行部分,第二部分是运行时执行部分。
一、符号名称函数 Symbol Name
1)fullyQualifiedName 取完整路径名
auto tmp = fullyQualifiedName!(File); writeln(tmp); //输出 std.stdio.File
2)moduleName 取模块名
auto tmp = moduleName!(File); writeln(tmp); //输出 std.stdio
3)packageName 取包名
auto tmp = packageName!(File);
writeln(tmp);
//输出std 因为File地包为std
二、函数类型判断
1) arity 函数参数的数量
void foo(){} void bar(uint){} auto pn1 = arity!foo; auto pn2 = arity!bar; writeln("pn1:",pn1); writeln("pn2:",pn2); //输出 pn1:0 //输出 pn2:1
2) functionAttributes 取函数的属性
void foo(){} real func(real x) pure nothrow @safe{return x;} auto v1 = functionAttributes!foo; auto v2 = functionAttributes!func & FunctionAttribute.safe; auto v3 = functionAttributes!func & FunctionAttribute.pure_; writeln("v1:",v1); writeln("v2:",v2); writeln("v3:",v3); /* 输出 v1:system v2:safe v3:pure_ */
3) FunctionTypeOf 函数的类型
int test(int a) { return 0; } auto x = is( FunctionTypeOf!test == typeof(test)); writeln("v1:",x); /* 输出 v1:true */
alias F_dglit = FunctionTypeOf!((int a){ return a; }); auto v1 = is(F_dglit* : int function(int)); auto v2 = is(F_dglit* : void function(int)); writeln("v1:",v1); writeln("v2:",v2); /* 输出 v1:true v2:false */
4) isSafe 函数是否为安全类型
@safe int add(int a, int b) {return a+b;} @trusted int sub(int a, int b) {return a-b;} @system int mul(int a, int b) {return a*b;} auto v1 = isSafe!add; auto v2 = isSafe!sub; auto v3 = isSafe!mul; writeln("v1:",v1); writeln("v2:",v2); writeln("v3:",v3); /* 输出 v1:true v2:true v3:false */
5) isUnsafe 函数是否为不安全类型
6) ParameterDefaults
7) ParameterIdentifierTuple
8) ParameterStorageClassTuple
9) Parameters
int foo(int a,string b); auto v1 = typeid(Parameters!foo); writeln("v1:",v1); /* 输出 v1:(int,immutable(char)[]) */
10) ReturnType
int foo(); auto v1 = typeid(ReturnType!foo); writeln("v1:",v1); /* 输出 v1:int */
11) SetFunctionAttributes
12) variadicFunctionStyle
三、Aggregate Type 迭代器类型工具函数
1) BaseClassesTuple 取基类类型 class 的
class C1 { } class C2 : C1 { } class C3 : C2 { } auto v1 = typeid(BaseClassesTuple!Object); auto v2 = typeid(BaseClassesTuple!C1); auto v3 = typeid(BaseClassesTuple!C2); auto v4 = typeid(BaseClassesTuple!C3); writeln("v1:",v1); writeln("v2:",v2); writeln("v3:",v3); writeln("v4:",v4); /* 输出 v1:() v2:(object.Object) v3:(main.main.C1,object.Object) v4:(main.main.C2,main.main.C1,object.Object) */
2) BaseTypeTuple 取类型的基类型 主要是接口
interface I1 { } interface I2 { } interface I12 : I1, I2 { } auto v1 = typeid(BaseTypeTuple!I1); auto v2 = typeid(BaseTypeTuple!I12); writeln("v1:",v1); writeln("v2:",v2); /* 输出 v1:() v2:(main.main.I1,main.main.I2) */
3) classInstanceAlignment 取类的对齐方式
class A { byte b; } class B { long l; } auto v1 = classInstanceAlignment!A; auto v2 = classInstanceAlignment!B; writeln("v1:",v1); writeln("v2:",v2); /* 输出 v1:4 v2:8 */
4) EnumMembers 取
enum A { a,b,c } auto v1 = EnumMembers!A; foreach(i,v;v1) writeln(format("v%d:%s",i,v)); /* 输出 v0:a v1:b v2:c */
5) FieldNameTuple 取字段名集合
struct S { int x; float y; } auto v1 = FieldNameTuple!S; foreach(i,v;v1) writeln(format("v%d:%s",i,v)); /* 输出 v0:x v1:y */
6) Fields 取字段类型
struct S { int x; float y; } auto v1 = typeid(Fields!S); writeln("v1:",v1); /* 输出 v1:(int,float) */
7) hasAliasing
8) hasElaborateAssign
9) hasElaborateCopyConstructor
10) hasElaborateDestructor
11) hasIndirections
12) hasMember 是否有成员函数
struct S { int x; void f(){} void t()(){} template T(){} } static assert(hasMember!(S, "x")); static assert(hasMember!(S, "f")); static assert(hasMember!(S, "t")); static assert(hasMember!(S, "T"));
13) hasNested
14) hasUnsharedAliasing
15) InterfacesTuple 取类型的所有接口类型元组
interface I1 {} interface I2 {} class A : I1, I2 { } class B : A, I1 { } class C : B {} alias TL = InterfacesTuple!C; foreach(i,item;TL) writeln(format("v%d:%s",i,typeid(item))); /* 输出 v0:main.main.I1 v1:main.main.I2 */
16) isNested
17) MemberFunctionsTuple 取类型的所有成员函数元组
18) RepresentationTypeTuple
19) TemplateArgsOf 取模板的参数
20) TemplateOf 取类型的模板
21) TransitiveBaseTypeTuple
四、Type Conversion 类型转换
1) CommonType 公共类型
X = CommonType!(int, long, short); Y = CommonType!(int, char[], short); v1 = typeid(X); v2 = typeid(Y); writeln("v1:",v1); writeln("v2:",v2); /* 输出 v1:long v2:void */
2) ImplicitConversionTargets
3) CopyTypeQualifiers
4) CopyConstness
5) isAssignable 类型2转化为类型1时能不能隐式转换
6) isCovariantWith
7) isImplicitlyConvertible
五、SomethingTypeOf
六、Categories of types
1) isAggregateType 是否为聚合类型
class C; union U; struct S; interface I; static assert( isAggregateType!C); static assert( isAggregateType!U); static assert( isAggregateType!S); static assert( isAggregateType!I); static assert(!isAggregateType!void); static assert(!isAggregateType!string); static assert(!isAggregateType!(int[])); static assert(!isAggregateType!(C[string])); static assert(!isAggregateType!(void delegate(int)));
2) isArray 是否为数组类型
3) isAssociativeArray
4) isAutodecodableString
5) isBasicType
6) isBoolean
7) isBuiltinType
8) isDynamicArray
9) isFloatingPoint
10) isIntegral
11) isNarrowString
12) isNumeric
13) isPointer
14) isScalarType
15) isSigned
16) isSomeChar
17) isSomeString
18) isStaticArray
19) isUnsigned
七、Type behaviours
1) isAbstractClass 是否为抽象类
2) isAbstractFunction 是否为抽象函数
3) isCallable 是否为函数调用类型
4) isDelegate 是否为委托类型
5) isExpressions 是否为表达式类型
6) isFinalClass 是否为最终类类型
7) isFinalFunction 是否为最终函数类型
8) isFunctionPointer 是否为函数指针类型
9) isInstanceOf 类型是否为某泛型的实例化类型
struct Doo(T) { } auto v1 = isInstanceOf!(Doo, Doo!int); writeln("v1:",v1); /* 输出 v1:true */
10) isIterable 是否为迭代器类型
迭代器类型有两种接口:
1. 实现int opApply(int delegate(ref ItemType) dg)函数
2. 实现
@property UserType front();
void popFront() ;
bool empty();
三个函数都可以实现迭代器,实现了迭代器,就可以使用foreach访问了。
struct OpApply { int opApply(int delegate(ref uint) dg) { assert(0); } } struct Range { @property uint front() { assert(0); } void popFront() { assert(0); } enum bool empty = false; } static assert( isIterable!(uint[])); static assert( isIterable!OpApply); static assert( isIterable!(uint[string])); static assert( isIterable!Range); static assert(!isIterable!uint);
11) isMutable 是否为可变类型
12) isSomeFunction 是否为相当函数类型
13) isTypeTuple 是否为类型无组
八、General Types
1) ForeachType 取迭代的项的类型
static assert(is(ForeachType!(uint[]) == uint));
2) KeyType
alias Hash = int[string]; static assert(is(KeyType!Hash == string)); static assert(is(ValueType!Hash == int));
3) Largest 体积最大的类型
static assert(is(Largest!(uint, ubyte, ushort, real) == real)); static assert(is(Largest!(ulong, double) == ulong)); static assert(is(Largest!(double, ulong) == double)); static assert(is(Largest!(uint, byte, double, short) == double));
4) mostNegative
5) OriginalType 取原始类型
enum E : real { a } enum F : E { a = E.a } alias G = const(F); static assert(is(OriginalType!E == real)); static assert(is(OriginalType!F == real)); static assert(is(OriginalType!G == const real));
6) PointerTarget 取指针指向的类型
7) Signed
8) Unqual
9) Unsigned
10) ValueType 值的类型
11) SubTypeOf 取子类型
九、Misc 杂项
1) mangledName 取管理时使用的名称
mangledName!int == int.mangleof 与mangleof功能一样
2) Select
3) select
十、User-Defined Attributes
1) hasUDA 变量是否有某个自定义的属性
enum E; struct S; struct Named { string name; } @("alpha") int a; @(E) int b; @E int c; @(S, E) int d; @S int e; @(S, E, "alpha") int f; @(100) int g; @Named("abc") int h; writeln("alpha:",hasUDA!(a, "alpha")); writeln("E:",hasUDA!(b, E)); writeln("S:",hasUDA!(d, S)); writeln("Named:",hasUDA!(h, Named)); /* 输出 alpha:true E:true S:true Named:true */
2) getUDAs 类型是否有某个自定义的属性
struct Attr { string name; int value; } @Attr("Answer", 42) int a; static assert(getUDAs!(a, Attr)[0].name == "Answer"); static assert(getUDAs!(a, Attr)[0].value == 42); @(Attr("Answer", 42), "string", 9999) int b; static assert(getUDAs!(b, Attr)[0].name == "Answer"); static assert(getUDAs!(b, Attr)[0].value == 42); @Attr("Answer", 42) @Attr("Pi", 3) int c; static assert(getUDAs!(c, Attr)[0].name == "Answer"); static assert(getUDAs!(c, Attr)[0].value == 42); static assert(getUDAs!(c, Attr)[1].name == "Pi"); static assert(getUDAs!(c, Attr)[1].value == 3); struct AttrT(T) { string name; T value; } @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d; static assert(getUDAs!(d, AttrT)[0].name == "Answer"); static assert(getUDAs!(d, AttrT)[0].value == 42); static assert(getUDAs!(d, AttrT)[1].name == "Pi"); static assert(getUDAs!(d, AttrT)[1].value == 3); static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer"); static assert(getUDAs!(d, AttrT!uint)[0].value == 42); static assert(getUDAs!(d, AttrT!int)[0].name == "Pi"); static assert(getUDAs!(d, AttrT!int)[0].value == 3);
3) getSymbolsByUDA 通过属性名称取符号
enum Attr; static struct A { @Attr int a; int b; @Attr void doStuff() {} void doOtherStuff() {} static struct Inner { // Not found by getSymbolsByUDA @Attr int c; } } // Finds both variables and functions with the attribute, but // doesn't include the variables and functions without it. static assert(getSymbolsByUDA!(A, Attr).length == 2); // Can access attributes on the symbols returned by getSymbolsByUDA. static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr)); static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr)); static struct UDA { string name; } static struct B { @UDA("X") int x; @UDA("Y") int y; @(100) int z; } // Finds both UDA attributes. static assert(getSymbolsByUDA!(B, UDA).length == 2); // Finds one `100` attribute. static assert(getSymbolsByUDA!(B, 100).length == 1); // Can get the value of the UDA from the return value static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X"); @UDA("A") static struct C { @UDA("B") int d; } // Also checks the symbol itself static assert(getSymbolsByUDA!(C, UDA).length == 2); static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C"); static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
十一、 未列表部分
1) ParameterIdentifierTuple 参数标识符表
int foo(int num, string name, int); static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
2) ParameterDefaults 参数的默认值
int foo(int num, string name = "hello", int[] = [1,2,3]); static assert(is(ParameterDefaults!foo[0] == void)); static assert( ParameterDefaults!foo[1] == "hello"); static assert( ParameterDefaults!foo[2] == [1,2,3]);