D 1.0   D 2.0
About Japanese Translation

www.digitalmars.com
Last update Sat Mar 6 19:22:36 2010

特性

特性 (trait) は、コンパイル時に、 プログラムからコンパイラの内部情報を取得できるようにする言語拡張です。 コンパイル時リフレクション と呼ばれることもあります。 構文は(pragmaに似た)簡単に拡張可能な形式で、 新しい機能が必要になったら すぐに追加できるようになっています。

TraitsExpression:
    __traits ( TraitsKeyword , TraitsArguments )

TraitsKeyword:
    isAbstractClass
    isArithmetic
    isAssociativeArray
    isFinalClass
    isFloating
    isIntegral
    isScalar
    isStaticArray
    isUnsigned
    isVirtualFunction
    isAbstractFunction
    isFinalFunction
    isStaticFunction
    isRef
    isOut
    isLazy
    hasMember
    identifier
    getMember
    getOverloads
    getVirtualFunctions
    classInstanceSize
    allMembers
    derivedMembers
    isSame
    compiles

TraitsArguments:
    TraitsArgument
    TraitsArgument , TraitsArguments

TraitsArgument:
    AssignExpression
    Type

isArithmetic

引数が全て、算術型であるか算術型の式である場合、 true を返します。 それ以外の場合は false を返します。 引数が無い場合は false を返します。

import std.stdio;

void main()
{
    int i;
    writefln(__traits(isArithmetic, int));
    writefln(__traits(isArithmetic, i, i+1, int));
    writefln(__traits(isArithmetic));
    writefln(__traits(isArithmetic, int*));
}

出力:

true
true
false
false

isFloating

isArithmetic と同じように、浮動小数点数型 (虚数型と複素数型を含む) かどうかを判定します。

isIntegral

isArithmetic と同じように、整数型 (文字型を含む) かどうかを判定します。

isScalar

isArithmetic と同じように、スカラ型 かどうかを判定します。

isUnsigned

isArithmetic と同じように、符号無し型 かどうかを判定します。

isStaticArray

isArithmetic と同じように、静的配列型 かどうかを判定します。

isAssociativeArray

isArithmetic と同じように、連想配列型 かどうかを判定します。

isAbstractClass

引数が全て、abstractクラス型であるかabstractクラス型の式である場合、 true を返します。 それ以外の場合は false を返します。 引数が無い場合は false を返します。

import std.stdio;

abstract class C { int foo(); }

void main()
{
    C c;
    writefln(__traits(isAbstractClass, C));
    writefln(__traits(isAbstractClass, c, C));
    writefln(__traits(isAbstractClass));
    writefln(__traits(isAbstractClass, int*));
}

出力:

true
true
false
false

isFinalClass

isAbstractClass と同じように、finalクラス かどうかを判定します。

isVirtualFunction

引数を1つ取ります。その引数が仮想関数なら true、そうでなければ false を返します。

import std.stdio;

struct S
{
  void bar() { }
}

class C
{
  void bar() { }
}

void main()
{
    writefln(__traits(isVirtualFunction, C.bar));  // true
    writefln(__traits(isVirtualFunction, S.bar));  // false
}

isAbstractFunction

引数を1つ取ります。その引数がabstract関数なら true、そうでなければ false を返します。

import std.stdio;

struct S
{
  void bar() { }
}

class C
{
  void bar() { }
}

class AC
{
  abstract void foo();
}

void main()
{
    writefln(__traits(isAbstractFunction, C.bar));   // false
    writefln(__traits(isAbstractFunction, S.bar));   // false
    writefln(__traits(isAbstractFunction, AC.foo));  // true
}

isFinalFunction

引数を1つ取ります。その引数がfinal関数なら true、そうでなければ false を返します。

import std.stdio;

struct S
{
  void bar() { }
}

class C
{
  void bar() { }
  final void foo();
}

final class FC
{
  void foo();
}

void main()
{
    writefln(__traits(isFinalFunction, C.bar));	  // false
    writefln(__traits(isFinalFunction, S.bar));	  // false
    writefln(__traits(isFinalFunction, C.foo));	  // true
    writefln(__traits(isFinalFunction, FC.foo));  // true
}

isStaticFunction

引数を一つ取り、それが静的関数ならば、 つまり context pointer を持たないならば true を返します。それ以外では false を返します。

isRef, isOut, isLazy

引数を1つとります。引数が宣言であった場合、 ref, out, lazy, ならば true を返し、それ以外の場合では false になります。

void fooref(ref int x)
{
    static assert(__traits(isRef, x));
    static assert(!__traits(isOut, x));
    static assert(!__traits(isLazy, x));
}

void fooout(out int x)
{
    static assert(!__traits(isRef, x));
    static assert(__traits(isOut, x));
    static assert(!__traits(isLazy, x));
}

void foolazy(lazy int x)
{
    static assert(!__traits(isRef, x));
    static assert(!__traits(isOut, x));
    static assert(__traits(isLazy, x));
}

hasMember

第一引数には、メンバがあるか調べたい型か、 メンバがあるか調べたい型を持つ式を指定します。 第二引数は文字列です。 その文字列が指定された型の有効なプロパティだった場合 true、そうでなければ false を返します。

import std.stdio;

struct S
{
    int m;
}

void main()
{   S s;

    writefln(__traits(hasMember, S, "m")); // true
    writefln(__traits(hasMember, s, "m")); // true
    writefln(__traits(hasMember, S, "y")); // false
    writefln(__traits(hasMember, int, "sizeof")); // true
}

