- 文法
- 型 トレイト
- isArithmetic
- isFloating
- isIntegral
- isScalar
- isUnsigned
- isStaticArray
- isAssociativeArray
- isAbstractClass
- isFinalClass
- isCopyable
- isPOD
- toType
- isZeroInit
- hasCopyConstructor
- hasPostblit
- getAliasThis
- getPointerBitmap
- getVirtualFunctions
- getVirtualMethods
- classInstanceSize
- classInstanceAlignment
- initSymbol
- 関数 トレイト
- 関数パラメータのトレイト
- シンボル・トレイト
トレイト
文法
トレイトは、 コンパイル時にプログラムがコンパイラ内部の情報を取得できるようにする 言語の拡張機能である。これは、 コンパイル時リフレクションとも呼ばれる。 これは、特別な、簡単に拡張できる構文( プラグマに類似)として行われるため、必要に応じて新しい機能が 追加できる。
TraitsExpression: __traits ( TraitsKeyword , TraitsArguments ) TraitsKeyword: isAbstractClass isArithmetic isAssociativeArray isFinalClass isPOD isNested isFuture isDeprecated isFloating isIntegral isScalar isStaticArray isUnsigned isDisabled isVirtualFunction isVirtualMethod isAbstractFunction isFinalFunction isStaticFunction isOverrideFunction isTemplate isRef isOut isLazy isReturnOnStack isCopyable isZeroInit isModule isPackage hasMember hasCopyConstructor hasPostblit identifier getAliasThis getAttributes getFunctionAttributes getFunctionVariadicStyle getLinkage getLocation getMember getOverloads getParameterStorageClasses getPointerBitmap getCppNamespaces getVisibility getProtection getTargetInfo getVirtualFunctions getVirtualMethods getUnitTests parent child classInstanceSize classInstanceAlignment getVirtualIndex allMembers derivedMembers isSame compiles toType initSymbol parameters fullyQualifiedName TraitsArguments: TraitsArgument TraitsArgument , TraitsArguments TraitsArgument: AssignExpression Typexml-ph-0000@deepl.internalxml-ph-0000@deepl.internal
型トレイト
isArithmetic
引数がすべて算術型である型、または 算術型として型付けされた式である場合、trueが 返される。 それ以外の場合、false が返される。 引数が存在しない場合、false が返される。
算術型には、整数型と浮動小数点数型がある。
import std.stdio; void main() { int i; writeln(__traits(isArithmetic, int)); writeln(__traits(isArithmetic, i, i+1, int)); writeln(__traits(isArithmetic)); writeln(__traits(isArithmetic, int*)); }
true true false false
isFloating
引数がすべて浮動小数点数型であるか、 または浮動小数点数型として型付けされた式である場合、trueが 返される。 それ以外の場合、false が返される。 引数が存在しない場合、false が返される。
浮動小数点型は以下のとおりである。float 、double 、real 、ifloat 、idouble 、ireal 、cfloat 、cdouble 、creal 、 浮動小数点型のベクトル、および浮動小数点型を基本型とする列挙型。
import core.simd : float4; enum E : float { a, b } static assert(__traits(isFloating, float)); static assert(__traits(isFloating, E)); static assert(__traits(isFloating, float4)); static assert(!__traits(isFloating, float[4]));
isIntegral
引数がすべて整数型であるか、 または整数型として型付けされた式である場合、trueが 返される。 それ以外の場合、false が返される。 引数が存在しない場合、false が返される。
整数型は以下の通り:byte 、ubyte 、short 、ushort 、int 、uint 、long 、ulong 、cent 、ucent 、bool 、char 、wchar 、dchar 、 整数型のベクトル、および整数を基本型とする列挙型。
import core.simd : int4; enum E { a, b } static assert(__traits(isIntegral, bool)); static assert(__traits(isIntegral, char)); static assert(__traits(isIntegral, int)); static assert(__traits(isIntegral, E)); static assert(__traits(isIntegral, int4)); static assert(!__traits(isIntegral, float)); static assert(!__traits(isIntegral, int[4])); static assert(!__traits(isIntegral, void*));
isScalar
引数がすべてスカラ型である型、 またはスカラ型として型付けされた式である場合、trueが 返される。 それ以外の場合は、false が返される。 引数が存在しない場合は、false が返される。
スカラー型は、整数型、 浮動小数点型、 ポインタ型、 スカラー型のベクトル、 およびスカラー型をベースとする列挙型である。
import core.simd : int4, void16; enum E { a, b } static assert(__traits(isScalar, bool)); static assert(__traits(isScalar, char)); static assert(__traits(isScalar, int)); static assert(__traits(isScalar, float)); static assert(__traits(isScalar, E)); static assert(__traits(isScalar, int4)); static assert(__traits(isScalar, void*)); // ポインタを含む! static assert(!__traits(isScalar, int[4])); static assert(!__traits(isScalar, void16)); static assert(!__traits(isScalar, void)); static assert(!__traits(isScalar, typeof(null))); static assert(!__traits(isScalar, Object));
isUnsigned
引数がすべて符号なし型であるか、 または符号なし型として型付けされた式である場合、trueが 返される。 それ以外の場合、false が返される。 引数が存在しない場合、false が返される。
符号なし型は以下の通り:ubyte 、ushort 、uint 、ulong 、ucent 、bool 、char 、wchar 、dchar 、 符号なし型のベクトル、および符号なし型をベースとする列挙型。
import core.simd : uint4; enum SignedEnum { a, b } enum UnsignedEnum : uint { a, b } static assert(__traits(isUnsigned, bool)); static assert(__traits(isUnsigned, char)); static assert(__traits(isUnsigned, uint)); static assert(__traits(isUnsigned, UnsignedEnum)); static assert(__traits(isUnsigned, uint4)); static assert(!__traits(isUnsigned, int)); static assert(!__traits(isUnsigned, float)); static assert(!__traits(isUnsigned, SignedEnum)); static assert(!__traits(isUnsigned, uint[4])); static assert(!__traits(isUnsigned, void*));
isStaticArray
isArithmetic と同様に動作するが、静的配列型用である 。
import core.simd : int4; enum E : int[4] { a = [1, 2, 3, 4] } static array = [1, 2, 3]; // 静的配列ではない: 型はint[3]ではなくint[]と推論される。 static assert(__traits(isStaticArray, void[0])); static assert(__traits(isStaticArray, E)); static assert(!__traits(isStaticArray, int4)); static assert(!__traits(isStaticArray, array));
isAssociativeArray
isArithmetic と同様に動作するが、連想配列型であることを除いて 。
isAbstractClass
引数がすべて抽象クラスである型、または 抽象クラスとして型付けされた式である場合、trueが 返される。 それ以外の場合は、false が返される。 引数が存在しない場合は、false が返される。
import std.stdio; abstract class C { int foo(); } void main() { C c; writeln(__traits(isAbstractClass, C)); writeln(__traits(isAbstractClass, c, C)); writeln(__traits(isAbstractClass)); writeln(__traits(isAbstractClass, int*)); }
true true false false
isFinalClass
isAbstractClass と同様に機能するが、最終クラス用である。
isCopyable
1つの引数を取る。その引数がコピー可能な型である場合、true が返される。 それ以外の場合、false が返される。
struct S { } static assert( __traits(isCopyable, S)); struct T { @disable this(this); // コピー構造を無効にする } static assert(!__traits(isCopyable, T));
isPOD
1つの引数を取り、それは型でなければならない。 型がPOD型の場合、true を返し、そうでない場合はfalse を返す。
toType
単一の引数を取り、string の型式に評価されなければならない。 文字列の内容は、実装で確認された型の文字化けした内容に対応していなければならない。
D のみサポートされている。C++ のような他のマングリングはサポートされていない。
返される値は型である。
template Type(T) { alias Type = T; } Type!(__traits(toType, "i")) j = 3; // jは`int`型として宣言されている static assert(is(Type!(__traits(toType, (int*).mangleof)) == int*)); __traits(toType, "i") x = 4; // xも`int`型として宣言されている
isZeroInit
型である必要がある引数を1つ取る。型の デフォルト初期化子がすべてゼロビット の場合、true が返され、それ以外の場合、false が返される。
struct S1 { int x; } struct S2 { int x = -1; } static assert(__traits(isZeroInit, S1)); static assert(!__traits(isZeroInit, S2)); void test() { int x = 3; static assert(__traits(isZeroInit, typeof(x))); } // `C.init`はヌル参照なので、 // Cクラスでは`isZeroInit`は常に真を返す。 class C { int x = -1; } static assert(__traits(isZeroInit, C)); // 要素`void`型の配列を初期化する。 static assert(__traits(isZeroInit, void));
hasCopyConstructor
引数は型である。それがコピーコンストラクタを持つ構造体の場合、true を返す。それ以外の場合、false を返す。コピーコンストラクタはポストブライトとは異なることに注意。
import std.stdio; struct S { } class C { } struct P { this(ref P rhs) {} } struct B { this(this) {} } void main() { writeln(__traits(hasCopyConstructor, S)); // false writeln(__traits(hasCopyConstructor, C)); // false writeln(__traits(hasCopyConstructor, P)); // true writeln(__traits(hasCopyConstructor, B)); // false、これはポストブリットである }
hasPostblit
引数は型である。それがpostblitを持つ構造体である場合、true を返す。それ以外の場合、false を返す。postblitはコピーコンストラクタとは異なることに注意。
import std.stdio; struct S { } class C { } struct P { this(ref P rhs) {} } struct B { this(this) {} } void main() { writeln(__traits(hasPostblit, S)); // false writeln(__traits(hasPostblit, C)); // false writeln(__traits(hasPostblit, P)); // false、これはコピーctorである writeln(__traits(hasPostblit, B)); // true }
getAliasThis
型という引数を1つ取る。型にalias this 宣言がある場合、 それらの宣言で使用されているメンバの名前(stringとして)のValueSeqを返す。 それ以外の場合、空のシーケンスを返す。
alias AliasSeq(T...) = T; struct S1 { string var; alias var this; } static assert(__traits(getAliasThis, S1) == AliasSeq!("var")); static assert(__traits(getAliasThis, int).length == 0); pragma(msg, __traits(getAliasThis, S1)); pragma(msg, __traits(getAliasThis, int));
tuple("var") tuple()
getPointerBitmap
引数は型である。 結果は、指定された型のインスタンスが使用するメモリを説明するsize_t の配列である。
配列の最初の要素は、型のサイズ(クラスでは クラスインスタンスサイズ)である。
以下の要素は、GC管理下のポインタが、 その型のインスタンスが占有するメモリ内の どの位置にあるかを表す。 T型の場合、xml-ph-0000@deepl.internal個のポインタが存在する。以下の要素は、その型のインスタンスが占有するメモリ内の、GC管理ポインタの位置を記述する。 型 T では、T.sizeof / size_t.sizeof 個のポインタが 配列値のビットで表現される。
この配列は、正確なGCによって誤ったポインタを回避するために使用することができる。
xml-ph-0000@deepl.internalvoid main() { static class C { // 暗黙の仮想関数テーブル・ポインタはマークされない // 暗黙のモニター・フィールドはマークされない、通常は手動で管理される C next; size_t sz; void* p; void function () fn; // GC管理ポインタではない } static struct S { size_t val1; void* p; C c; byte[] arr; // { length, ptr } void delegate () dg; // { context, func } } static assert (__traits(getPointerBitmap, C) == [6*size_t.sizeof, 0b010100]); static assert (__traits(getPointerBitmap, S) == [7*size_t.sizeof, 0b0110110]); }
getVirtualFunctions
getVirtualMethodsと同じだが、 何もオーバーライドしないfinal関数が含まれる点が異なる。
getVirtualMethods
最初の引数はクラス型またはクラス型の式である。 2番目の引数は、そのクラスの関数の名前に一致する文字列である。 結果は、その関数の仮想オーバーロードのシンボルシーケンスである。 何もオーバーライドしないfinal関数は含まれない。
import std.stdio; class D { this() { } ~this() { } void foo() { } int foo(int) { return 2; } } void main() { D d = new D(); foreach (t; __traits(getVirtualMethods, D, "foo")) writeln(typeid(typeof(t))); alias b = typeof(__traits(getVirtualMethods, D, "foo")); foreach (t; b) writeln(typeid(t)); auto i = __traits(getVirtualMethods, d, "foo")[1](1); writeln(i); }
void() int() void() int() 2
classInstanceSize
単一の引数を取り、クラス型またはクラス型の式として評価されなければならない。 結果は size_t 型であり、値は クラス型の実行時インスタンスのバイト数である。 これはクラスの静的型に基づいており、 多型型ではない。
classInstanceAlignment
単一の引数を取り、クラス型またはクラス型の式として評価されなければならない。 結果は size_t 型であり、値は クラス型の実行時インスタンスのアラインメントである。 これはクラス型の静的型に基づいており、 多相型ではない。
initSymbol
単一の引数を取り、class 、struct 、またはunion 型に評価されなければならない。 const(void)[] を返し、その中には指定された型のインスタンスの初期状態が格納される。 スライスは、あらゆる型T に対して以下のように構築される。
- ptr T がゼロ初期化された構造体/共用体である場合、 または の初期化子シンボルを指す。T null
- length インスタンスのサイズに等しく、すなわち、構造体/共用体では 、 T.sizeof __traits(classInstanceSize, T)`。
このトレイトはTypeInfo.initializer() の動作に一致するが、TypeInfo が利用できない場合にも使用できる。
このトレイトは、CTFEでは使用できない。なぜなら、 初期化子シンボルの実際のアドレスはリンカーによって設定されるため、コンパイル時には利用できないからだ。
class C { int i = 4; } /// mallocされた`C`のインスタンスを初期化する void main() { const void[] initSym = __traits(initSymbol, C); void* ptr = malloc(initSym.length); scope (exit) free(ptr); ptr[0..initSym.length] = initSym[]; C c = cast(C) ptr; assert(c.i == 4); }xml-ph-0000@deepl.internalxml-ph-0000@deepl.internal 機能特性
関数トレイト
isDisabled
1つの引数を取り、@disable でマークされた関数宣言であればtrue を返す。 でマークされた関数宣言であれば を返す。
struct Foo { @disable void foo(); void bar(){} } static assert(__traits(isDisabled, Foo.foo)); static assert(!__traits(isDisabled, Foo.bar));
その他の宣言については、@disable が文法的に有効な属性であっても、 注釈に効果がないため、false が返される。
@disable struct Bar{} static assert(!__traits(isDisabled, Bar));
getVirtualIndex
単一の引数を取り、関数として評価されなければならない。 結果は、親型の vtable におけるその関数のインデックスを含むptrdiff_t である 。 渡された関数が final で仮想関数をオーバーライドしていない場合は、 代わりに-1 が返される。
isVirtualFunction
isVirtualMethodと同じだが、 何もオーバーライドしないfinal関数はtrueを返す。
isVirtualMethod
引数を1つ取る。その引数が仮想関数である場合、true が返される。そうでない場合はfalse が返される。 何も上書きしない最終関数はfalseを返す。
import std.stdio; struct S { void bar() { } } class C { void bar() { } } void main() { writeln(__traits(isVirtualMethod, C.bar)); // true writeln(__traits(isVirtualMethod, S.bar)); // false }
isAbstractFunction
1つの引数を取る。その引数が抽象関数である場合、true が返され、そうでない場合はfalse が返される。
import std.stdio; struct S { void bar() { } } class C { void bar() { } } class AC { abstract void foo(); } void main() { writeln(__traits(isAbstractFunction, C.bar)); // false writeln(__traits(isAbstractFunction, S.bar)); // false writeln(__traits(isAbstractFunction, AC.foo)); // true }
isFinalFunction
引数を1つ取る。その引数が最終関数である場合、true が返される。それ以外の場合、false が返される。
import std.stdio; struct S { void bar() { } } class C { void bar() { } final void foo(); } final class FC { void foo(); } void main() { writeln(__traits(isFinalFunction, C.bar)); // false writeln(__traits(isFinalFunction, S.bar)); // false writeln(__traits(isFinalFunction, C.foo)); // true writeln(__traits(isFinalFunction, FC.foo)); // true }
isOverrideFunction
1つの引数を取る。その引数がoverrideでマークされた関数である場合、true が返される。それ以外の場合、false が返される。
import std.stdio; class Base { void foo() { } } class Foo : Base { override void foo() { } void bar() { } } void main() { writeln(__traits(isOverrideFunction, Base.foo)); // false writeln(__traits(isOverrideFunction, Foo.foo)); // true writeln(__traits(isOverrideFunction, Foo.bar)); // false }
isStaticFunction
1つの引数を取る。その引数が静的関数である場合、 つまりコンテキストポインタを持たない場合、true が返される。それ以外の場合、false が返される。
struct A { int foo() { return 3; } static int boo(int a) { return a; } } void main() { assert(__traits(isStaticFunction, A.boo)); assert(!__traits(isStaticFunction, A.foo)); assert(__traits(isStaticFunction, main)); }
isReturnOnStack
引数は1つで、関数シンボル、関数リテラル、 デリゲート、または関数ポインタのいずれかでなければならない。 戻り値はbool で、関数の戻り値が 隠し追加パラメータとして関数に渡されたポインタ経由でスタックに返される 場合、true となる。
struct S { int[20] a; } int test1(); S test2(); static assert(__traits(isReturnOnStack, test1) == false); static assert(__traits(isReturnOnStack, test2) == true);
- レジスタに値を返す方が高速であることが多いので、 最も高速な方法を使用していることを確認するために、よく使用される関数のチェックとして使用できる。
- インラインアセンブラを使用して関数を正しく呼び出す場合。
- コンパイラがこれを正しく実行しているかどうかをテストすることは通常、厄介で難しいが、 この機能により、効率的で直接的なシンプルなテストが可能になる。
getFunctionVariadicStyle
1つの引数を取り、その引数は関数シンボル、または 関数、デリゲート、関数ポインタである型でなければならない。 これは、サポートされている"可変長引数"の種類を識別する文字列を返す。
result | kind | access | example |
---|---|---|---|
"none" | 可変長引数関数ではない | | void foo(); |
"argptr" | D言語のスタイルの可変長引数関数 | _argptr および_arguments | void bar(...) |
"stdarg" | C言語のスタイルの可変長引数関数 | core.stdc.stdarg | extern (C) void abc(int, ...) |
"typesafe" | 型安全な可変長引数関数 | スタック上の配列 | void def(int[] ...) |
import core.stdc.stdarg; void novar() {} extern(C) void cstyle(int, ...) {} extern(C++) void cppstyle(int, ...) {} void dstyle(...) {} void typesafe(int[]...) {} static assert(__traits(getFunctionVariadicStyle, novar) == "none"); static assert(__traits(getFunctionVariadicStyle, cstyle) == "stdarg"); static assert(__traits(getFunctionVariadicStyle, cppstyle) == "stdarg"); static assert(__traits(getFunctionVariadicStyle, dstyle) == "argptr"); static assert(__traits(getFunctionVariadicStyle, typesafe) == "typesafe"); static assert(__traits(getFunctionVariadicStyle, (int[] a...) {}) == "typesafe"); static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg");
getFunctionAttributes
1つの引数を取り、その引数は関数シンボル、関数リテラル、または関数ポインタのいずれかでなければならない。その関数のすべての属性の文字列ValueSeqを返す。xml-ph-0000@deepl.internal引数は1つで、関数シンボル、関数リテラル、または関数ポインタのいずれかでなければならない。 その関数のすべての属性の文字列ValueSeqを返す。 excluding 任意のユーザー定義属性(UDAsは getAttributesトレイトで取得できる)。 属性が存在しない場合は、空のシーケンスを返す。
注釈: 返されるシーケンス内の属性の順序は、 処理系定義であり、依存すべきではない。現在サポートされている属性の一覧は以下の通りである:
、xml-ph-0000@deepl.internal、xml-ph-0001@deepl.internal、xml-ph-0002@deepl.internal、xml-ph-000- pure、nothrow 、@nogc 、@property 、@system 、@trusted 、@safe 、ref 、@live
さらに、以下の属性は非staticメンバ関数にのみ有効である。
xml-ph-0000@deepl.internal、xml-ph-0001@deepl.internal- const、immutable 、inout 、shared
int sum(int x, int y) pure nothrow { return x + y; } pragma(msg, __traits(getFunctionAttributes, sum)); struct S { void test() const @system { } } pragma(msg, __traits(getFunctionAttributes, S.test));
tuple("pure", "nothrow", "@system") tuple("const", "@system")
一部の属性は推測できることに注意。例えば:
pragma(msg, __traits(getFunctionAttributes, (int x) @trusted { return x * 2; }));
tuple("pure", "nothrow", "@nogc", "@trusted")
関数 パラメータ トレイト
isRef, isOut、 isLazy
1つの引数を取る。その引数が宣言の場合、true が返される。それがref 、out、または lazyの場合、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)); }
getParameterStorageClasses
2つの引数を取る。 最初の引数は、関数シンボル、関数呼び出し、または 関数、デリゲート、関数ポインタである型でなければならない。 2番目の引数は、最初の引数が 0である場合、どのパラメータを識別する整数である。 戻り値は、そのパラメータのストレージクラスを表す文字列のValueSeqである。
ref int foo(return ref const int* p, scope int* a, out int b, lazy int c); static assert(__traits(getParameterStorageClasses, foo, 0)[0] == "return"); static assert(__traits(getParameterStorageClasses, foo, 0)[1] == "ref"); static assert(__traits(getParameterStorageClasses, foo, 1)[0] == "scope"); static assert(__traits(getParameterStorageClasses, foo, 2)[0] == "out"); static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy"); int* p, a; int b, c; static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 1)[0] == "scope"); static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 2)[0] == "out"); static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 3)[0] == "lazy");
parameters
関数内部でのみ使用できる。引数を取らず、 囲む関数のパラメータの l値シーケンスを返す。
alias AliasSeq(A...) = A; void f(int n, char c) { alias PS = __traits(parameters); PS[0]++; // increment n static assert(is(typeof(PS) == AliasSeq!(int, char))); // output parameter names static foreach (i, p; PS) { pragma(msg, __traits(identifier, p)); } } int add(int x, int y) { return x + y; } int forwardToAdd(int x, int y) { return add(__traits(parameters)); // 等価である; //return add(x, y); }
関数がネストされている場合、返されるパラメータは 外側の関数ではなく内側の関数のものとなる。
int nestedExample(int x) { // 外側関数のパラメータ static assert(typeof(__traits(parameters)).length == 1); int add(int x, int y) { // 内部関数のパラメータ static assert(typeof(__traits(parameters)).length == 2); return x + y; } return add(x, x); }
class C { int opApply(int delegate(size_t, C) dg) { if (dg(0, this)) return 1; return 0; } } void foreachExample(C c, int x) { foreach(idx; 0..5) { static assert(is(typeof(__traits(parameters)) == AliasSeq!(C, int))); } foreach(idx, elem; c) { // __traits(parameters)は、opApplyに渡されたデリゲートを過去に見ている static assert(is(typeof(__traits(parameters)) == AliasSeq!(C, int))); } }00@deepl.internalxml-ph-0000@deepl.internal 0@deepl.internalxml-ph-0000@deepl.internal
シンボル・トレイト
fullyQualifiedName
型またはシンボルの完全修飾名を取得する。
module myModule; int i; static assert(__traits(fullyQualifiedName, i) == "myModule.i"); struct MyStruct {} static assert(__traits(fullyQualifiedName, const MyStruct[]) == "const(myModule.MyStruct[])");
isNested
1つの引数を取る。 引数が内部でコンテキストポインタを格納するネスト型である場合、true を返す。 それ以外の場合、false を返す。 ネスト型には、クラス、 構造体、 関数がある。
isFuture
1つの引数を取る。引数がシンボルであり、@future キーワードが指定されている場合はtrue を返し、 それ以外はfalse を返す。現在、@future キーワードがサポートされているのは関数と変数宣言のみである。
isDeprecated
deprecated 引数を1つ取る。引数がシンボルで、true キーワードでマークされている場合、 を返す。 それ以外の場合、false を返す。
isTemplate
1つの引数を取る。その引数またはそのオーバーロードのいずれかがテンプレートである場合、true が返される。それ以外の場合、false が返される。
void foo(T)(){} static assert(__traits(isTemplate,foo)); static assert(!__traits(isTemplate,foo!int())); static assert(!__traits(isTemplate,"string"));
isModule
引数を1つ取る。その引数がモジュールを参照するシンボルである場合、true が返される。それ以外の場合はfalse が返される。 パッケージモジュールは、 モジュールとして直接インポートされていない場合でも、モジュールとして扱われる。
import core.thread; import std.algorithm.sorting; // 通常のパッケージ(package.dがない) static assert(!__traits(isModule, core)); // パッケージ・モジュール(package.dファイルがある) // std.algorithmを直接インポートしていないことに注意。 // (言い換えれば、we don't have an "import std.algorithm;"ディレクティブがない。) static assert(__traits(isModule, std.algorithm)); // 通常のモジュール static assert(__traits(isModule, std.algorithm.sorting));
isPackage
引数を1つ取る。その引数がパッケージを参照するシンボルである場合、true が返される。 それ以外の場合、false が返される。
import std.algorithm.sorting; static assert(__traits(isPackage, std)); static assert(__traits(isPackage, std.algorithm)); static assert(!__traits(isPackage, std.algorithm.sorting));
hasMember
最初の引数は、メンバを持つ型、または メンバを持つ型の式である。 2番目の引数は文字列である。 文字列が型の有効なプロパティである場合、true が返され、そうでない場合はfalse が返される。
import std.stdio; struct S { int m; } void main() { S s; writeln(__traits(hasMember, S, "m")); // true writeln(__traits(hasMember, s, "m")); // true writeln(__traits(hasMember, S, "y")); // false writeln(__traits(hasMember, S, "write")); // falseだが、UFCS経由でメンバのように呼び出せる writeln(__traits(hasMember, int, "sizeof")); // true }
identifier
シンボルを1つの引数として受け取る。 そのシンボルの識別子を文字列リテラルとして返す。
xml-ph-0000@deepl.internalint var = 123; pragma(msg, typeof(var)); // int pragma(msg, typeof(__traits(identifier, var))); // string writeln(var); // 123 writeln(__traits(identifier, var)); // "var"
getAttributes
引数としてシンボルを1つ取る。 すべての添付されたユーザー定義属性のシーケンスを返す。 ユーザー定義属性が存在しない場合は空のシーケンスを返す。引数はシンボルを1つだけ取る。 すべての添付されたユーザー定義属性のシーケンスを返す。 ユーザー定義属性が存在しない場合は空のシーケンスを返す
詳細は以下を参照のこと:ユーザー定義属性
印刷:@(3) int a; @("string", 7) int b; enum Foo; @Foo int c; pragma(msg, __traits(getAttributes, a)); pragma(msg, __traits(getAttributes, b)); pragma(msg, __traits(getAttributes, c));
tuple(3) tuple("string", 7) tuple((Foo))
getLinkage
引数は1つで、宣言シンボル、または関数、デリゲート、 関数へのポインタ、構造体、クラス、インターフェイスの型である。 宣言のLinkageAttributeを表す文字列を返す。
- "D"
- "C"
- "C++"
- "Windows"
- "Objective-C"
- "System"
extern (C) int fooc(); alias aliasc = fooc; static assert(__traits(getLinkage, fooc) == "C"); static assert(__traits(getLinkage, aliasc) == "C"); extern (C++) struct FooCPPStruct {} extern (C++) class FooCPPClass {} extern (C++) interface FooCPPInterface {} static assert(__traits(getLinkage, FooCPPStruct) == "C++"); static assert(__traits(getLinkage, FooCPPClass) == "C++"); static assert(__traits(getLinkage, FooCPPInterface) == "C++");
getLocation
シンボルを1つの引数として取る。 オーバーロードを明確にするには、getOverloadsの結果を希望するインデックスとともにxml-ph-0000@deepl.internalに渡す。 戻り値シンボルである引数を1つ取る。 オーバーロードを区別するには、getOverloadsの結果を希望するインデックスとともにgetLocation に渡す。 引数が宣言されたファイル名、行番号、およびカラム番号に対応する2つのintを含むValueSeqを返す。
getMember
2つの引数を取り、2番目の引数は文字列でなければならない。 結果は、1番目の引数から形成された式に 「.」が続き、2番目の引数が識別子として続く。
import std.stdio; struct S { int mx; static int my; } void main() { S s; __traits(getMember, s, "mx") = 1; // s.mx=1;と同じ writeln(__traits(getMember, s, "m" ~ "x")); // 1 // __traits(getMember, S, "mx") = 1; // エラー、S.mxにこれがない __traits(getMember, S, "my") = 2; // OK }
getOverloads
最初の引数は、集約(例えば、構造体/クラス/モジュール)である。 2番目の引数は、string であり、 返すメンバの名前に一致する。 3番目の引数は、bool であり、オプションである。true の場合、 結果にはテンプレートのオーバーロードも含まれる。 結果は、指定された名前のすべてのオーバーロードのシンボルシーケンスである。
import std.stdio; class D { this() { } ~this() { } void foo() { } int foo(int) { return 2; } void bar(T)() { return T.init; } class bar(int n) {} } void main() { D d = new D(); foreach (t; __traits(getOverloads, D, "foo")) writeln(typeid(typeof(t))); alias b = typeof(__traits(getOverloads, D, "foo")); foreach (t; b) writeln(typeid(t)); auto i = __traits(getOverloads, d, "foo")[1](1); writeln(i); foreach (t; __traits(getOverloads, D, "bar", true)) writeln(t.stringof); }
void() int() void() int() 2 bar(T)() bar(int n)
getCppNamespaces
引数はシンボルである。 結果は、シンボルが存在する名前空間に対応する、空の場合もある文字列の ValueSeq である。引数はシンボルである。 結果は、シンボルが存在する名前空間に対応する、空の場合もある文字列の ValueSeqである。
xml-ph-0000@deepl.internalextern(C++, "ns") struct Foo {} struct Bar {} extern(C++, __traits(getCppNamespaces, Foo)) struct Baz {} static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz)); void main() { static assert(__traits(getCppNamespaces, Foo)[0] == "ns"); static assert(!__traits(getCppNamespaces, Bar).length); static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz)); }
getVisibility
引数はシンボルである。 結果は、可視性レベルを示す文字列である:「public」、「private」、「protected」、「export」、または「package」。
import std.stdio; class D { export void foo() { } public int bar; } void main() { D d = new D(); auto i = __traits(getVisibility, d.foo); writeln(i); auto j = __traits(getVisibility, d.bar); writeln(j); }
export public
getProtection
getVisibilityの互換性のある別名。
getTargetInfo
引数として文字列キーを受け取る。 結果は、要求されたターゲット情報を記述する式となる。
version (CppRuntime_Microsoft) static assert(__traits(getTargetInfo, "cppRuntimeLibrary") == "libcmt");
キーは処理系定義であり、特殊なターゲットに関する関連データも許可される。 常に利用可能な信頼性の高いサブセットが存在する。
- "cppRuntimeLibrary" - このツールチェーンのC++ランタイムライブラリ親和性
- "cppStd" - extern(C++) コードでサポートされている C++ 標準のバージョンは、C++ コンパイラの__cplusplus マクロと同等である
- "floatAbi" - 浮動小数点ABI。"hard" 、"soft" 、または"softfp"
- "objectFormat" - ターゲットオブジェクトフォーマット
getUnitTests
引数は1つで、集約(例えば、構造体/クラス/モジュール)のシンボルを指定する。 結果は、その集約のすべてのユニットテスト関数のシンボルシーケンスとなる。 返される関数は通常のネストされた静的関数と同様であり、 CTFEは動作し、 UDAはアクセス可能である。
注釈:
コンパイラには"-unittest"フラグを渡す必要がある。フラグが 渡されない場合、__traits(getUnitTests) は常に空のシーケンスを返す 。
module foo; import core.runtime; import std.stdio; struct name { string name; } class Foo { unittest { writeln("foo.Foo.unittest"); } } @name("foo") unittest { writeln("foo.unittest"); } template Tuple (T...) { alias Tuple = T; } shared static this() { // デフォルトのユニット・テスト・ランナーをオーバーライドして、何もしないようにする。 // その後、"main"が呼び出される。 Runtime.moduleUnitTester = { return true; }; } void main() { writeln("start main"); alias tests = Tuple!(__traits(getUnitTests, foo)); static assert(tests.length == 1); alias attributes = Tuple!(__traits(getAttributes, tests[0])); static assert(attributes.length == 1); foreach (test; tests) test(); foreach (test; __traits(getUnitTests, Foo)) test(); }
デフォルトでは、上記は以下のように表示される。
start main foo.unittest foo.Foo.unittest
parent
シンボルとして評価される単一の引数を取る。 結果は、その親であるシンボルとなる。
child
2つの引数を取る。 最初の引数はシンボルまたは式でなければならない。 2番目の引数はシンボルで、例えば、最初の引数のメンバへのエイリアスなどである 。 結果は、2番目の引数を、this コンテキストを最初の引数の値に設定して解釈したものである。
import std.stdio; struct A { int i; int foo(int j) { return i * j; } T bar(T)(T t) { return i + t; } } alias Ai = A.i; alias Abar = A.bar!int; void main() { A a; __traits(child, a, Ai) = 3; writeln(a.i); writeln(__traits(child, a, A.foo)(2)); writeln(__traits(child, a, Abar)(5)); }
3 6 8
allMembers
単一の引数を取り、モジュール、構造体、共用体、クラス、インターフェイス、列挙型、または テンプレートのインスタンス化のいずれかに評価されなければならない。
文字列リテラルのシーケンスが返され、それぞれは、 その引数のメンバ名に、 (引数がクラスである場合)そのベースクラスのすべてのメンバを結合したものとなる。 同じ名前は繰り返されない。 組み込みプロパティは含まれない。import std.stdio; class D { this() { } ~this() { } void foo() { } int foo(int) { return 0; } } void main() { auto b = [ __traits(allMembers, D) ]; writeln(b); // ["__ctor", "__dtor", "foo", "toString", "toHash", "opCmp", "opEquals", // "Monitor", "factory"] }
結果に表示される文字列の順序は 定義されていない。
derivedMembers
単一の引数を取り、型または型式の式として評価される必要がある。 文字列リテラルのシーケンスが返され、それぞれが その型のメンバーの名前となる。 名前は重複しない。 ベースクラスのメンバー名は含まれない。 組み込みプロパティは含まれない。
import std.stdio; class D { this() { } ~this() { } void foo() { } int foo(int) { return 0; } } void main() { auto a = [__traits(derivedMembers, D)]; writeln(a); // ["__ctor", "__dtor", "foo"] }
結果に表示される文字列の順序は 定義されていない。
isSame
2つの引数を比較し、bool に評価する。
2つの引数が同じシンボルである場合、結果はtrue となる (エイリアスが解決された場合)。
struct S { } int foo(); int bar(); static assert(__traits(isSame, foo, foo)); static assert(!__traits(isSame, foo, bar)); static assert(!__traits(isSame, foo, S)); static assert(__traits(isSame, S, S)); static assert(!__traits(isSame, object, S)); static assert(__traits(isSame, object, object)); alias daz = foo; static assert(__traits(isSame, foo, daz));
結果は、2つの引数が 同じ値に評価されるリテラルまたは列挙型で構成される式である場合、true となる。
enum e = 3; static assert(__traits(isSame, (e), 3)); static assert(__traits(isSame, 5, 2 + e));
2つの引数がどちらも ラムダ関数(またはラムダ関数のエイリアス )である場合、それらは等価であるかどうかが比較される。 比較が正しく計算されるためには、以下の条件が 両方のラムダ関数に当てはまる必要がある。
- ラムダ関数の引数には、明示的な引数型としてテンプレート化されたものを使用してはならない。 その他の引数型(基本型、ユーザー定義型、テンプレート型)はサポートされている。
- ラムダ関数の本体には、単一の式(return文は含まない)を含める必要があり、 その式には数値、明示的な定数、列挙型値、関数引数、関数呼び出しのみを含めることができる。 式にローカル変数やreturn文が含まれる場合、その関数は比較できないとみなされる。
これらの制約が満たされない場合、関数は比較できないと見なされ、 結果はfalse となる。
static assert(__traits(isSame, (a, b) => a + b, (c, d) => c + d)); static assert(__traits(isSame, a => ++a, b => ++b)); static assert(!__traits(isSame, (int a, int b) => a + b, (a, b) => a + b)); static assert(__traits(isSame, (a, b) => a + b + 10, (c, d) => c + d + 10));
int f() { return 2; } void test(alias pred)() { // mainのf()は、トップレベルのf()とは異なる関数である static assert(!__traits(isSame, (int a) => a + f(), pred)); } void main() { // ローカル変数にアクセスするラムダは、比較できないとみなされる int b; static assert(!__traits(isSame, a => a + b, a => a + b)); // 他の関数を呼び出すラムダは比較可能である int f() { return 3;} static assert(__traits(isSame, a => a + f(), a => a + f())); test!((int a) => a + f())(); }
class A { int a; this(int a) { this.a = a; } } class B { int a; this(int a) { this.a = a; } } static assert(__traits(isSame, (A a) => ++a.a, (A b) => ++b.a)); // 異なるデータ型を持つラムダは比較できないとみなされる、 // メモリレイアウトが同じであっても static assert(!__traits(isSame, (A a) => ++a.a, (B a) => ++a.a));
2つの引数がタプルである場合、結果はtrue となる。 2つのタプルが展開後に同じ長さであり、 n番目の引数の各ペアが事前に指定された制約を満たしている場合。
import std.meta; struct S { } // __traits(isSame,0,0) && __traits(isSame,1,1)のような static assert(__traits(isSame, AliasSeq!(0,1), AliasSeq!(0,1))); // __traits(isSame,S,std.meta) && __traits(isSame,1,1)のような static assert(!__traits(isSame, AliasSeq!(S,1), AliasSeq!(std.meta,1))); // 配列の長さが異なる static assert(!__traits(isSame, AliasSeq!(1), AliasSeq!(1,2)));
compiles
すべての引数がコンパイル可能(意味的に正しい)である場合、ブール値true を返す。 引数はシンボル、型、または構文的に正しい式であることができる。 引数は文または宣言であってはならない。代わりに、 これらは 関数リテラル式でラップすることができる。
引数がなければ、結果はfalse となる。
static assert(!__traits(compiles)); static assert(__traits(compiles, 1 + 1)); // 式 static assert(__traits(compiles, typeof(1))); // 型 static assert(__traits(compiles, object)); // 記号 static assert(__traits(compiles, 1, 2, 3, int, long)); static assert(!__traits(compiles, 3[1])); // セマンティックエラー static assert(!__traits(compiles, 1, 2, 3, int, long, 3[1])); enum n = 3; // 宣言/ステートメントを関数リテラルで囲む static assert(__traits(compiles, { int[n] arr; })); static assert(!__traits(compiles, { foreach (e; n) {} })); struct S { static int s1; int s2; } static assert(__traits(compiles, S.s1 = 0)); static assert(!__traits(compiles, S.s2 = 0)); static assert(!__traits(compiles, S.s3)); int foo(); static assert(__traits(compiles, foo)); static assert(__traits(compiles, foo + 1)); // オプションの括弧でfooを呼び出す static assert(!__traits(compiles, &foo + 1));
これは次のような場合に役立つ。
- 汎用コード内で( static assert汎用コード内で、 時として理解が難しいコンパイラのエラーメッセージよりも
- テンプレートの部分的な特殊化よりも細かい粒度の特殊化を行う。
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.109.1
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku