Traits are extensions to the language to enable programs, at compile time, to get at information internal to the compiler. This is also known as compile time reflection. It is done as a special, easily extended syntax (similar to Pragmas) so that new capabilities can be added as required.
TraitsExpression:__traits(TraitsKeyword,TraitsArguments)TraitsKeyword:isAbstractClassisArithmeticisAssociativeArrayisFinalClassisPODisNestedisFutureisDeprecatedisFloatingisIntegralisScalarisStaticArrayisUnsignedisDisabledisVirtualFunctionisVirtualMethodisAbstractFunctionisFinalFunctionisStaticFunctionisOverrideFunctionisTemplateisRefisOutisLazyisReturnOnStackisCopyableisZeroInitisModuleisPackageisCOMClasshasMemberhasCopyConstructorhasMoveConstructorhasPostblitidentifierfullyQualifiedNamegetAliasThisgetAttributesgetBitfieldOffsetgetBitfieldWidthgetFunctionAttributesgetFunctionVariadicStylegetLinkagegetLocationgetMembergetOverloadsgetParameterStorageClassesgetPointerBitmapgetCppNamespacesgetVisibilitygetProtectiongetTargetInfogetVirtualFunctionsgetVirtualMethodsgetUnitTestsparentchildclassInstanceSizeclassInstanceAlignmentgetVirtualIndexallMembersderivedMembersisSamecompilestoTypeinitSymbolparametersfullyQualifiedNameTraitsArguments:TraitsArgumentTraitsArgument,TraitsArgumentsTraitsArgument:AssignExpressionType
If the arguments are all either a type that is anArithmeticType, or an expression that is typed as such, thentrue is returned. Otherwise,false is returned. If there are no arguments,false is returned.
Arithmetic types are integral types and floating point types.
import std.stdio;void main(){int i;staticassert(__traits(isArithmetic,int));staticassert(__traits(isArithmetic, i, i+1,int));staticassert(!__traits(isArithmetic));staticassert(!__traits(isArithmetic,int*));}
If the arguments are all either types that are floating point types, or expressions that are typed as floating point types, thentrue is returned. Otherwise,false is returned. If there are no arguments,false is returned.
The floating point types are:float,double,real,ifloat,idouble,ireal,cfloat,cdouble,creal, vectors of floating point types, and enums with a floating point base type.
import core.simd : float4;enum E :float { a, b }staticassert(__traits(isFloating,float));staticassert(__traits(isFloating, E));staticassert(__traits(isFloating, float4));staticassert(!__traits(isFloating,float[4]));
If the arguments are all either types that are integral types, or expressions that are typed as integral types, thentrue is returned. Otherwise,false is returned. If there are no arguments,false is returned.
The integral types are:byte,ubyte,short,ushort,int,uint,long,ulong,cent,ucent,bool,char,wchar,dchar, vectors of integral types, and enums with an integral base type.
import core.simd : int4;enum E { a, b }staticassert(__traits(isIntegral,bool));staticassert(__traits(isIntegral,char));staticassert(__traits(isIntegral,int));staticassert(__traits(isIntegral, E));staticassert(__traits(isIntegral, int4));staticassert(!__traits(isIntegral,float));staticassert(!__traits(isIntegral,int[4]));staticassert(!__traits(isIntegral,void*));
If the arguments are all either types that are scalar types, or expressions that are typed as scalar types, thentrue is returned. Otherwise,false is returned. If there are no arguments,false is returned.
Scalar types are integral types, floating point types, pointer types, vectors of scalar types, and enums with a scalar base type.
import core.simd : int4, void16;enum E { a, b }staticassert(__traits(isScalar,bool));staticassert(__traits(isScalar,char));staticassert(__traits(isScalar,int));staticassert(__traits(isScalar,float));staticassert(__traits(isScalar, E));staticassert(__traits(isScalar, int4));staticassert(__traits(isScalar,void*));// Includes pointers!staticassert(!__traits(isScalar,int[4]));staticassert(!__traits(isScalar, void16));staticassert(!__traits(isScalar,void));staticassert(!__traits(isScalar,typeof(null)));staticassert(!__traits(isScalar, Object));
If the arguments are all either types that are unsigned types, or expressions that are typed as unsigned types, thentrue is returned. Otherwise,false is returned. If there are no arguments,false is returned.
The unsigned types are:ubyte,ushort,uint,ulong,ucent,bool,char,wchar,dchar, vectors of unsigned types, and enums with an unsigned base type.
import core.simd : uint4;enum SignedEnum { a, b }enum UnsignedEnum :uint { a, b }staticassert(__traits(isUnsigned,bool));staticassert(__traits(isUnsigned,char));staticassert(__traits(isUnsigned,uint));staticassert(__traits(isUnsigned, UnsignedEnum));staticassert(__traits(isUnsigned, uint4));staticassert(!__traits(isUnsigned,int));staticassert(!__traits(isUnsigned,float));staticassert(!__traits(isUnsigned, SignedEnum));staticassert(!__traits(isUnsigned,uint[4]));staticassert(!__traits(isUnsigned,void*));
Works likeisArithmetic, except it's for static array types.
import core.simd : int4;enum E :int[4] { a = [1, 2, 3, 4] }static array = [1, 2, 3];// Not a static array: the type is inferred as int[] not int[3].staticassert(__traits(isStaticArray,void[0]));staticassert(__traits(isStaticArray, E));staticassert(!__traits(isStaticArray, int4));staticassert(!__traits(isStaticArray, array));
Works likeisArithmetic, except it's for associative array types.
If the arguments are all either types that are abstract classes, or expressions that are typed as abstract classes, thentrue is returned. Otherwise,false is returned. If there are no arguments,false is returned.
import std.stdio;abstractclass C {int foo(); }void main(){ C c; writeln(__traits(isAbstractClass, C)); writeln(__traits(isAbstractClass, c, C)); writeln(__traits(isAbstractClass)); writeln(__traits(isAbstractClass,int*));}
truetruefalsefalse
Works likeisAbstractClass, except it's for final classes.
Takes one argument. If that argument is a symbol that refers to aclass declaration which is aCOM class thentrue is returned, otherwisefalse.
Takes one argument. If that argument is a copyable type thentrue is returned,otherwisefalse.
struct S{}staticassert(__traits(isCopyable, S));struct T{ @disablethis(this);// disable copy construction}staticassert(!__traits(isCopyable, T));
Takes one argument, which must be a type. It returnstrue if the type is aPOD type, otherwisefalse.
Takes a single argument, which must evaluate to an expression of typestring. The contents of the string must correspond to themangled contents of a type that has been seen by the implementation.
Only D mangling is supported. Other manglings, such as C++ mangling, are not.
The value returned is a type.
template Type(T) {alias Type = T; }Type!(__traits(toType,"i")) j = 3;// j is declared as type `int`staticassert(is(Type!(__traits(toType, (int*).mangleof)) ==int*));__traits(toType,"i") x = 4;// x is also declared as type `int`
Takes one argument which must be a type. If the type'sdefault initializer is all zero bits thentrue is returned, otherwisefalse.
struct S1 {int x; }struct S2 {int x = -1; }staticassert(__traits(isZeroInit, S1));staticassert(!__traits(isZeroInit, S2));void test(){int x = 3;staticassert(__traits(isZeroInit,typeof(x)));}// `isZeroInit` will always return true for a class C// because `C.init` is null reference.class C {int x = -1; }staticassert(__traits(isZeroInit, C));// For initializing arrays of element type `void`.staticassert(__traits(isZeroInit,void));
The argument is a type. If it is a struct with a copy constructor, returnstrue. Otherwise, returnfalse. A copy constructor is distinct from a move constructor or a postblit.
import std.stdio;struct S { }class C { }struct P{this(ref P rhs) {}// copy constructor}struct B{this(this) {}// postblit}void main(){ writeln(__traits(hasCopyConstructor, S));// false writeln(__traits(hasCopyConstructor, C));// false writeln(__traits(hasCopyConstructor, P));// true writeln(__traits(hasCopyConstructor, B));// false, this is a postblit}
The argument is a type. If it is a struct with a move constructor, returnstrue. Otherwise, returnfalse. A move constructor is distinct from a copy constructor or a postblit.
import std.stdio;struct S{this(S rhs) {}// move constructor}class C { }struct P{this(ref P rhs) {}// copy constructor}struct B{this(this) {}// postblit}void main(){ writeln(__traits(hasMoveConstructor, S));// true writeln(__traits(hasMoveConstructor, C));// false writeln(__traits(hasMoveConstructor, P));// false writeln(__traits(hasMoveConstructor, B));// false, this is a postblit}
The argument is a type. If it is a struct with a postblit, returnstrue. Otherwise, returnfalse. Note a postblit is distinct from a copy constructor.
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, this is a copy ctor writeln(__traits(hasPostblit, B));// true}
Takes one argument, a type. If the type hasalias this declarations, returns aValueSeq of the names (asstrings) of the members used in those declarations. Otherwise returns an empty sequence.
alias AliasSeq(T...) = T;struct S1{ string var;alias varthis;}staticassert(__traits(getAliasThis, S1) == AliasSeq!("var"));staticassert(__traits(getAliasThis,int).length == 0);pragma(msg,__traits(getAliasThis, S1));pragma(msg,__traits(getAliasThis,int));
AliasSeq!("var")AliasSeq!()The argument is a type. The result is an array ofsize_t describing the memory used by an instance of the given type.
The first element of the array is the size of the type (for classes it is theclassInstanceSize).
The following elements describe the locations of GC managed pointers within the memory occupied by an instance of the type. For type T, there areT.sizeof / size_t.sizeof possible pointers represented by the bits of the array values.
This array can be used by a precise GC to avoid false pointers.
void main(){staticclass C {// implicit virtual function table pointer not marked// implicit monitor field not marked, usually managed manually C next; size_t sz;void* p;voidfunction () fn;// not a GC managed pointer }staticstruct S { size_t val1;void* p; C c;byte[] arr;// { length, ptr }voiddelegate () dg;// { context, func } }staticassert (__traits(getPointerBitmap, C) == [6*size_t.sizeof, 0b010100]);staticassert (__traits(getPointerBitmap, S) == [7*size_t.sizeof, 0b0110110]);}
The same asgetVirtualMethods, except that final functions that do not override anything are included.
The first argument is a class type or an expression of class type. The second argument is a string that matches the name of one of the functions of that class. The result is a symbol sequence of the virtual overloads of that function. It does not include final functions that do not override anything.
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
Takes a single argument, which must evaluate to either a class type or an expression of class type. The result is of typesize_t, and the value is the number of bytes in the runtime instance of the class type. It is based on the static type of a class, not the polymorphic type.
Takes a single argument, which must evaluate to either a class type or an expression of class type. The result is of typesize_t, and the value is the alignment of a runtime instance of the class type. It is based on the static type of a class, not the polymorphic type.
Takes a single argument, which must evaluate to aclass,struct orunion type. Returns aconst(void)[] that holds the initial state of any instance of the supplied type. The slice is constructed for any typeT as follows:
This trait matches the behaviour ofTypeInfo.initializer() but can also be used whenTypeInfo is not available.
This trait is not available duringCTFE because the actual address of the initializer symbol will be set by the linker and hence is not available at compile time.
import core.stdc.stdlib;class C{int i = 4;}/// Initializes a malloc'ed instance of `C`void main(){constvoid[] initSym =__traits(initSymbol, C);void* ptr = malloc(initSym.length);scope (exit) free(ptr);// Note: allocated memory will only be written to through `c`, so cast is safe ptr[0..initSym.length] =cast(void[]) initSym[]; C c =cast(C) ptr;assert(c.i == 4);}
Takes one argument and returnstrue if it's a function declaration marked with@disable.
struct Foo{ @disablevoid foo();void bar(){}}staticassert(__traits(isDisabled, Foo.foo));staticassert(!__traits(isDisabled, Foo.bar));
For any other declaration, even if@disable is a syntactically valid attribute,false is returned because the annotation has no effect.
@disablestruct Bar{}staticassert(!__traits(isDisabled, Bar));
Takes a single argument which must evaluate to a function. The result is aptrdiff_t containing the index of that function within the vtable of the parent type. If the function passed in is final and does not override a virtual function,-1 is returned instead.
The same asisVirtualMethod, except that final functions that don't override anything return true.
Takes one argument. If that argument is a virtual function,true is returned, otherwisefalse. Final functions that don't override anything return 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}
Takes one argument. If that argument is an abstract function,true is returned, otherwisefalse.
import std.stdio;struct S{void bar() { }}class C{void bar() { }}class AC{abstractvoid foo();}void main(){ writeln(__traits(isAbstractFunction, C.bar));// false writeln(__traits(isAbstractFunction, S.bar));// false writeln(__traits(isAbstractFunction, AC.foo));// true}
Takes one argument. If that argument is a final function,true is returned, otherwisefalse.
import std.stdio;struct S{void bar() { }}class C{void bar() { }finalvoid foo();}finalclass 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}
Takes one argument. If that argument is a function marked withoverride,true is returned, otherwisefalse.
import std.stdio;class Base{void foo() { }}class Foo : Base{overridevoid foo() { }void bar() { }}void main(){ writeln(__traits(isOverrideFunction, Base.foo));// false writeln(__traits(isOverrideFunction, Foo.foo));// true writeln(__traits(isOverrideFunction, Foo.bar));// false}
Takes one argument. If that argument is a static function, meaning it has no context pointer,true is returned, otherwisefalse.
struct A{int foo() {return 3; }staticint boo(int a) {return a; }}void main(){assert(__traits(isStaticFunction, A.boo));assert(!__traits(isStaticFunction, A.foo));assert(__traits(isStaticFunction, main));}
Takes one argument which must either be a function symbol, function literal, a delegate, or a function pointer. It returns abool which istrue if the return value of the function is returned on the stack via a pointer to it passed as a hidden extra parameter to the function.
struct S {int[20] a; }int test1();S test2();staticassert(__traits(isReturnOnStack, test1) ==false);staticassert(__traits(isReturnOnStack, test2) ==true);
Takes one argument which must either be a function symbol, or a type that is a function, delegate or a function pointer. It returns a string identifying the kind ofvariadic arguments that are supported.
| result | kind | access | example |
|---|---|---|---|
| "none" | not a variadic function | void foo(); | |
| "argptr" | D style variadic function | _argptr and_arguments | void bar(...) |
| "stdarg" | C style variadic function | core.stdc.stdarg | extern (C) void abc(int, ...) |
| "typesafe" | typesafe variadic function | array on stack | void def(int[] ...) |
import core.stdc.stdarg;void novar() {}extern(C)void cstyle(int, ...) {}extern(C++)void cppstyle(int, ...) {}void dstyle(...) {}void typesafe(int[]...) {}staticassert(__traits(getFunctionVariadicStyle, novar) =="none");staticassert(__traits(getFunctionVariadicStyle, cstyle) =="stdarg");staticassert(__traits(getFunctionVariadicStyle, cppstyle) =="stdarg");staticassert(__traits(getFunctionVariadicStyle, dstyle) =="argptr");staticassert(__traits(getFunctionVariadicStyle, typesafe) =="typesafe");staticassert(__traits(getFunctionVariadicStyle, (int[] a...) {}) =="typesafe");staticassert(__traits(getFunctionVariadicStyle,typeof(cstyle)) =="stdarg");
Takes one argument which must either be a function symbol, function literal, or a function pointer. It returns a stringValueSeq of all the attributes of that functionexcluding any user-defined attributes (UDAs can be retrieved with thegetAttributes trait). If no attributes exist it will return an empty sequence.
Note: The order of the attributes in the returned sequence is implementation-defined and should not be relied upon.A list of currently supported attributes are:
Additionally the following attributes are only valid for non-static member functions:
int sum(int x,int y)purenothrow {return x + y; }pragma(msg,__traits(getFunctionAttributes, sum));struct S{void test()const @system { }}pragma(msg,__traits(getFunctionAttributes, S.test));
AliasSeq!("pure", "nothrow", "@system")AliasSeq!("const", "@system")Note that some attributes can be inferred. For example:
pragma(msg,__traits(getFunctionAttributes, (int x) @trusted {return x * 2; }));
AliasSeq!("pure", "nothrow", "@nogc", "@trusted")Takes one argument. If that argument is a variable/parameter declaration which has theref storage class,true is returned, otherwisefalse.
void foo(refint x,int y){staticassert(__traits(isRef, x));staticassert(!__traits(isRef, y));int i;ref j = i;staticassert(!__traits(isRef, i));staticassert(__traits(isRef, j));}refint get();// get returns by reference, but it's not a ref itselfstaticassert(!__traits(isRef, get));
Takes one argument. If that argument is a declaration which isout orlazy,true is returned, otherwisefalse.
void fooref(refint x){staticassert(__traits(isRef, x));staticassert(!__traits(isOut, x));staticassert(!__traits(isLazy, x));}void fooout(outint x){staticassert(!__traits(isRef, x));staticassert(__traits(isOut, x));staticassert(!__traits(isLazy, x));}void foolazy(lazyint x){staticassert(!__traits(isRef, x));staticassert(!__traits(isOut, x));staticassert(__traits(isLazy, x));}
Takes two arguments. The first must either be a function symbol, a function call, or a type that is a function, delegate or a function pointer. The second is an integer identifying which parameter, where the first parameter is 0. It returns aValueSeq of strings representing the storage classes of that parameter.
refint foo(returnrefconstint* p,scopeint* a,outint b,lazyint c);staticassert(__traits(getParameterStorageClasses, foo, 0)[0] =="return");staticassert(__traits(getParameterStorageClasses, foo, 0)[1] =="ref");staticassert(__traits(getParameterStorageClasses, foo, 1)[0] =="scope");staticassert(__traits(getParameterStorageClasses, foo, 2)[0] =="out");staticassert(__traits(getParameterStorageClasses,typeof(&foo), 3)[0] =="lazy");int* p, a;int b, c;staticassert(__traits(getParameterStorageClasses, foo(p, a, b, c), 1)[0] =="scope");staticassert(__traits(getParameterStorageClasses, foo(p, a, b, c), 2)[0] =="out");staticassert(__traits(getParameterStorageClasses, foo(p, a, b, c), 3)[0] =="lazy");
May only be used inside a function. Takes no arguments, and returns anlvalue sequence of the enclosing function's parameters.
alias AliasSeq(A...) = A;void f(int n,char c){alias PS =__traits(parameters); PS[0]++;// increment nstaticassert(is(typeof(PS) == AliasSeq!(int,char)));// output parameter namesstaticforeach (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));// equivalent to;//return add(x, y);}
If the function is nested, the parameters returned are those of the inner function, not the outer one.
int nestedExample(int x){// outer function's parametersstaticassert(typeof(__traits(parameters)).length == 1);int add(int x,int y) {// inner function's parametersstaticassert(typeof(__traits(parameters)).length == 2);return x + y; }return add(x, x);}
class C{int opApply(intdelegate(size_t, C) dg) {if (dg(0,this))return 1;return 0; }}void foreachExample(C c,int x){foreach(idx; 0..5) {staticassert(is(typeof(__traits(parameters)) == AliasSeq!(C,int))); }foreach(idx, elem; c) {// __traits(parameters) sees past the delegate passed to opApplystaticassert(is(typeof(__traits(parameters)) == AliasSeq!(C,int))); }}
Gets the fully qualified name of a type or symbol.
module myModule;int i;staticassert(__traits(fullyQualifiedName, i) =="myModule.i");struct MyStruct {}staticassert(__traits(fullyQualifiedName,const MyStruct[]) =="const(myModule.MyStruct[])");
Takes one argument. It returnstrue if the argument is a nested type which internally stores a context pointer, otherwise it returnsfalse. Nested types can beclasses,structs, andfunctions.
Takes one argument. It returnstrue if the argument is a symbol marked with the@__future attribute, otherwisefalse. Currently, only functions and variable declarations have support for the@__future keyword.
Takes one argument. It returnstrue if the argument is a symbol marked with thedeprecated keyword, otherwisefalse.
deprecated("No longer supported")int i;struct A{int foo() {return 1; }deprecated("please use foo")int bar() {return 1; }}staticassert(__traits(isDeprecated, i));staticassert(!__traits(isDeprecated, A.foo));staticassert(__traits(isDeprecated, A.bar));
Takes one argument. If that argument or any of its overloads is a template thentrue is returned, otherwisefalse.
void foo(T)(){}staticassert(__traits(isTemplate, foo));staticassert(!__traits(isTemplate, foo!int()));staticassert(!__traits(isTemplate,"string"));
Takes one argument. If that argument is a symbol that refers to amodule thentrue is returned, otherwisefalse.Package modules are considered to be modules even if they have not been directly imported as modules.
import core.thread;import std.algorithm.sorting;// A regular package (no package.d)staticassert(!__traits(isModule, core));// A package module (has a package.d file)// Note that we haven't imported std.algorithm directly.// (In other words, we don't have an "import std.algorithm;" directive.)staticassert(__traits(isModule, std.algorithm));// A regular modulestaticassert(__traits(isModule, std.algorithm.sorting));
Takes one argument. If that argument is a symbol that refers to apackage thentrue is returned, otherwisefalse.
import std.algorithm.sorting;staticassert(__traits(isPackage, std));staticassert(__traits(isPackage, std.algorithm));staticassert(!__traits(isPackage, std.algorithm.sorting));
The first argument is a type that has members, or is an expression of a type that has members. The second argument is a string. If the string is a valid property of the type,true is returned, otherwisefalse.
import std.stdio;struct S{int m;}void main(){ S s;staticassert(__traits(hasMember, S,"m"));staticassert(__traits(hasMember, s,"m"));staticassert(!__traits(hasMember, S,"y"));staticassert(!__traits(hasMember, S,"write"));// false, but callable like a member via UFCSstaticassert(__traits(hasMember,int,"sizeof"));staticassert(__traits(hasMember, 5,"sizeof"));}
Takes one argument, a symbol. Returns the identifier for that symbol as a string literal.
int var = 123;staticassert(__traits(identifier, var) =="var");
Takes one argument, a symbol. Returns a sequence of all attacheduser-defined attributes. If no UDAs exist it will return an empty sequence.
@(3)int a;@("string", 7)int b;enum Foo;@Fooint c;pragma(msg,__traits(getAttributes, a));pragma(msg,__traits(getAttributes, b));pragma(msg,__traits(getAttributes, c));
AliasSeq!(3)AliasSeq!("string", 7)AliasSeq!((Foo))Takes one argument, a qualified symbol that resolves to a field in a struct or class. The result is auint.
If the field is a bitfield, it returns the bit number of the least significant bit in the field. The rightmost bit is at offset 0, the leftmost bit is at offset 31 (for 32 bit int fields).
If the field is not a bitfield, it returns the number 0.
struct S{int a, b;int :2, c:3;}staticassert(__traits(getBitfieldOffset, S.b) == 0);staticassert(__traits(getBitfieldOffset, S.c) == 2);
Takes one argument, a qualified symbol that resolves to a field in a struct or class. The result is auint.
If the field is a bitfield, it returns the width of the bit field as a number of bits.
If the field is not a bitfield, it returns the number of bits in the type.
struct S{int a, b;int :2, c:3;}staticassert(__traits(getBitfieldWidth, S.b) == 32);staticassert(__traits(getBitfieldWidth, S.c) == 3);
Takes one argument, which is a declaration symbol, or the type of a function, delegate, pointer to function, struct, class, or interface. Returns a string representing theLinkageAttribute of the declaration. The string is one of:
extern (C)int fooc();alias aliasc = fooc;staticassert(__traits(getLinkage, fooc) =="C");staticassert(__traits(getLinkage, aliasc) =="C");extern (C++)struct FooCPPStruct {}extern (C++)class FooCPPClass {}extern (C++)interface FooCPPInterface {}staticassert(__traits(getLinkage, FooCPPStruct) =="C++");staticassert(__traits(getLinkage, FooCPPClass) =="C++");staticassert(__traits(getLinkage, FooCPPInterface) =="C++");
Takes one argument which is a symbol. To disambiguate between overloads, pass the result ofgetOverloads with the desired index, togetLocation. Returns aValueSeq of a string and twoints which correspond to the filename, line number and column number where the argument was declared.
Takes two arguments, the second must be a string. The result is an expression formed from the first argument, followed by a ‘.’, followed by the second argument as an identifier.
import std.stdio;struct S{int mx;staticint my;}void main(){ S s;__traits(getMember, s,"mx") = 1;// same as s.mx=1; writeln(__traits(getMember, s,"m" ~"x"));// 1// __traits(getMember, S, "mx") = 1; // error, no this for S.mx__traits(getMember, S,"my") = 2;// ok}
import std.stdio;class D{void foo() { }int foo(int) {return 2; }void bar(T)() {return T.init; }class bar(int n) {}}void main(){ D d =new D();alias fooOverloads =__traits(getOverloads, D,"foo");foreach (o; fooOverloads) writeln(typeid(typeof(o)));// typeof on a symbol sequence gives a type sequenceforeach (T;typeof(fooOverloads)) writeln(typeid(T));// calls d.foo(3)auto i =__traits(getOverloads, d,"foo")[1](3);assert(i == 2);// pass true to include templates// calls std.stdio.writeln(i)__traits(getOverloads, std.stdio,"writeln",true)[0](i);foreach (o;__traits(getOverloads, D,"bar",true)) writeln(o.stringof);}
void function()int function(int)void function()int function(int)2bar(T)()bar(int n)
The argument is a symbol. The result is aValueSeq of strings, possibly empty, that correspond to the namespaces the symbol resides in.
extern(C++,"ns")struct Foo {}struct Bar {}extern(C++,__traits(getCppNamespaces, Foo))struct Baz {}staticassert(__traits(getCppNamespaces, Foo) ==__traits(getCppNamespaces, Baz));void main(){staticassert(__traits(getCppNamespaces, Foo)[0] =="ns");staticassert(!__traits(getCppNamespaces, Bar).length);staticassert(__traits(getCppNamespaces, Foo) ==__traits(getCppNamespaces, Baz));}
The argument is a symbol. The result is a string giving its visibility level: "public", "private", "protected", "export", or "package".
import std.stdio;class D{exportvoid foo() { }publicint bar;}void main(){ D d =new D();auto i =__traits(getVisibility, d.foo); writeln(i);auto j =__traits(getVisibility, d.bar); writeln(j);}
exportpublic
Takes one argument, which can be a type, expression, or symbol, and returns a string.
module plugh;import std.stdio;void main(){auto s =__traits(fullyQualifiedName,int); writeln(s);auto t =__traits(fullyQualifiedName, 1.0); writeln(t);auto u =__traits(fullyQualifiedName, t); writeln(u);}
intdoubleplugh.main.t
A backward-compatible alias forgetVisibility.
Receives a string key as argument. The result is an expression describing the requested target information.
version (CppRuntime_Microsoft)staticassert(__traits(getTargetInfo,"cppRuntimeLibrary") =="libcmt");
Keys are implementation defined, allowing relevant data for exotic targets. A reliable subset exists which are always available:
Takes one argument, a symbol of an aggregate (e.g. struct/class/module). The result is a symbol sequence of all the unit test functions of that aggregate. The functions returned are like normal nested static functions,CTFE will work andUDAs will be accessible.
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;}sharedstaticthis(){// Override the default unit test runner to do nothing. After that, "main" will// be called. Runtime.moduleUnitTester = {returntrue; };}void main(){ writeln("start main");alias tests = Tuple!(__traits(getUnitTests, foo));staticassert(tests.length == 1);alias attributes = Tuple!(__traits(getAttributes, tests[0]));staticassert(attributes.length == 1);foreach (test; tests) test();foreach (test;__traits(getUnitTests, Foo)) test();}
By default, the above will print:
start mainfoo.unittestfoo.Foo.unittest
Takes a single argument which must evaluate to a symbol. The result is the symbol that is the parent of it.
Takes two arguments. The first must be a symbol or expression. The second is a symbol, such as an alias to a member of the first argument. The result is the second argument interpreted with itsthis context set to the value of the first argument.
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));}
368
Takes a single argument, which must evaluate to either a module, a struct, a union, a class, an interface, an enum, or a template instantiation.
A sequence of string literals is returned, each of which is the name of a member of that argument combined with all of the members of its base classes (if the argument is a class). No name is repeated. Builtin properties are not included.
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"]}
The order in which the strings appear in the result is not defined.
Takes a single argument, which must evaluate to either a type or an expression of type. A sequence of string literals is returned, each of which is the name of a member of that type. No name is repeated. Base class member names are not included. Builtin properties are not included.
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"]}
The order in which the strings appear in the result is not defined.
Compares two arguments and evaluates tobool.
The result istrue if the two arguments are the same symbol (once aliases are resolved).
struct S { }int foo();int bar();staticassert(__traits(isSame, foo, foo));staticassert(!__traits(isSame, foo, bar));staticassert(!__traits(isSame, foo, S));staticassert(__traits(isSame, S, S));staticassert(!__traits(isSame, object, S));staticassert(__traits(isSame, object, object));alias daz = foo;staticassert(__traits(isSame, foo, daz));
isSame matches against non-instantiated templates.
struct Foo(T){ T x;}struct Bar(T){ T x;}struct Point(T){ T x; T y;}enum isFooOrBar(alias FB) =__traits(isSame, FB, Foo) ||__traits(isSame, FB, Bar);staticassert(isFooOrBar!(Foo));staticassert(isFooOrBar!(Bar));staticassert(!isFooOrBar!(Point));
The result istrue if the two arguments are expressions made up of literals or enums that evaluate to the same value.
enum e = 3;staticassert(__traits(isSame, (e), 3));staticassert(__traits(isSame, 5, 2 + e));
If the two arguments are bothlambda functions (or aliases to lambda functions), then they are compared for equality. For the comparison to be computed correctly, the following conditions must be met for both lambda functions:
If these constraints aren't fulfilled, the function is considered incomparable and the result isfalse.
staticassert(__traits(isSame, (a, b) => a + b, (c, d) => c + d));staticassert(__traits(isSame, a => ++a, b => ++b));staticassert(!__traits(isSame, (int a,int b) => a + b, (a, b) => a + b));staticassert(__traits(isSame, (a, b) => a + b + 10, (c, d) => c + d + 10));
int f() {return 2; }void test(alias pred)(){// f() from main is a different function from top-level f()staticassert(!__traits(isSame, (int a) => a + f(), pred));}void main(){// lambdas accessing local variables are considered incomparableint b;staticassert(!__traits(isSame, a => a + b, a => a + b));// lambdas calling other functions are comparableint f() {return 3;}staticassert(__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; }}staticassert(__traits(isSame, (A a) => ++a.a, (A b) => ++b.a));// lambdas with different data types are considered incomparable,// even if the memory layout is the samestaticassert(!__traits(isSame, (A a) => ++a.a, (B a) => ++a.a));
If the two arguments are tuples then the result istrue if the two tuples, after expansion, have the same length and if each pair of nth argument respects the constraints previously specified.
import std.meta;struct S { }// like __traits(isSame,0,0) && __traits(isSame,1,1)staticassert(__traits(isSame, AliasSeq!(0,1), AliasSeq!(0,1)));// like __traits(isSame,S,std.meta) && __traits(isSame,1,1)staticassert(!__traits(isSame, AliasSeq!(S,1), AliasSeq!(std.meta,1)));// the length of the sequences is differentstaticassert(!__traits(isSame, AliasSeq!(1), AliasSeq!(1,2)));
Returns a booltrue if all of the arguments compile (are semantically correct). The arguments can be symbols, types, or expressions that are syntactically correct. The arguments cannot be statements or declarations - instead these can be wrapped in a function literal expression.
If there are no arguments, the result isfalse.
staticassert(!__traits(compiles));staticassert(__traits(compiles, 1 + 1));// expressionstaticassert(__traits(compiles,typeof(1)));// typestaticassert(__traits(compiles, object));// symbolstaticassert(__traits(compiles, 1, 2, 3,int,long));staticassert(!__traits(compiles, 3[1]));// semantic errorstaticassert(!__traits(compiles, 1, 2, 3,int,long, 3[1]));enum n = 3;// wrap a declaration/statement in a function literalstaticassert(__traits(compiles, {int[n] arr; }));staticassert(!__traits(compiles, {foreach (e; n) {} }));struct S{staticint s1;int s2;}staticassert(__traits(compiles, S.s1 = 0));staticassert(!__traits(compiles, S.s2 = 0));staticassert(!__traits(compiles, S.s3));int foo();staticassert(__traits(compiles, foo));staticassert(__traits(compiles, foo + 1));// call foo with optional parensstaticassert(!__traits(compiles, &foo + 1));
This is useful for: