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