D语言基本类型判断 traits.d

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  公共类型

alias X = CommonType!(int, long, short);
alias Y = CommonType!(int, char[], short);
auto v1 = typeid(X);
auto 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]);
原文地址:https://www.cnblogs.com/wanhongnan/p/5735213.html