identifier

シンボルを1つ引数としてとり、 そのシンボルの識別子を文字列として返します。

getMember

二つ引数を取り、 第二引数は文字列です。 "第一引数 . 第二引数を識別子化したもの" という形の式を返します。

import std.stdio;

struct S
{
    int mx;
    static int my;
}

void main()
{ S s;

  __traits(getMember, s, "mx") = 1;  // same as s.mx=1;
  writefln(__traits(getMember, s, "m" ~ "x")); // 1

  __traits(getMember, S, "mx") = 1;  // error, no this for S.mx
  __traits(getMember, S, "my") = 2;  // ok
}

getOverloads

第一引数にはクラス型か、 クラス型を持つ式を指定します。 第二引数には、 そのクラスの関数名にマッチする文字列を指定します。 結果は、その名前で定義されている関数全ての配列です。

import std.stdio;

class D
{
    this() { }
    ~this() { }
    void foo() { }
    int foo(int) { return 2; }
}

void main()
{
    D d = new D();

    foreach (t; __traits(getOverloads, D, "foo"))
	writefln(typeid(typeof(t)));

    alias typeof(__traits(getOverloads, D, "foo")) b;
    foreach (t; b)
	writefln(typeid(t));

    auto i = __traits(getOverloads, d, "foo")[1](1);
    writefln(i);
}

出力:

void()
int()
void()
int()
2

getVirtualFunctions

第一引数にはクラス型か、 クラス型を持つ式を指定します。 第二引数には、 そのクラスの関数名にマッチする文字列を指定します。 結果は、その名前で定義されている仮想関数全ての配列です。

import std.stdio;

class D
{
    this() { }
    ~this() { }
    void foo() { }
    int foo(int) { return 2; }
}

void main()
{
    D d = new D();

    foreach (t; __traits(getVirtualFunctions, D, "foo"))
	writefln(typeid(typeof(t)));

    alias typeof(__traits(getVirtualFunctions, D, "foo")) b;
    foreach (t; b)
	writefln(typeid(t));

    auto i = __traits(getVirtualFunctions, d, "foo")[1](1);
    writefln(i);
}

出力:

void()
int()
void()
int()
2

classInstanceSize

クラス型かクラス型を持つ式一つを 引数に取ります。 返値は size_t 型で、 値はそのクラスのインスタンスが消費するバイト数になります。 この値は、クラスの静的型に基づいたサイズです。 多態は考慮されません。

allMembers

型か、 型を持つ式一つを引数にとります。 返値は文字列リテラルのタプルで、 指定された型及びその基底クラスの全てのメンバの 名前が格納されています。 名前が重複することはありません。 また、組み込みのプロパティは含まれません。

import std.stdio;

class D
{
    this() { }
    ~this() { }
    void foo() { }
    int foo(int) { return 0; }
}

void main()
{
    auto a = __traits(allMembers, D);
    writefln(a);
    // _ctor,_dtor,foo,print,toString,toHash,opCmp,opEquals

    auto b = [ __traits(allMembers, D) ];
    writefln(b);
    // [_ctor,_dtor,foo,print,toString,toHash,opCmp,opEquals]
}

結果の文字列配列がどのような順番になっているかは 特に定義されていません。

derivedMembers

型か、 型を持つ式一つを引数にとります。 返値は文字列リテラルのタプルで、 指定された型の全てのメンバの名前が格納されています。 名前が重複することはありません。 基底クラスのメンバは含まれません。 また、組み込みのプロパティは含まれません。

import std.stdio;

class D
{
    this() { }
    ~this() { }
    void foo() { }
    int foo(int) { return 0; }
}

void main()
{
    auto a = __traits(derivedMembers, D);
    writefln(a);	// _ctor,_dtor,foo
}

結果の文字列配列がどのような順番になっているかは 特に定義されていません。

isSame

二つの引数を受け取り、同じシンボルならば true、 そうでなければ false を返します。

import std.stdio;

struct S { }

int foo();
int bar();

void main()
{
    writefln(__traits(isSame, foo, foo)); // true
    writefln(__traits(isSame, foo, bar)); // false
    writefln(__traits(isSame, foo, S));   // false
    writefln(__traits(isSame, S, S));     // true
    writefln(__traits(isSame, std, S));   // false
    writefln(__traits(isSame, std, std)); // true
}

二つの引数がリテラルとenumで構成された式であって、 同じ値に評価されれば、true が返ります。

compiles

全ての引数がコンパイルが通る(意味的に正しい)ならば、 true を返します。 引数としては、 文法的に正しいシンボル,型,式のいずれかを指定できます。 文や宣言を引数として指定することはできません。

ゼロ引数で呼び出した場合 false となります。

import std.stdio;

struct S
{
    static int s1;
    int s2;
}

int foo();
int bar();

void main()
{
    writefln(__traits(compiles));                      // false
    writefln(__traits(compiles, foo));                 // true
    writefln(__traits(compiles, foo + 1));             // true
    writefln(__traits(compiles, &foo + 1));            // false
    writefln(__traits(compiles, typeof(1)));           // true
    writefln(__traits(compiles, S.s1));                // true
    writefln(__traits(compiles, S.s3));                // false
    writefln(__traits(compiles, 1,2,3,int,long,std));  // true
    writefln(__traits(compiles, 3[1]));                // false
    writefln(__traits(compiles, 1,2,3,int,long,3[1])); // false
}

使い方としては: