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]);
时间: 2024-10-30 14:04:19

D语言基本类型判断 traits.d的相关文章

c++模板元编程七:类型判断的traits类

2 用于判断类型的traits类 is_void类可以判断模板参数的类型,使用很简单,注意,也可以直接使用::value. cout << std::is_void<void>::type::value << endl; cout << std::is_void<bool>::type::value << endl; 但是实现很有趣,特化居然可以用来继承不同的类.这里没有去找clang++实现代码,用boost代码代替吧. templ

程序猿之---C语言细节16(看了绝对值,编译类型ANSI C和K&amp;R C类型判断,c编译器类型转换bug的细节)

主要内容:编译类型ANSI C和K&R C类型判断,c编译器bug的细节 #include <stdio.h> int main() { // 例子1 :编译器类型判断 /* * K&R采用无符号保留原则,即当一个无符号类型与ing 或更小的整型混合使用时,结果类型为无符号 * ANSI C采用值保留原则, 即当把几个整数操作数像下面这样混合使用时,结果类型可能为有符号也可能为无符号 * ,结果取决于操作数的类型的相对大小 */ if(-1 < (unsigned cha

C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义(转载)

C#与Java对比学习:类型判断.类与接口继承.代码规范与编码习惯.常量定义 类型判断符号: C#:object a;  if(a is int) { }  用 is 符号判断 Java:object a; if(a instanceof Integer) { } 用 instanceof 符号判断 类与接口的继承: C#:public class MDataRow : List<MDataCell>, IDataRecord, ICustomTypeDescriptor Java:publi

26_Shell语言————if条件判断之文件测试、短路操作符

一.文件测试 文件测试大多都是单目测试,其用法相对简单,其格式为: 操作符:文件路径 可以用来测试的选项有: -f:测试其是否为普通文件,即使用ls -l命令查看时,文件类型显示为 - 的文件: -d:测试其是否为目录文件,即使用ls -l命令查看时,文件类型显示为 d的文件: -e:测试文件是否存在,不论是目录还是文件,如果存在则为真,否则为假: -r:测试文件对当前访问者来说(非创建者)是否可读: -w:测试文件对当前访问者来说(非创建者)是否可写: -x:测试文件对当前访问者来说(非创建者

动态语言/动态类型语言/静态类型语言

动态语言 指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除,即结构上的变化 如众所周知的ECMAScrip(JavaScript)便是一个动态语言 除此之外,Ruby.Python也都属于动态语言 C与C++则不属于动态语言 动态类型语言 指类型检查是在运行时做的 静态类型语言 分析 类型检查是在运行前判断(如编译阶段),如C#和java都是静态类型语言 静态类型语言为了达到多态,会采取一些类型鉴别手段,如继承.接口 而动态类型语言不需要,所以一般动态语言都会采用dynam

JavaScript类型判断

JavaScript的数据类型可以分为:标准类型和对象类型. 标准类型有:undefined Null Boolean Date Number Object 对象类型(构造器类型)有:Boolean Date Number Object Array Date Error Function RegExp 用来判断数据类型的一般有四种方式,分别是: 1.typeof 可以识别标准类型(Null除外) 不能识别对象类型(Function除外) 2.Prototype.toString() 可以识别标准

17.C#类型判断和重载决策(九章9.4)

今天来结束第九章,聊下我们经常忽略,但是编译器会帮我们完成的"类型判断和重载决策",理解编译器如何帮我们完成,相信在写代码时会更明确,避免一些编译出错,排查的问题,让我们开发更给力. 我们知道隐式类型的数组以及将方法组转换为委托类型都需要类型推断,但将方法组作为其它方法的参数进行转换时,会显得极其复杂,我们由浅入深,一步一步来看,编译器是如何帮我们做的一些推断. 1 //定义一个泛型方法,参数分别为TInput类型和一个Func<TInput, TResult>类型的委托

NAT类型判断

本文给出NAT类型判断代码 Cone NAT or Symmetric NAT 具体实现框图如下:若SERVER A和SERVER B返回给Client的PORT1和PORT2相等,则该NAT为Cone NAT,否则为Symmetric NAT. Is Full Cone NAT? 具体实现框图如下:若Client能收到SERVER B返回的数据,则NAT为Full Cone NAT. IP-Restricted Cone NAT or Port-Restricted Cone NAT 具体实现

写python的一些坑:pocket api,类型判断,unicode写文件,raise

1.pocket api pocket新版api不允许直接发送用户名跟密码,所以需要先申请app的consumer_key,然后再get_request_token,拿到一个request_token,再通过consumer_key和request_token用浏览器访问authorize网站,之后手工点击授权,然后返回access_token.今后在应用里使用consumer_key和access_token就可以向使用账号的操作(添加.删除)了. 用python很好实现. 2.python类