| @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[])); | |
| } | |