Исходный код: std/traits.d
MutableOf
(T)InoutOf
(T)ConstOf
(T)SharedOf
(T)SharedInoutOf
(T)SharedConstOf
(T)ImmutableOf
(T)packageName
(alias T)import std.traits; static assert(packageName!packageName == "std");
moduleName
(alias T)import std.traits; static assert(moduleName!moduleName == "std.traits");
fullyQualifiedName
(T...) if (T.length == 1)Пример:
module myModule; struct MyStruct {} static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");
static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName");
ReturnType
(func...) if (func.length == 1 && isCallable!func)int foo(); ReturnType!foo x; // x объявлен как int
Parameters
(func...) if (func.length == 1 && isCallable!func)int foo(int, long); void bar(Parameters!foo); // объявлена void bar(int, long); void abc(Parameters!foo[1]); // объявлена void abc(long);
ParameterTypeTuple
= Parameters(func...) if (func.length == 1 && isCallable!func);
arity
(alias func) if (isCallable!func && variadicFunctionStyle!func == Variadic.no)arity
неопределена для функций с переменным числом аргументов (variadic).void foo(){} static assert(arity!foo==0); void bar(uint){} static assert(arity!bar==1); void variadicFoo(uint...){} static assert(!__traits(compiles, arity!variadicFoo));
alias STC = ParameterStorageClass; // укороченное имя перечисления void func(ref int ctx, out real result, real param) { } alias pstc = ParameterStorageClassTuple!func; static assert(pstc.length == 3); // три параметра static assert(pstc[0] == STC.ref_); static assert(pstc[1] == STC.out_); static assert(pstc[2] == STC.none);
none
scope_
out_
ref_
lazy_
return_
ParameterIdentifierTuple
(func...) if (func.length == 1 && isCallable!func)int foo(int num, string name, int); static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
ParameterDefaults
(func...) if (func.length == 1 && isCallable!func)int foo(int num, string name = "hello", int[] = [1,2,3]); static assert(is(ParameterDefaults!foo[0] == void)); static assert( ParameterDefaults!foo[1] == "hello"); static assert( ParameterDefaults!foo[2] == [1,2,3]);
ParameterDefaultValueTuple
= ParameterDefaults(func...) if (func.length == 1 && isCallable!func);
import std.traits : functionAttributes, FunctionAttribute; alias FA = FunctionAttribute; // укороченное имя перечисления 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)); // не @trusted
none
pure_
nothrow_
ref_
property
trusted
safe
nogc
system
const_
immutable_
inout_
shared_
return_
isSafe
(alias func) if (isCallable!func)true
, если func – это @safe или @trusted.@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);
isUnsafe
(alias func);
true
, если func – это @system.@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);
functionLinkage
(func...) if (func.length == 1 && isCallable!func)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");
void func() {} static assert(variadicFunctionStyle!func == Variadic.no); extern(C) int printf(in char*, ...); static assert(variadicFunctionStyle!printf == Variadic.c);
no
c
d
typesafe
typesafe
.FunctionTypeOf
(func...) if (func.length == 1 && isCallable!func)FunctionTypeOf
способно получить тип функции у свойства.
Замечание: Не спутайте типы функций с типами типами функциональных указателей; типы функций обычно используются для целей отражения во время компиляции. Do not confuse function types with function pointer types; function types are usually used for compile-time reflection purposes.
class C { int value() @property { return 0; } } static assert(is( typeof(C.value) == int )); static assert(is( FunctionTypeOf!(C.value) == function ));
SetFunctionAttributes
(T, string linkage, uint attrs) if (isFunctionPointer!T || isDelegate!T)SetFunctionAttributes
(T, string linkage, uint attrs) if (is(T == function))T | Базовый тип. |
linkage | Желаемое соглашение о вызове результирующего типа. |
attrs | Желаемые атрибуты функции FunctionAttribute результирующего типа. |
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; }
isInnerClass
(T) if (is(T == class))T | проверяемый тип |
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));
isNested
(T) if (is(T == class) || is(T == struct) || is(T == union))static struct S { } static assert(!isNested!S); int i; struct NestedStruct { void f() { ++i; } } static assert(isNested!NestedStruct);
hasNested
(T)static struct S { } int i; struct NS { void f() { ++i; } } static assert(!hasNested!(S[2])); static assert(hasNested!(NS[2]));
Fields
(T)struct S { int x; float y; } static assert(is(Fields!S == TypeTuple!(int, float)));
FieldTypeTuple
= Fields(T);
FieldNameTuple
(T)struct S { int x; float y; } static assert(FieldNameTuple!S == TypeTuple!("x", "y")); static assert(FieldNameTuple!int == TypeTuple!"");
RepresentationTypeTuple
(T)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*));
hasAliasing
(T...)true
тогда и только тогда, когда представление T включает в себя по крайней мере одно из следующего: 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);
hasIndirections
(T)true
тогда и только тогда, когда представление T включает в себя по крайней мере одно из следующего: 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]));
hasUnsharedAliasing
(T...)true
тогда и только тогда, когда представление T включает в себя по крайней мере одно из следующего: 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);
hasElaborateCopyConstructor
(S)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);
hasElaborateAssign
(S)Замечание: Структура с (возможно вложенным) postblit оператором (операторами) получит скрытый сгенерированный компилятором сложный оператор присвоения (если не отключен явно).
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]));
hasElaborateDestructor
(S)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);
hasMember
(T, string name);
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"));
EnumMembers
(E) if (is(E == enum))E | Тип перечисления. E может иметь дублированные значения. |
Замечание:
enum может иметь несколько членов, которые имеют одно и то же значение. Если вы хотите использовать EnumMembers
чтобы, например, генерировать случаи в операторе switch во время компиляции, вы должны использовать шаблон std.meta.NoDuplicates, чтобы избегать генерации дублированных случаев в switch.
Замечание: Возвращаемые значения строго типизированы с E. Таким образом, следующий код не работает без явного приведения через cast:
enum E : int { a, b, c } int[] abc = cast(int[]) [ EnumMembers!E ];В cast нет необходимости, если тип переменной выводится. Смотрите пример ниже.
Пример: Создание массива из значений перечисления:
enum Sqrts : real { one = 1, two = 1.41421, three = 1.73205, } auto sqrts = [ EnumMembers!Sqrts ]; assert(sqrts == [ Sqrts.one, Sqrts.two, Sqrts.three ]);Обобщенная функция rank(v) в следующем примере использует этот шаблон для обнаружения члена e в типе перечисления E.
// Возвращает i, если e - i-й член E. size_t rank(E)(E e) if (is(E == enum)) { 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);
BaseTypeTuple
(A)BaseTypeTuple
!Object возвращает пустой кортеж типов.interface I1 { } interface I2 { } interface I12 : I1, I2 { } static assert(is(BaseTypeTuple!I12 == TypeTuple!(I1, I2))); interface I3 : I1 { } interface I123 : I1, I2, I3 { } static assert(is(BaseTypeTuple!I123 == TypeTuple!(I1, I2, I3)));
BaseClassesTuple
(T) if (is(T == class))BaseClassesTuple
!Object даёт пустой кортеж типов.class C1 { } class C2 : C1 { } class C3 : C2 { } static assert(!BaseClassesTuple!Object.length); static assert(is(BaseClassesTuple!C1 == TypeTuple!(Object))); static assert(is(BaseClassesTuple!C2 == TypeTuple!(C1, Object))); static assert(is(BaseClassesTuple!C3 == TypeTuple!(C2, C1, Object)));
InterfacesTuple
(T)InterfacesTuple
!Object
даёт пустой кортеж типов.TransitiveBaseTypeTuple
(T)TransitiveBaseTypeTuple
!Object даёт пустой кортеж типов.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);
MemberFunctionsTuple
(C, string name) if (is(C == class) || is(C == interface))interface I { I foo(); } class B { real foo(real v) { return v; } } class C : B, I { override C foo() { return this; } // ковариантная перегрузка 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));
TemplateOf
(alias T : Base!Args, alias Base, Args...)TemplateOf
(T : Base!Args, alias Base, Args...)struct Foo(T, U) {} static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
TemplateArgsOf
(alias T : Base!Args, alias Base, Args...)TemplateArgsOf
(T : Base!Args, alias Base, Args...)struct Foo(T, U) {} static assert(is(TemplateArgsOf!(Foo!(int, real)) == TypeTuple!(int, real)));
classInstanceAlignment
(T) if (is(T == class))class A { byte b; } class B { long l; } // Экземпляр класса всегда имеет скрытый указатель static assert(classInstanceAlignment!A == (void*).alignof); static assert(classInstanceAlignment!B == long.alignof);
CommonType
(T...)alias X = CommonType!(int, long, short); assert(is(X == long)); alias Y = CommonType!(int, char[], short); assert(is(Y == void));
ImplicitConversionTargets
(T)ImplicitConversionTargets
!double не включает float.isImplicitlyConvertible
(From, To);
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)[]));
isAssignable
(Lhs, Rhs = Lhs);
true
тогда и только тогда, когда значение типа Rhs может быть присвоено переменной типа Lhs.
isAssignable
возвращает, могут ли быть присвоены одновременно как lvalue, так и rvalue.
Если вы опускаете Rhs, isAssignable
проверит тождественное присвоение Lhs.static assert( isAssignable!(long, int)); static assert(!isAssignable!(int, long)); static assert( isAssignable!(const(char)[], string)); static assert(!isAssignable!(string, char[])); // int присваивается в int static assert( isAssignable!int); // immutable int не присваивается в immutable int static assert(!isAssignable!(immutable int));
isCovariantWith
(F, G) if (is(F == function) && is(G == function))interface I { I clone(); } interface J { J clone(); } class C : I { override C clone() // ковариантная перегрузка I.clone() { return new C; } } // C.clone() может перегрузить I.clone(), безусловно. static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone))); // C.clone() не может перегрузить J.clone(); возвращаемый тип C неявно не // преобразуется в J. static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
rvalueOf
(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
lvalueOf
(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
Замечание: Попытка использовать возвращённое значение закончится ошибкой "Symbol Undefined" во время линковки.
Example:
// Заметьте, что `f` не обязательно реализовывать, // так как она не вызывается. int f(int); bool f(ref int); static assert(is(typeof(f(rvalueOf!int)) == int)); static assert(is(typeof(f(lvalueOf!int)) == bool)); int i = rvalueOf!int; // ошибка, никакое действительное значение не возвращается
isBoolean
(T);
static assert( isBoolean!bool); enum EB : bool { a = true } static assert( isBoolean!EB); static assert(!isBoolean!(SubTypeOf!bool));
isIntegral
(T);
isFloatingPoint
(T);
isNumeric
(T);
isScalarType
(T);
static assert(!isScalarType!void); static assert( isScalarType!(immutable(int))); static assert( isScalarType!(shared(float))); static assert( isScalarType!(shared(const bool))); static assert( isScalarType!(const(dchar)));
isBasicType
(T);
static assert(isBasicType!void); static assert(isBasicType!(immutable(int))); static assert(isBasicType!(shared(float))); static assert(isBasicType!(shared(const bool))); static assert(isBasicType!(const(dchar)));
isUnsigned
(T);
isSigned
(T);
isSomeChar
(T);
//Символьные типы 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)); //Не символьные типы 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]));
isSomeString
(T);
//Строковые типы static assert( isSomeString!string); static assert( isSomeString!(wchar[])); static assert( isSomeString!(dchar[])); static assert( isSomeString!(typeof("aaa"))); static assert( isSomeString!(const(char)[])); enum ES : string { a = "aaa", b = "bbb" } static assert( isSomeString!ES); //Не строковые типы static assert(!isSomeString!int); static assert(!isSomeString!(int[])); static assert(!isSomeString!(byte[])); static assert(!isSomeString!(typeof(null))); static assert(!isSomeString!(char[4]));
isNarrowString
(T);
static assert(isNarrowString!string); static assert(isNarrowString!wstring); static assert(isNarrowString!(char[])); static assert(isNarrowString!(wchar[])); static assert(!isNarrowString!dstring); static assert(!isNarrowString!(dchar[]));
isAutodecodableString
(T);
T | тестируемый тип |
true
, если T представляет строку, подлежащую автоматическому декодированию
Смотрите также:
isNarrowStringstatic struct Stringish { string s; alias s this; } assert(isAutodecodableString!wstring); assert(isAutodecodableString!Stringish); assert(!isAutodecodableString!dstring);
isStaticArray
(T);
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);
isDynamicArray
(T);
static assert( isDynamicArray!(int[])); static assert( isDynamicArray!(string)); static assert( isDynamicArray!(long[3][])); static assert(!isDynamicArray!(int[5])); static assert(!isDynamicArray!(typeof(null)));
isArray
(T);
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)));
isAssociativeArray
(T);
isBuiltinType
(T);
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!C); static assert(!isBuiltinType!U); static assert(!isBuiltinType!S); static assert(!isBuiltinType!I); static assert(!isBuiltinType!(void delegate(int)));
isSIMDVector
(T);
isPointer
(T);
PointerTarget
(T : T*)isAggregateType
(T);
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)));
isIterable
(T);
true
, если T может быть итерирован с использованием цикла foreach с единственной переменной цикла автоматически выведенного типа, независимо от того, как цикл foreach реализован. Сюда включаются диапазоны, структуры/классы, которые определяют opApply с единственной переменной цикла, и встроенные динамические, статические и ассоциативные массивы.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);
isMutable
(T);
true
, если T не является const или immutable. Заметьте, что isMutable
возвращает true
для string, или immutable(char)[], поскольку "голова" является изменяемой.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));
isInstanceOf
(alias S, T);
isInstanceOf
(alias S, alias T);
true
, если T является экземпляром шаблона S.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));
isExpressions
(T...)static assert(isExpressions!(1, 2.0, "a")); static assert(!isExpressions!(int, double, string)); static assert(!isExpressions!(int, 2.0, "a"));
isExpressionTuple
= isExpressions(T...);
isTypeTuple
(T...)static assert(isTypeTuple!(int, float, string)); static assert(!isTypeTuple!(1, 2.0, "a")); static assert(!isTypeTuple!(1, double, string));
isFunctionPointer
(T...) if (T.length == 1)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) {}));
isDelegate
(T...) if (T.length == 1)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)));
isSomeFunction
(T...) if (T.length == 1)isCallable
(T...) if (T.length == 1)interface I { real value() @property; } struct S { static int opCall(int) { return 0; } } class C { int opCall(int) { return 0; } } auto c = new C; static assert( isCallable!c); static assert( isCallable!S); static assert( isCallable!(c.opCall)); static assert( isCallable!(I.value)); static assert( isCallable!((int a) { return a; })); static assert(!isCallable!I);
isAbstractFunction
(T...) if (T.length == 1)isFinalFunction
(T...) if (T.length == 1)struct S { void bar() { } } final class FC { void foo(); } class C { void bar() { } final void foo(); } static assert(!isFinalFunction!(S.bar)); static assert( isFinalFunction!(FC.foo)); static assert(!isFinalFunction!(C.bar)); static assert( isFinalFunction!(C.foo));
isNestedFunction
(alias f);
isAbstractClass
(T...) if (T.length == 1)struct S { } class C { } abstract class AC { } static assert(!isAbstractClass!S); static assert(!isAbstractClass!C); static assert( isAbstractClass!AC);
isFinalClass
(T...) if (T.length == 1)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);
Unqual
(T)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));
CopyTypeQualifiers
(FromType, ToType)static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
CopyConstness
(FromType, ToType)const(int) i; CopyConstness!(typeof(i), float) f; assert( is(typeof(f) == const float)); CopyConstness!(char, uint) u; assert( is(typeof(u) == uint)); //Квалификатор 'shared' не будет скопирован assert(!is(CopyConstness!(shared bool, int) == shared int)); //Но константность будет assert( is(CopyConstness!(shared const real, double) == const double)); //Осторожный, const(int)[] - это изменяемый массив const(int) alias MutT = CopyConstness!(const(int)[], int); assert(!is(MutT == const(int))); //Хорошо, const(int[]) применяется к массиву и к содержащимся int alias CstT = CopyConstness!(const(int[]), int); assert( is(CstT == const(int)));
ForeachType
(T)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)));
OriginalType
(T)enum E : real { a } 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));
KeyType
(V : V[K], K)import std.traits; alias Hash = int[string]; static assert(is(KeyType!Hash == string)); static assert(is(ValueType!Hash == int)); KeyType!Hash str = "a"; // str объявлено как string ValueType!Hash num = 1; // num объявлено как int
ValueType
(V : V[K], K)import std.traits; alias Hash = int[string]; static assert(is(KeyType!Hash == string)); static assert(is(ValueType!Hash == int)); KeyType!Hash str = "a"; // str объявлено как string ValueType!Hash num = 1; // num объявлено как int
Unsigned
(T)Largest
(T...) if (T.length >= 1)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));
Signed
(T)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)); }
mostNegative
(T) if (isNumeric!T || isSomeChar!T || isBoolean!T)static assert(mostNegative!float == -float.max); static assert(mostNegative!double == -double.max); static assert(mostNegative!real == -real.max); static assert(mostNegative!bool == false);
foreach (T; TypeTuple!(bool, byte, short, int, long)) static assert(mostNegative!T == T.min); foreach (T; TypeTuple!(ubyte, ushort, uint, ulong, char, wchar, dchar)) static assert(mostNegative!T == 0);
mangledName
(sth...) if (sth.length == 1)mangledName
– тоже самое, что и встроенное свойство .mangleof, за исключением того, что получаются правильные названия функций-свойств.
module test; import std.traits : mangledName; class C { int value() @property; } pragma(msg, C.value.mangleof); // печатает "i" pragma(msg, mangledName!(C.value)); // печатает "_D4test1C5valueMFNdZi"
Select
(bool condition, T...) if (T.length == 2)// может выбирать типы 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))); // может выбирать идентификаторы int a = 1; int b = 2; alias selA = Select!(true, a, b); alias selB = Select!(false, a, b); assert(selA == 1); assert(selB == 2); // может выбирать выражения (времени компиляции) enum val = Select!(false, -4, 9 - 6); static assert(val == 3);
select
(bool cond : true, A, B)(A a
, lazy B b
);
select
(bool cond : false, A, B)(lazy A a
, B b
);
true
, возвращает a
без вычисления b
. В противном случае, возвращает b
без вычисления a
.hasUDA
(alias symbol, alias attribute);
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()));
getUDAs
(alias symbol, alias attribute)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);
getSymbolsByUDA
(alias symbol, alias attribute)enum Attr; static struct A { @Attr int a; int b; @Attr void doStuff() {} void doOtherStuff() {} static struct Inner { // не будет найдено в getSymbolsByUDA @Attr int c; } } // Находит как переменные, так и функции с атрибутом, // но не включает переменные и функции без него. static assert(getSymbolsByUDA!(A, Attr).length == 2); // Можно получить доступ к атрибутам в идентификаторах, возвращённых getSymbolsByUDA. static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr)); static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr)); static struct UDA { string name; } static struct B { @UDA("X") int x; @UDA("Y") int y; @(100) int z; } // Найти оба атрибута UDA. static assert(getSymbolsByUDA!(B, UDA).length == 2); // Найти один атрибут `100`. static assert(getSymbolsByUDA!(B, 100).length == 1); // Можно получить значение UDA из возвращаемого значения static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X"); @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"); static struct D { int x; } //Не находит ничего, если нет члена с заданным UDA static assert(getSymbolsByUDA!(D,UDA).length == 0);
allSameType
(T...)true
тогда и только тогда, когда все типы T одинаковые.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));
ifTestable
(T, alias pred = (a) => a);
true
тогда и только тогда, когда тип T можно тестировать в выражении if, то есть, если if (pred(T.init)) {} является компилируемым.isType
(X...) if (X.length == 1)isType
, X).
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!()));
isFunction
(X...) if (X.length == 1)static void func(){} static assert(isFunction!func); struct S { void func(){} } static assert(isFunction!(S.func));
isFinal
(X...) if (X.length == 1)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));
isCopyable
(S);
S | Проверяемый тип. |
struct S1 {} // Хорошо. Можно копировать struct S2 { this(this) {}} // Хорошо. Можно копировать struct S3 {@disable this(this) {}} // Не хорошо. Копирование запрещено struct S4 {S3 s;} // Не хорошо. Запрещено копирование поля 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);