@safe unittest { import std.traits; static assert(is(InoutOf!(int) == inout int)); static assert(is(InoutOf!(inout int) == inout int)); static assert(is(InoutOf!(const int) == inout const int)); static assert(is(InoutOf!(shared int) == inout shared int)); } @safe unittest { import std.traits; static assert(is(ConstOf!(int) == const int)); static assert(is(ConstOf!(const int) == const int)); static assert(is(ConstOf!(inout int) == const inout int)); static assert(is(ConstOf!(shared int) == const shared int)); } @safe unittest { import std.traits; static assert(is(SharedOf!(int) == shared int)); static assert(is(SharedOf!(shared int) == shared int)); static assert(is(SharedOf!(inout int) == shared inout int)); static assert(is(SharedOf!(immutable int) == shared immutable int)); } @safe unittest { import std.traits; static assert(is(SharedInoutOf!(int) == shared inout int)); static assert(is(SharedInoutOf!(int) == inout shared int)); static assert(is(SharedInoutOf!(const int) == shared inout const int)); static assert(is(SharedInoutOf!(immutable int) == shared inout immutable int)); } @safe unittest { import std.traits; static assert(is(SharedConstOf!(int) == shared const int)); static assert(is(SharedConstOf!(int) == const shared int)); static assert(is(SharedConstOf!(inout int) == shared inout const int)); // immutable variables are implicitly shared and const static assert(is(SharedConstOf!(immutable int) == immutable int)); } @safe unittest { import std.traits; static assert(is(SharedConstInoutOf!(int) == shared const inout int)); static assert(is(SharedConstInoutOf!(int) == const shared inout int)); static assert(is(SharedConstInoutOf!(inout int) == shared inout const int)); // immutable variables are implicitly shared and const static assert(is(SharedConstInoutOf!(immutable int) == immutable int)); } @safe unittest { import std.traits; static assert(is(ImmutableOf!(int) == immutable int)); static assert(is(ImmutableOf!(const int) == immutable int)); static assert(is(ImmutableOf!(inout int) == immutable int)); static assert(is(ImmutableOf!(shared int) == immutable int)); } @safe unittest { import std.traits; static assert(__traits(isSame, QualifierOf!(shared const inout int), SharedConstInoutOf)); static assert(__traits(isSame, QualifierOf!(immutable int), ImmutableOf)); static assert(__traits(isSame, QualifierOf!(shared int), SharedOf)); static assert(__traits(isSame, QualifierOf!(shared inout int), SharedInoutOf)); import std.meta : Alias; static assert(__traits(isSame, QualifierOf!(int), Alias)); } @safe unittest { import std.traits; static assert(packageName!packageName == "std"); } @safe unittest { import std.traits; static assert(packageName!moduleName == "std"); } @safe unittest { import std.traits; static assert(moduleName!moduleName == "std.traits"); } @safe unittest { import std.traits; static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName"); } @safe unittest { import std.traits; int foo(); ReturnType!foo x; // x is declared as int } @safe unittest { import std.traits; int foo(int, long); void bar(Parameters!foo); // declares void bar(int, long); void abc(Parameters!foo[1]); // declares void abc(long); } @safe unittest { import std.traits; void foo(){} static assert(arity!foo == 0); void bar(uint){} static assert(arity!bar == 1); void variadicFoo(uint...){} static assert(!__traits(compiles, arity!variadicFoo)); } @safe unittest { import std.traits; alias STC = ParameterStorageClass; // shorten the enum name void func(ref int ctx, out real result, in real param, void* ptr) { } alias pstc = ParameterStorageClassTuple!func; static assert(pstc.length == 4); // number of parameters static assert(pstc[0] == STC.ref_); static assert(pstc[1] == STC.out_); version (none) { // TODO: When the DMD PR (dlang/dmd#11474) gets merged, // remove the versioning and the second test static assert(pstc[2] == STC.in_); // This is the current behavior, before `in` is fixed to not be an alias static assert(pstc[2] == STC.scope_); } static assert(pstc[3] == STC.none); } @safe unittest { import std.traits; static void func(ref int ctx, out real result); enum param1 = extractParameterStorageClassFlags!( __traits(getParameterStorageClasses, func, 0) ); static assert(param1 == ParameterStorageClass.ref_); enum param2 = extractParameterStorageClassFlags!( __traits(getParameterStorageClasses, func, 1) ); static assert(param2 == ParameterStorageClass.out_); enum param3 = extractParameterStorageClassFlags!( __traits(getParameterStorageClasses, func, 0), __traits(getParameterStorageClasses, func, 1) ); static assert(param3 == (ParameterStorageClass.ref_ | ParameterStorageClass.out_)); } @safe unittest { import std.traits; int foo(int num, string name, int); static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]); } @safe unittest { import std.traits; int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0); static assert(is(ParameterDefaults!foo[0] == void)); static assert( ParameterDefaults!foo[1] == "hello"); static assert( ParameterDefaults!foo[2] == [1,2,3]); static assert( ParameterDefaults!foo[3] == 0); } @safe unittest { import std.traits; alias FA = FunctionAttribute; // shorten the enum name real func(real x) pure nothrow @safe { return x; } static assert(functionAttributes!func & FA.pure_); static assert(functionAttributes!func & FA.safe); static assert(!(functionAttributes!func & FA.trusted)); // not @trusted } @safe unittest { import std.traits; real func(real x) pure nothrow @safe; static assert(hasFunctionAttributes!(func, "@safe", "pure")); static assert(!hasFunctionAttributes!(func, "@trusted")); // for templates attributes are automatically inferred bool myFunc(T)(T b) { return !b; } static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow")); static assert(!hasFunctionAttributes!(myFunc!bool, "shared")); } @safe unittest { import std.traits; @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;} static assert( isSafe!add); static assert( isSafe!sub); static assert(!isSafe!mul); } @safe unittest { import std.traits; @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;} static assert(!isUnsafe!add); static assert(!isUnsafe!sub); static assert( isUnsafe!mul); } @safe unittest { import std.traits; extern(D) void Dfunc() {} extern(C) void Cfunc() {} static assert(functionLinkage!Dfunc == "D"); static assert(functionLinkage!Cfunc == "C"); string a = functionLinkage!Dfunc; assert(a == "D"); auto fp = &Cfunc; string b = functionLinkage!fp; assert(b == "C"); } @safe unittest { import std.traits; void func() {} static assert(variadicFunctionStyle!func == Variadic.no); extern(C) int printf(const char*, ...); static assert(variadicFunctionStyle!printf == Variadic.c); } @safe unittest { import std.traits; class C { int value() @property => 0; static string opCall() => "hi"; } static assert(is( typeof(C.value) == int )); static assert(is( FunctionTypeOf!(C.value) == function )); static assert(is( FunctionTypeOf!C == typeof(C.opCall) )); int function() fp; alias IntFn = int(); static assert(is( typeof(fp) == IntFn* )); static assert(is( FunctionTypeOf!fp == IntFn )); } @safe unittest { import std.traits; alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T); auto assumePure(T)(T t) if (isFunctionPointer!T || isDelegate!T) { enum attrs = functionAttributes!T | FunctionAttribute.pure_; return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; } int f() { import core.thread : getpid; return getpid(); } int g() pure @trusted { auto pureF = assumePure(&f); return pureF(); } assert(g() > 0); } @safe unittest { import std.traits; class C { int outer; } static assert(!isInnerClass!C); class Outer1 { class Inner1 { } class Inner2 { int outer; } } static assert(isInnerClass!(Outer1.Inner1)); static assert(!isInnerClass!(Outer1.Inner2)); static class Outer2 { static class Inner { int outer; } } static assert(!isInnerClass!(Outer2.Inner)); } @safe unittest { import std.traits; static struct S { } static assert(!isNested!S); int i; struct NestedStruct { void f() { ++i; } } static assert(isNested!NestedStruct); } @safe unittest { import std.traits; static struct S { } int i; struct NS { void f() { ++i; } } static assert(!hasNested!(S[2])); static assert(hasNested!(NS[2])); } @safe unittest { import std.traits; import std.meta : AliasSeq; struct S { int x; float y; } static assert(is(Fields!S == AliasSeq!(int, float))); } @safe unittest { import std.traits; import std.meta : AliasSeq; struct S { int x; float y; } static assert(FieldNameTuple!S == AliasSeq!("x", "y")); static assert(FieldNameTuple!int == AliasSeq!""); } @safe unittest { import std.traits; struct S1 { int a; float b; } struct S2 { char[] a; union { S1 b; S1 * c; } } alias R = RepresentationTypeTuple!S2; assert(R.length == 4 && is(R[0] == char[]) && is(R[1] == int) && is(R[2] == float) && is(R[3] == S1*)); } @safe unittest { import std.traits; struct S1 { int a; Object b; } struct S2 { string a; } struct S3 { int a; immutable Object b; } struct S4 { float[3] vals; } static assert( hasAliasing!S1); static assert(!hasAliasing!S2); static assert(!hasAliasing!S3); static assert(!hasAliasing!S4); } @safe unittest { import std.traits; static assert( hasIndirections!(int[string])); static assert( hasIndirections!(void delegate())); static assert( hasIndirections!(void delegate() immutable)); static assert( hasIndirections!(immutable(void delegate()))); static assert( hasIndirections!(immutable(void delegate() immutable))); static assert(!hasIndirections!(void function())); static assert( hasIndirections!(void*[1])); static assert(!hasIndirections!(byte[1])); } @safe unittest { import std.traits; struct S1 { int a; Object b; } struct S2 { string a; } struct S3 { int a; immutable Object b; } static assert( hasUnsharedAliasing!S1); static assert(!hasUnsharedAliasing!S2); static assert(!hasUnsharedAliasing!S3); struct S4 { int a; shared Object b; } struct S5 { char[] a; } struct S6 { shared char[] b; } struct S7 { float[3] vals; } static assert(!hasUnsharedAliasing!S4); static assert( hasUnsharedAliasing!S5); static assert(!hasUnsharedAliasing!S6); static assert(!hasUnsharedAliasing!S7); } @safe unittest { import std.traits; static assert(!hasElaborateCopyConstructor!int); static struct S1 { } static struct S2 { this(this) {} } static struct S3 { S2 field; } static struct S4 { S3[1] field; } static struct S5 { S3[] field; } static struct S6 { S3[0] field; } static struct S7 { @disable this(); S3 field; } static assert(!hasElaborateCopyConstructor!S1); static assert( hasElaborateCopyConstructor!S2); static assert( hasElaborateCopyConstructor!(immutable S2)); static assert( hasElaborateCopyConstructor!S3); static assert( hasElaborateCopyConstructor!(S3[1])); static assert(!hasElaborateCopyConstructor!(S3[0])); static assert( hasElaborateCopyConstructor!S4); static assert(!hasElaborateCopyConstructor!S5); static assert(!hasElaborateCopyConstructor!S6); static assert( hasElaborateCopyConstructor!S7); } @safe unittest { import std.traits; static assert(!hasElaborateAssign!int); static struct S { void opAssign(S) {} } static assert( hasElaborateAssign!S); static assert(!hasElaborateAssign!(const(S))); static struct S1 { void opAssign(ref S1) {} } static struct S2 { void opAssign(int) {} } static struct S3 { S s; } static assert( hasElaborateAssign!S1); static assert(!hasElaborateAssign!S2); static assert( hasElaborateAssign!S3); static assert( hasElaborateAssign!(S3[1])); static assert(!hasElaborateAssign!(S3[0])); } @safe unittest { import std.traits; static assert(!hasElaborateDestructor!int); static struct S1 { } static struct S2 { ~this() {} } static struct S3 { S2 field; } static struct S4 { S3[1] field; } static struct S5 { S3[] field; } static struct S6 { S3[0] field; } static struct S7 { @disable this(); S3 field; } static assert(!hasElaborateDestructor!S1); static assert( hasElaborateDestructor!S2); static assert( hasElaborateDestructor!(immutable S2)); static assert( hasElaborateDestructor!S3); static assert( hasElaborateDestructor!(S3[1])); static assert(!hasElaborateDestructor!(S3[0])); static assert( hasElaborateDestructor!S4); static assert(!hasElaborateDestructor!S5); static assert(!hasElaborateDestructor!S6); static assert( hasElaborateDestructor!S7); } @safe unittest { import std.traits; static assert(!hasElaborateMove!int); static struct S1 { } static struct S2 { void opPostMove(ref S2) {} } static struct S3 { void opPostMove(inout ref S3) inout {} } static struct S4 { void opPostMove(const ref S4) {} } static struct S5 { void opPostMove(S5) {} } static struct S6 { void opPostMove(int) {} } static struct S7 { S3[1] field; } static struct S8 { S3[] field; } static struct S9 { S3[0] field; } static struct S10 { @disable this(); S3 field; } static assert(!hasElaborateMove!S1); static assert( hasElaborateMove!S2); static assert( hasElaborateMove!S3); static assert( hasElaborateMove!(immutable S3)); static assert( hasElaborateMove!S4); static assert(!hasElaborateMove!S5); static assert(!hasElaborateMove!S6); static assert( hasElaborateMove!S7); static assert(!hasElaborateMove!S8); static assert(!hasElaborateMove!S9); static assert( hasElaborateMove!S10); } @safe unittest { import std.traits; static assert(!hasMember!(int, "blah")); struct S1 { int blah; } struct S2 { int blah(){ return 0; } } class C1 { int blah; } class C2 { int blah(){ return 0; } } static assert(hasMember!(S1, "blah")); static assert(hasMember!(S2, "blah")); static assert(hasMember!(C1, "blah")); static assert(hasMember!(C2, "blah")); } @safe unittest { import std.traits; static struct S { static void sf() {} void f() {} static int si; int i; } static assert( hasStaticMember!(S, "sf")); static assert(!hasStaticMember!(S, "f")); static assert( hasStaticMember!(S, "si")); static assert(!hasStaticMember!(S, "i")); static assert(!hasStaticMember!(S, "hello")); } @safe unittest { import std.traits; enum Sqrts : real { one = 1, two = 1.41421, three = 1.73205 } auto sqrts = [EnumMembers!Sqrts]; assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]); } @safe unittest { import std.traits; // Returns i if e is the i-th enumerator of E. static size_t rank(E)(E e) if (is(E == enum)) { static foreach (i, member; EnumMembers!E) { if (e == member) return i; } assert(0, "Not an enum member"); } enum Mode { read = 1, write = 2, map = 4 } assert(rank(Mode.read) == 0); assert(rank(Mode.write) == 1); assert(rank(Mode.map) == 2); } @safe unittest { import std.traits; import std.conv : to; class FooClass { string calledMethod; void foo() @safe { calledMethod = "foo"; } void bar() @safe { calledMethod = "bar"; } void baz() @safe { calledMethod = "baz"; } } enum FooEnum { foo, bar, baz } auto var = FooEnum.bar; auto fooObj = new FooClass(); s: final switch (var) { static foreach (member; EnumMembers!FooEnum) { case member: // Generate a case for each enum value. // Call fooObj.{name of enum value}(). __traits(getMember, fooObj, to!string(member))(); break s; } } // As we pass in FooEnum.bar, the bar() method gets called. assert(fooObj.calledMethod == "bar"); } @safe unittest { import std.traits; import std.meta : AliasSeq; interface I1 { } interface I2 { } interface I12 : I1, I2 { } static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2))); interface I3 : I1 { } interface I123 : I1, I2, I3 { } static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3))); } @safe unittest { import std.traits; import std.meta : AliasSeq; class C1 { } class C2 : C1 { } class C3 : C2 { } static assert(!BaseClassesTuple!Object.length); static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object))); static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object))); static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object))); } @safe unittest { import std.traits; interface I1 {} interface I2 {} class A : I1, I2 {} class B : A, I1 {} class C : B {} alias TL = InterfacesTuple!C; static assert(is(TL[0] == I1) && is(TL[1] == I2)); } @safe unittest { import std.traits; interface J1 {} interface J2 {} class B1 {} class B2 : B1, J1, J2 {} class B3 : B2, J1 {} alias TL = TransitiveBaseTypeTuple!B3; assert(TL.length == 5); assert(is (TL[0] == B2)); assert(is (TL[1] == B1)); assert(is (TL[2] == Object)); assert(is (TL[3] == J1)); assert(is (TL[4] == J2)); assert(TransitiveBaseTypeTuple!Object.length == 0); } @safe unittest { import std.traits; interface I { I foo(); } class B { real foo(real v) { return v; } } class C : B, I { override C foo() { return this; } // covariant overriding of I.foo() } alias foos = MemberFunctionsTuple!(C, "foo"); static assert(foos.length == 2); static assert(__traits(isSame, foos[0], C.foo)); static assert(__traits(isSame, foos[1], B.foo)); } @safe unittest { import std.traits; struct Foo(T, U) {} static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo)); } @safe unittest { import std.traits; import std.meta : AliasSeq; struct Foo(T, U) {} static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real))); } @safe unittest { import std.traits; class A { byte b; } class B { long l; } // As class instance always has a hidden pointer static assert(classInstanceAlignment!A == (void*).alignof); static assert(classInstanceAlignment!B == long.alignof); } @safe unittest { import std.traits; alias X = CommonType!(int, long, short); assert(is(X == long)); alias Y = CommonType!(int, char[], short); assert(is(Y == void)); } @safe unittest { import std.traits; static assert(is(CommonType!(3) == int)); static assert(is(CommonType!(double, 4, float) == double)); static assert(is(CommonType!(string, char[]) == const(char)[])); static assert(is(CommonType!(3, 3U) == uint)); static assert(is(CommonType!(double, int) == double)); } @safe unittest { import std.traits; import std.meta : AliasSeq; static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real))); static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real))); static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real))); static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real))); static assert(is(AllImplicitConversionTargets!(char) == AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long, ulong, float, double, real) )); static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!( short, ushort, dchar, int, uint, long, ulong, float, double, real ))); static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!( int, uint, long, ulong, float, double, real ))); static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[]))); static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*))); interface A {} interface B {} class C : A, B {} static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B))); static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B))); static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!( immutable Object, immutable A, immutable B ))); interface I : A, B {} static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B))); static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B))); static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!( immutable A, immutable B ))); } @safe unittest { import std.traits; static assert( isImplicitlyConvertible!(immutable(char), char)); static assert( isImplicitlyConvertible!(const(char), char)); static assert( isImplicitlyConvertible!(char, wchar)); static assert(!isImplicitlyConvertible!(wchar, char)); static assert(!isImplicitlyConvertible!(const(ushort), ubyte)); static assert(!isImplicitlyConvertible!(const(uint), ubyte)); static assert(!isImplicitlyConvertible!(const(ulong), ubyte)); static assert(!isImplicitlyConvertible!(const(char)[], string)); static assert( isImplicitlyConvertible!(string, const(char)[])); } @safe unittest { import std.traits; // Mutable and immmutable both convert to const... static assert( isQualifierConvertible!(char, const(char))); static assert( isQualifierConvertible!(immutable(char), const(char))); // ...but const does not convert back to mutable or immutable static assert(!isQualifierConvertible!(const(char), char)); static assert(!isQualifierConvertible!(const(char), immutable(char))); } @safe unittest { import std.traits; static assert( isAssignable!(long, int)); static assert(!isAssignable!(int, long)); static assert( isAssignable!(const(char)[], string)); static assert(!isAssignable!(string, char[])); // int is assignable to int static assert( isAssignable!int); // immutable int is not assignable to immutable int static assert(!isAssignable!(immutable int)); } @safe unittest { import std.traits; struct S1 { void opAssign(S1); } struct S2 { void opAssign(ref S2); } static assert( isRvalueAssignable!(long, int)); static assert(!isRvalueAssignable!(int, long)); static assert( isRvalueAssignable!S1); static assert(!isRvalueAssignable!S2); } @safe unittest { import std.traits; struct S1 { void opAssign(S1); } struct S2 { void opAssign(ref S2); } static assert( isLvalueAssignable!(long, int)); static assert(!isLvalueAssignable!(int, long)); static assert( isLvalueAssignable!S1); static assert( isLvalueAssignable!S2); } @safe unittest { import std.traits; interface I { I clone(); } interface J { J clone(); } class C : I { override C clone() // covariant overriding of I.clone() { return new C; } } // C.clone() can override I.clone(), indeed. static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone))); // C.clone() can't override J.clone(); the return type C is not implicitly // convertible to J. static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone))); } @system unittest { import std.traits; static int f(int); static assert(is(typeof(f(rvalueOf!int)) == int)); } @system unittest { import std.traits; static bool f(ref int); static assert(is(typeof(f(lvalueOf!int)) == bool)); } @safe unittest { import std.traits; static assert( isBoolean!bool); enum EB : bool { a = true } static assert( isBoolean!EB); struct SubTypeOfBool { bool val; alias val this; } static assert(!isBoolean!(SubTypeOfBool)); } @safe unittest { import std.traits; static assert( isIntegral!byte && isIntegral!short && isIntegral!int && isIntegral!long && isIntegral!(const(long)) && isIntegral!(immutable(long)) ); static assert( !isIntegral!bool && !isIntegral!char && !isIntegral!double ); // types which act as integral values do not pass struct S { int val; alias val this; } static assert(!isIntegral!S); } @safe unittest { import std.traits; static assert( isFloatingPoint!float && isFloatingPoint!double && isFloatingPoint!real && isFloatingPoint!(const(real)) && isFloatingPoint!(immutable(real)) ); static assert(!isFloatingPoint!int); // types which act as floating point values do not pass struct S { float val; alias val this; } static assert(!isFloatingPoint!S); } @safe unittest { import std.traits; static assert( isNumeric!byte && isNumeric!short && isNumeric!int && isNumeric!long && isNumeric!float && isNumeric!double && isNumeric!real && isNumeric!(const(real)) && isNumeric!(immutable(real)) ); static assert( !isNumeric!void && !isNumeric!bool && !isNumeric!char && !isNumeric!wchar && !isNumeric!dchar ); // types which act as numeric values do not pass struct S { int val; alias val this; } static assert(!isNumeric!S); } @safe unittest { import std.traits; static assert(!isScalarType!void); static assert( isScalarType!(immutable(byte))); static assert( isScalarType!(immutable(ushort))); static assert( isScalarType!(immutable(int))); static assert( isScalarType!(ulong)); static assert( isScalarType!(shared(float))); static assert( isScalarType!(shared(const bool))); static assert( isScalarType!(const(char))); static assert( isScalarType!(wchar)); static assert( isScalarType!(const(dchar))); static assert( isScalarType!(const(double))); static assert( isScalarType!(const(real))); } @safe unittest { import std.traits; static assert(isBasicType!void); static assert(isBasicType!(const(void))); static assert(isBasicType!(shared(void))); static assert(isBasicType!(immutable(void))); static assert(isBasicType!(shared const(void))); static assert(isBasicType!(shared inout(void))); static assert(isBasicType!(shared inout const(void))); static assert(isBasicType!(inout(void))); static assert(isBasicType!(inout const(void))); static assert(isBasicType!(immutable(int))); static assert(isBasicType!(shared(float))); static assert(isBasicType!(shared(const bool))); static assert(isBasicType!(const(dchar))); } @safe unittest { import std.traits; static assert( isUnsigned!uint && isUnsigned!ulong ); static assert( !isUnsigned!char && !isUnsigned!int && !isUnsigned!long && !isUnsigned!char && !isUnsigned!wchar && !isUnsigned!dchar ); } @safe unittest { import std.traits; static assert( isSigned!int && isSigned!long ); static assert( !isSigned!uint && !isSigned!ulong ); } @safe unittest { import std.traits; //Char types static assert( isSomeChar!char); static assert( isSomeChar!wchar); static assert( isSomeChar!dchar); static assert( isSomeChar!(typeof('c'))); static assert( isSomeChar!(immutable char)); static assert( isSomeChar!(const dchar)); //Non char types static assert(!isSomeChar!int); static assert(!isSomeChar!byte); static assert(!isSomeChar!string); static assert(!isSomeChar!wstring); static assert(!isSomeChar!dstring); static assert(!isSomeChar!(char[4])); } @safe unittest { import std.traits; //String types static assert( isSomeString!string); static assert( isSomeString!(wchar[])); static assert( isSomeString!(dchar[])); static assert( isSomeString!(typeof("aaa"))); static assert( isSomeString!(const(char)[])); //Non string types static assert(!isSomeString!int); static assert(!isSomeString!(int[])); static assert(!isSomeString!(byte[])); static assert(!isSomeString!(typeof(null))); static assert(!isSomeString!(char[4])); enum ES : string { a = "aaa", b = "bbb" } static assert(!isSomeString!ES); static struct Stringish { string str; alias str this; } static assert(!isSomeString!Stringish); } @safe unittest { import std.traits; static assert(isNarrowString!string); static assert(isNarrowString!wstring); static assert(isNarrowString!(char[])); static assert(isNarrowString!(wchar[])); static assert(!isNarrowString!dstring); static assert(!isNarrowString!(dchar[])); static assert(!isNarrowString!(typeof(null))); static assert(!isNarrowString!(char[4])); enum ES : string { a = "aaa", b = "bbb" } static assert(!isNarrowString!ES); static struct Stringish { string str; alias str this; } static assert(!isNarrowString!Stringish); } @safe unittest { import std.traits; static assert(isOrderingComparable!int); static assert(isOrderingComparable!string); static struct Foo {} static assert(!isOrderingComparable!Foo); static struct Bar { int a; auto opCmp(Bar b1) const { return a - b1.a; } } Bar b1 = Bar(5); Bar b2 = Bar(7); assert(isOrderingComparable!Bar && b2 > b1); } @safe unittest { import std.traits; static struct AliasedString { string s; alias s this; } enum StringEnum { a = "foo" } assert(!isConvertibleToString!string); assert(isConvertibleToString!AliasedString); assert(isConvertibleToString!StringEnum); assert(isConvertibleToString!(char[25])); assert(!isConvertibleToString!(char[])); } @safe unittest { import std.traits; static struct Stringish { string s; alias s this; } static assert(isAutodecodableString!wstring); static assert(isAutodecodableString!Stringish); static assert(!isAutodecodableString!dstring); enum E : const(char)[3] { X = "abc" } enum F : const(char)[] { X = "abc" } enum G : F { X = F.init } static assert(isAutodecodableString!(char[])); static assert(!isAutodecodableString!(E)); static assert(isAutodecodableString!(F)); static assert(isAutodecodableString!(G)); struct Stringish2 { Stringish s; alias s this; } enum H : Stringish { X = Stringish() } enum I : Stringish2 { X = Stringish2() } static assert(isAutodecodableString!(H)); static assert(isAutodecodableString!(I)); static assert(!isAutodecodableString!(noreturn[])); static assert(!isAutodecodableString!(immutable(noreturn)[])); } @safe unittest { import std.traits; static assert( isStaticArray!(int[3])); static assert( isStaticArray!(const(int)[5])); static assert( isStaticArray!(const(int)[][5])); static assert(!isStaticArray!(const(int)[])); static assert(!isStaticArray!(immutable(int)[])); static assert(!isStaticArray!(const(int)[4][])); static assert(!isStaticArray!(int[])); static assert(!isStaticArray!(int[char])); static assert(!isStaticArray!(int[1][])); static assert(!isStaticArray!(int[int])); static assert(!isStaticArray!int); } @safe unittest { import std.traits; static assert( isDynamicArray!(int[])); static assert( isDynamicArray!(string)); static assert( isDynamicArray!(long[3][])); static assert(!isDynamicArray!(int[5])); static assert(!isDynamicArray!(typeof(null))); } @safe unittest { import std.traits; static assert( isArray!(int[])); static assert( isArray!(int[5])); static assert( isArray!(string)); static assert(!isArray!uint); static assert(!isArray!(uint[uint])); static assert(!isArray!(typeof(null))); } @safe unittest { import std.traits; struct S; static assert( isAssociativeArray!(int[string])); static assert( isAssociativeArray!(S[S])); static assert(!isAssociativeArray!(string[])); static assert(!isAssociativeArray!S); static assert(!isAssociativeArray!(int[4])); } @safe unittest { import std.traits; class C; union U; struct S; interface I; static assert( isBuiltinType!void); static assert( isBuiltinType!string); static assert( isBuiltinType!(int[])); static assert( isBuiltinType!(C[string])); static assert( isBuiltinType!(typeof(null))); static assert(!isBuiltinType!C); static assert(!isBuiltinType!U); static assert(!isBuiltinType!S); static assert(!isBuiltinType!I); static assert(!isBuiltinType!(void delegate(int))); } @safe unittest { import std.traits; static if (is(__vector(float[4]))) { alias SimdVec = __vector(float[4]); static assert(isSIMDVector!(__vector(float[4]))); static assert(isSIMDVector!SimdVec); } static assert(!isSIMDVector!uint); static assert(!isSIMDVector!(float[4])); } @safe unittest { import std.traits; void fun(); static assert( isPointer!(int*)); static assert( isPointer!(int function())); static assert(!isPointer!int); static assert(!isPointer!string); static assert(!isPointer!(typeof(null))); static assert(!isPointer!(typeof(fun))); static assert(!isPointer!(int delegate())); } @safe unittest { import std.traits; static assert(is(PointerTarget!(int*) == int)); static assert(is(PointerTarget!(void*) == void)); } @safe unittest { import std.traits; 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))); enum ES : S { a = S.init } enum EC : C { a = C.init } enum EI : I { a = I.init } enum EU : U { a = U.init } static assert( isAggregateType!ES); static assert( isAggregateType!EC); static assert( isAggregateType!EI); static assert( isAggregateType!EU); } @safe unittest { import std.traits; struct OpApply { int opApply(scope 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); } @safe unittest { import std.traits; static assert( isMutable!int); static assert( isMutable!string); static assert( isMutable!(shared int)); static assert( isMutable!(shared const(int)[])); static assert(!isMutable!(const int)); static assert(!isMutable!(inout int)); static assert(!isMutable!(shared(const int))); static assert(!isMutable!(shared(inout int))); static assert(!isMutable!(immutable string)); } @safe unittest { import std.traits; static struct Foo(T...) { } static struct Bar(T...) { } static struct Doo(T) { } static struct ABC(int x) { } static void fun(T)() { } template templ(T) { } static assert(isInstanceOf!(Foo, Foo!int)); static assert(!isInstanceOf!(Foo, Bar!int)); static assert(!isInstanceOf!(Foo, int)); static assert(isInstanceOf!(Doo, Doo!int)); static assert(isInstanceOf!(ABC, ABC!1)); static assert(!isInstanceOf!(Foo, Foo)); static assert(isInstanceOf!(fun, fun!int)); static assert(isInstanceOf!(templ, templ!int)); } @safe unittest { import std.traits; static struct A(T = void) { // doesn't work as expected, only accepts A when T = void void func(B)(B b) if (isInstanceOf!(A, B)) {} // correct behavior void method(B)(B b) if (isInstanceOf!(TemplateOf!(A), B)) {} } A!(void) a1; A!(void) a2; A!(int) a3; static assert(!__traits(compiles, a1.func(a3))); static assert( __traits(compiles, a1.method(a2))); static assert( __traits(compiles, a1.method(a3))); } @safe unittest { import std.traits; static assert(isExpressions!(1, 2.0, "a")); static assert(!isExpressions!(int, double, string)); static assert(!isExpressions!(int, 2.0, "a")); } @safe unittest { import std.traits; static assert(isTypeTuple!(int, float, string)); static assert(!isTypeTuple!(1, 2.0, "a")); static assert(!isTypeTuple!(1, double, string)); } @safe unittest { import std.traits; static void foo() {} void bar() {} auto fpfoo = &foo; static assert( isFunctionPointer!fpfoo); static assert( isFunctionPointer!(void function())); auto dgbar = &bar; static assert(!isFunctionPointer!dgbar); static assert(!isFunctionPointer!(void delegate())); static assert(!isFunctionPointer!foo); static assert(!isFunctionPointer!bar); static assert( isFunctionPointer!((int a) {})); } @safe unittest { import std.traits; static void sfunc() { } int x; void func() { x++; } int delegate() dg; assert(isDelegate!dg); assert(isDelegate!(int delegate())); assert(isDelegate!(typeof(&func))); int function() fp; assert(!isDelegate!fp); assert(!isDelegate!(int function())); assert(!isDelegate!(typeof(&sfunc))); } @safe unittest { import std.traits; static real func(ref int) { return 0; } static void prop() @property { } class C { real method(ref int) { return 0; } real prop() @property { return 0; } } auto c = new C; auto fp = &func; auto dg = &c.method; static assert( isSomeFunction!func); static assert( isSomeFunction!prop); static assert( isSomeFunction!(C.method)); static assert( isSomeFunction!(C.prop)); static assert( isSomeFunction!(c.prop)); static assert( isSomeFunction!fp); static assert( isSomeFunction!dg); real val; static assert(!isSomeFunction!int); static assert(!isSomeFunction!val); } @safe unittest { import std.traits; void f() { } int g(int x) { return x; } static assert( isCallable!f); static assert( isCallable!g); class C { int opCall(int) { return 0; } } auto c = new C; struct S { static int opCall(int) { return 0; } } interface I { real value() @property; } static assert( isCallable!c); static assert( isCallable!(c.opCall)); static assert( isCallable!S); static assert( isCallable!(I.value)); static assert( isCallable!((int a) { return a; })); static assert(!isCallable!I); } @safe unittest { import std.traits; void f()() { } T g(T = int)(T x) { return x; } struct S1 { static void opCall()() { } } struct S2 { static T opCall(T = int)(T x) {return x; } } static assert( isCallable!f); static assert( isCallable!g); static assert( isCallable!S1); static assert( isCallable!S2); } @safe unittest { import std.traits; static struct Wrapper { void f() { } int f(int x) { return x; } void g()() { } T g(T = int)(T x) { return x; } } static assert(isCallable!(Wrapper.f)); static assert(isCallable!(Wrapper.g)); } @safe unittest { import std.traits; struct S { void foo() { } } class C { void foo() { } } class AC { abstract void foo(); } static assert(!isAbstractFunction!(int)); static assert(!isAbstractFunction!(S.foo)); static assert(!isAbstractFunction!(C.foo)); static assert( isAbstractFunction!(AC.foo)); } @safe unittest { import std.traits; struct S { void bar() { } } final class FC { void foo(); } class C { void bar() { } final void foo(); } static assert(!isFinalFunction!(int)); static assert(!isFinalFunction!(S.bar)); static assert( isFinalFunction!(FC.foo)); static assert(!isFinalFunction!(C.bar)); static assert( isFinalFunction!(C.foo)); } @safe unittest { import std.traits; static void f() {} static void fun() { int i; int f() { return i; } static assert(isNestedFunction!(f)); } static assert(!isNestedFunction!f); } @safe unittest { import std.traits; struct S { } class C { } abstract class AC { } static assert(!isAbstractClass!S); static assert(!isAbstractClass!C); static assert( isAbstractClass!AC); C c; static assert(!isAbstractClass!c); AC ac; static assert( isAbstractClass!ac); } @safe unittest { import std.traits; class C { } abstract class AC { } final class FC1 : C { } final class FC2 { } static assert(!isFinalClass!C); static assert(!isFinalClass!AC); static assert( isFinalClass!FC1); static assert( isFinalClass!FC2); C c; static assert(!isFinalClass!c); FC1 fc1; static assert( isFinalClass!fc1); } @safe unittest { import std.traits; static assert(is(Unconst!int == int)); static assert(is(Unconst!(const int) == int)); static assert(is(Unconst!(immutable int) == int)); static assert(is(Unconst!(shared int) == shared int)); static assert(is(Unconst!(shared(const int)) == shared int)); } @safe unittest { import std.traits; static assert(is(Unshared!int == int)); static assert(is(Unshared!(const int) == const int)); static assert(is(Unshared!(immutable int) == immutable int)); static assert(is(Unshared!(shared int) == int)); static assert(is(Unshared!(shared(const int)) == const int)); static assert(is(Unshared!(shared(int[])) == shared(int)[])); } @safe unittest { import std.traits; static assert(is(Unqual!int == int)); static assert(is(Unqual!(const int) == int)); static assert(is(Unqual!(immutable int) == int)); static assert(is(Unqual!(shared int) == int)); static assert(is(Unqual!(shared(const int)) == int)); } @safe unittest { import std.traits; static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int)); } @safe unittest { import std.traits; const(int) i; CopyConstness!(typeof(i), float) f; assert( is(typeof(f) == const float)); CopyConstness!(char, uint) u; assert( is(typeof(u) == uint)); //The 'shared' qualifier will not be copied assert(!is(CopyConstness!(shared bool, int) == shared int)); //But the constness will be assert( is(CopyConstness!(shared const real, double) == const double)); //Careful, const(int)[] is a mutable array of const(int) alias MutT = CopyConstness!(const(int)[], int); assert(!is(MutT == const(int))); //Okay, const(int[]) applies to array and contained ints alias CstT = CopyConstness!(const(int[]), int); assert( is(CstT == const(int))); } @safe unittest { import std.traits; static assert(is(ForeachType!(uint[]) == uint)); static assert(is(ForeachType!string == immutable(char))); static assert(is(ForeachType!(string[string]) == string)); static assert(is(ForeachType!(inout(int)[]) == inout(int))); } @safe unittest { import std.traits; enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle 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)); } @safe unittest { import std.traits; alias Hash = int[string]; static assert(is(KeyType!Hash == string)); static assert(is(ValueType!Hash == int)); KeyType!Hash str = "a"; // str is declared as string ValueType!Hash num = 1; // num is declared as int } @safe unittest { import std.traits; alias Hash = int[string]; static assert(is(KeyType!Hash == string)); static assert(is(ValueType!Hash == int)); KeyType!Hash str = "a"; // str is declared as string ValueType!Hash num = 1; // num is declared as int } @safe unittest { import std.traits; static assert(is(Unsigned!(int) == uint)); static assert(is(Unsigned!(long) == ulong)); static assert(is(Unsigned!(const short) == const ushort)); static assert(is(Unsigned!(immutable byte) == immutable ubyte)); static assert(is(Unsigned!(inout int) == inout uint)); } @safe unittest { import std.traits; static assert(is(Unsigned!(uint) == uint)); static assert(is(Unsigned!(const uint) == const uint)); static assert(is(Unsigned!(ubyte) == ubyte)); static assert(is(Unsigned!(immutable uint) == immutable uint)); } @safe unittest { import std.traits; 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)); static if (is(ucent)) static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent)); } @safe unittest { import std.traits; alias S1 = Signed!uint; static assert(is(S1 == int)); alias S2 = Signed!(const(uint)); static assert(is(S2 == const(int))); alias S3 = Signed!(immutable(uint)); static assert(is(S3 == immutable(int))); static if (is(ucent)) { alias S4 = Signed!ucent; static assert(is(S4 == cent)); } } @safe unittest { import std.traits; static assert(mostNegative!float == -float.max); static assert(mostNegative!double == -double.max); static assert(mostNegative!real == -real.max); static assert(mostNegative!bool == false); } @safe unittest { import std.traits; import std.meta : AliasSeq; static foreach (T; AliasSeq!(bool, byte, short, int, long)) static assert(mostNegative!T == T.min); static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar)) static assert(mostNegative!T == 0); } @safe unittest { import std.traits; ubyte a = 3, b = 5; static assert(is(typeof(a * b) == Promoted!ubyte)); static assert(is(Promoted!ubyte == int)); static assert(is(Promoted!(shared(bool)) == shared(int))); static assert(is(Promoted!(const(int)) == const(int))); static assert(is(Promoted!double == double)); } @safe unittest { import std.traits; import std.meta : AliasSeq; alias TL = staticMap!(mangledName, int, const int, immutable int); static assert(TL == AliasSeq!("i", "xi", "yi")); } @safe unittest { import std.traits; // can select types static assert(is(Select!(true, int, long) == int)); static assert(is(Select!(false, int, long) == long)); static struct Foo {} static assert(is(Select!(false, const(int), const(Foo)) == const(Foo))); // can select symbols int a = 1; int b = 2; alias selA = Select!(true, a, b); alias selB = Select!(false, a, b); assert(selA == 1); assert(selB == 2); // can select (compile-time) expressions enum val = Select!(false, -4, 9 - 6); static assert(val == 3); } @safe unittest { import std.traits; real run() { return 0; } int fail() { assert(0); } auto a = select!true(run(), fail()); auto b = select!false(fail(), run()); static assert(is(typeof(a) == real)); static assert(is(typeof(b) == real)); } @safe unittest { import std.traits; enum E; struct S {} @("alpha") int a; static assert(hasUDA!(a, "alpha")); static assert(!hasUDA!(a, S)); static assert(!hasUDA!(a, E)); @(E) int b; static assert(!hasUDA!(b, "alpha")); static assert(!hasUDA!(b, S)); static assert(hasUDA!(b, E)); @E int c; static assert(!hasUDA!(c, "alpha")); static assert(!hasUDA!(c, S)); static assert(hasUDA!(c, E)); @(S, E) int d; static assert(!hasUDA!(d, "alpha")); static assert(hasUDA!(d, S)); static assert(hasUDA!(d, E)); @S int e; static assert(!hasUDA!(e, "alpha")); static assert(hasUDA!(e, S)); static assert(!hasUDA!(e, S())); static assert(!hasUDA!(e, E)); @S() int f; static assert(!hasUDA!(f, "alpha")); static assert(hasUDA!(f, S)); static assert(hasUDA!(f, S())); static assert(!hasUDA!(f, E)); @(S, E, "alpha") int g; static assert(hasUDA!(g, "alpha")); static assert(hasUDA!(g, S)); static assert(hasUDA!(g, E)); @(100) int h; static assert(hasUDA!(h, 100)); struct Named { string name; } @Named("abc") int i; static assert(hasUDA!(i, Named)); static assert(hasUDA!(i, Named("abc"))); static assert(!hasUDA!(i, Named("def"))); struct AttrT(T) { string name; T value; } @AttrT!int("answer", 42) int j; static assert(hasUDA!(j, AttrT)); static assert(hasUDA!(j, AttrT!int)); static assert(!hasUDA!(j, AttrT!string)); @AttrT!string("hello", "world") int k; static assert(hasUDA!(k, AttrT)); static assert(!hasUDA!(k, AttrT!int)); static assert(hasUDA!(k, AttrT!string)); struct FuncAttr(alias f) { alias func = f; } static int fourtyTwo() { return 42; } static size_t getLen(string s) { return s.length; } @FuncAttr!getLen int l; static assert(hasUDA!(l, FuncAttr)); static assert(!hasUDA!(l, FuncAttr!fourtyTwo)); static assert(hasUDA!(l, FuncAttr!getLen)); static assert(!hasUDA!(l, FuncAttr!fourtyTwo())); static assert(!hasUDA!(l, FuncAttr!getLen())); @FuncAttr!getLen() int m; static assert(hasUDA!(m, FuncAttr)); static assert(!hasUDA!(m, FuncAttr!fourtyTwo)); static assert(hasUDA!(m, FuncAttr!getLen)); static assert(!hasUDA!(m, FuncAttr!fourtyTwo())); static assert(hasUDA!(m, FuncAttr!getLen())); } @safe unittest { import std.traits; struct Attr { string name; int value; } @Attr("Answer", 42) int a; static assert(getUDAs!(a, Attr).length == 1); 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).length == 1); 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).length == 2); 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); static assert(getUDAs!(c, Attr("Answer", 42)).length == 1); static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer"); static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42); static assert(getUDAs!(c, Attr("Answer", 99)).length == 0); struct AttrT(T) { string name; T value; } @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d; static assert(getUDAs!(d, AttrT).length == 2); 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).length == 1); static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer"); static assert(getUDAs!(d, AttrT!uint)[0].value == 42); static assert(getUDAs!(d, AttrT!int).length == 1); static assert(getUDAs!(d, AttrT!int)[0].name == "Pi"); static assert(getUDAs!(d, AttrT!int)[0].value == 3); struct SimpleAttr {} @SimpleAttr int e; static assert(getUDAs!(e, SimpleAttr).length == 1); static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr)); @SimpleAttr() int f; static assert(getUDAs!(f, SimpleAttr).length == 1); static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr)); struct FuncAttr(alias f) { alias func = f; } static int add42(int v) { return v + 42; } static string concat(string l, string r) { return l ~ r; } @FuncAttr!add42 int g; static assert(getUDAs!(g, FuncAttr).length == 1); static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47); static assert(getUDAs!(g, FuncAttr!add42).length == 1); static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47); static assert(getUDAs!(g, FuncAttr!add42()).length == 0); static assert(getUDAs!(g, FuncAttr!concat).length == 0); static assert(getUDAs!(g, FuncAttr!concat()).length == 0); @FuncAttr!add42() int h; static assert(getUDAs!(h, FuncAttr).length == 1); static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47); static assert(getUDAs!(h, FuncAttr!add42).length == 1); static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47); static assert(getUDAs!(h, FuncAttr!add42()).length == 1); static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47); static assert(getUDAs!(h, FuncAttr!concat).length == 0); static assert(getUDAs!(h, FuncAttr!concat()).length == 0); @("alpha") @(42) int i; static assert(getUDAs!(i, "alpha").length == 1); static assert(getUDAs!(i, "alpha")[0] == "alpha"); static assert(getUDAs!(i, 42).length == 1); static assert(getUDAs!(i, 42)[0] == 42); static assert(getUDAs!(i, 'c').length == 0); } @safe unittest { import std.traits; enum Attr; struct A { @Attr int a; int b; } static assert(getSymbolsByUDA!(A, Attr).length == 1); static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr)); } @safe unittest { import std.traits; 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)); } @safe unittest { import std.traits; 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"); } @safe unittest { import std.traits; static struct UDA { string name; } @UDA("A") static struct C { @UDA("B") int d; } static assert(getSymbolsByUDA!(C, UDA).length == 2); static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C"); static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d"); } @safe unittest { import std.traits; static struct UDA { string name; } static struct D { int x; } static assert(getSymbolsByUDA!(D, UDA).length == 0); } @safe unittest { import std.traits; static assert(allSameType!()); static assert(allSameType!(int)); static assert(allSameType!(int, int)); static assert(allSameType!(int, int, int)); static assert(allSameType!(float, float, float)); static assert(!allSameType!(int, double)); static assert(!allSameType!(int, float, double)); static assert(!allSameType!(int, float, double, real)); static assert(!allSameType!(short, int, float, double, real)); } @safe unittest { import std.traits; class C; struct S1; struct S2 { T opCast(T)() const; } static assert( ifTestable!bool); static assert( ifTestable!int); static assert( ifTestable!(S1*)); static assert( ifTestable!(typeof(null))); static assert( ifTestable!(int[])); static assert( ifTestable!(int[string])); static assert( ifTestable!S2); static assert( ifTestable!C); static assert(!ifTestable!S1); } @safe unittest { import std.traits; struct S { template Test() {} } class C {} interface I {} union U {} static assert(isType!int); static assert(isType!string); static assert(isType!(int[int])); static assert(isType!S); static assert(isType!C); static assert(isType!I); static assert(isType!U); int n; void func(){} static assert(!isType!n); static assert(!isType!func); static assert(!isType!(S.Test)); static assert(!isType!(S.Test!())); } @safe unittest { import std.traits; static void func(){} static assert(isFunction!func); struct S { void func(){} } static assert(isFunction!(S.func)); } @safe unittest { import std.traits; class C { void nf() {} static void sf() {} final void ff() {} } final class FC { } static assert(!isFinal!(C)); static assert( isFinal!(FC)); static assert(!isFinal!(C.nf)); static assert(!isFinal!(C.sf)); static assert( isFinal!(C.ff)); } @safe unittest { import std.traits; struct S1 {} // Fine. Can be copied struct S2 { this(this) {}} // Fine. Can be copied struct S3 {@disable this(this); } // Not fine. Copying is disabled. struct S4 {S3 s;} // Not fine. A field has copying disabled. class C1 {} static assert( isCopyable!S1); static assert( isCopyable!S2); static assert(!isCopyable!S3); static assert(!isCopyable!S4); static assert(isCopyable!C1); static assert(isCopyable!int); static assert(isCopyable!(int[])); }