std.traits

Шаблоны, которые извлекают информацию о типах и идентификаторах во время компиляции.
Category Templates
Признаки имён идентификаторов fullyQualifiedName moduleName packageName
Признаки функций isFunction arity functionAttributes functionLinkage FunctionTypeOf isSafe isUnsafe isFinal ParameterDefaults ParameterIdentifierTuple ParameterStorageClassTuple Parameters ReturnType SetFunctionAttributes variadicFunctionStyle
Признаки агрегатных типов BaseClassesTuple BaseTypeTuple classInstanceAlignment EnumMembers FieldNameTuple Fields hasAliasing hasElaborateAssign hasElaborateCopyConstructor hasElaborateDestructor hasIndirections hasMember hasNested hasUnsharedAliasing InterfacesTuple isInnerClass isNested MemberFunctionsTuple RepresentationTypeTuple TemplateArgsOf TemplateOf TransitiveBaseTypeTuple
Преобразования типов CommonType ImplicitConversionTargets CopyTypeQualifiers CopyConstness isAssignable isCovariantWith isImplicitlyConvertible
SomethingTypeOf BooleanTypeOf IntegralTypeOf FloatingPointTypeOf NumericTypeOf UnsignedTypeOf SignedTypeOf CharTypeOf StaticArrayTypeOf DynamicArrayTypeOf ArrayTypeOf StringTypeOf AssocArrayTypeOf BuiltinTypeOf
Категории типов isType isAggregateType isArray isAssociativeArray isAutodecodableString isBasicType isBoolean isBuiltinType isCopyable isDynamicArray isFloatingPoint isIntegral isNarrowString isNumeric isPointer isScalarType isSigned isSomeChar isSomeString isStaticArray isUnsigned
Тип поведения isAbstractClass isAbstractFunction isCallable isDelegate isExpressions isFinalClass isFinalFunction isFunctionPointer isInstanceOf isIterable isMutable isSomeFunction isTypeTuple
Общие типы ForeachType KeyType Largest mostNegative OriginalType PointerTarget Signed Unqual Unsigned ValueType
Разное mangledName Select select
Атрибуты, заданные пользователем hasUDA getUDAs getSymbolsByUDA
Лицензия:
Boost License 1.0.
Авторы:
Walter Bright, Tomasz Stachowiak (isExpressions), Andrei Alexandrescu, Shin Fujishiro, Robert Clipsham, David Nadlinger, Kenji Hara, Shoichi Kato

Исходный код: std/traits.d

template MutableOf(T)
Добавляет специфический квалификатор к данному типу T.
template InoutOf(T)
Добавляет специфический квалификатор к данному типу T.
template ConstOf(T)
то же самое.
template SharedOf(T)
то же самое.
template SharedInoutOf(T)
то же самое.
template SharedConstOf(T)
то же самое.
template ImmutableOf(T)
то же самое.
template packageName(alias T)
Получить полное имя пакета для данного идентификатора.
Примеры:
import std.traits;
static assert(packageName!packageName == "std");
template moduleName(alias T)
Получите имя модуля (включая пакет) для данного идентификатора.
Примеры:
import std.traits;
static assert(moduleName!moduleName == "std.traits");
template fullyQualifiedName(T...) if (T.length == 1)
Получить полное квалифицированное имя типа или идентификатора. Может действовать как интеллектуальный тип/идентификатор для преобразования в string.

Пример:

module myModule;
struct MyStruct {}
static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");

Примеры:
static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName");
template ReturnType(func...) if (func.length == 1 && isCallable!func)
Получить тип возвращаемого значения из функции, указателя на функцию, делегата, структуры с opCall, указателя на структуру с opCall, или класса с opCall. Пожалуйста, заметьте, что ref является не частью типа, а атрибутом функции (смотрите шаблон functionAttributes).
Примеры:
int foo();
ReturnType!foo x;   // x объявлен как int
template Parameters(func...) if (func.length == 1 && isCallable!func)
Получить, в виде кортежа, типы параметров, передаваемых в функцию, указатель на функцию, делегат, структуру с opCall, указатель на структуру с opCall, или класс с opCall.
Примеры:
int foo(int, long);
void bar(Parameters!foo);      // объявлена void bar(int, long);
void abc(Parameters!foo[1]);   // объявлена void abc(long);
alias ParameterTypeTuple = Parameters(func...) if (func.length == 1 && isCallable!func);
Альтернативное имя для Parameters, сохранено для обеспечения совместимости.
template arity(alias func) if (isCallable!func && variadicFunctionStyle!func == Variadic.no)
Возвращает количество аргументов функции func. 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));

Переместиться к: lazy_ · none · out_ · ref_ · return_ · scope_

enum ParameterStorageClass: uint;

template ParameterStorageClassTuple(func...) if (func.length == 1 && isCallable!func)
Возвращает кортеж, состоящий из классов памяти параметров функции func.
Примеры:
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_
Эти флаги могут объединяться вместе через побитовое ИЛИ, чтобы представлять сложный класс памяти.
template ParameterIdentifierTuple(func...) if (func.length == 1 && isCallable!func)
Получить, в виде кортежа, идентификаторы параметров функции.
Примеры:
int foo(int num, string name, int);
static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
template ParameterDefaults(func...) if (func.length == 1 && isCallable!func)
Получить, в виде кортежа, значение по умолчанию параметров функции. Если параметр не имеет значения по умолчанию, вместо него возвращается void.
Примеры:
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]);
alias ParameterDefaultValueTuple = ParameterDefaults(func...) if (func.length == 1 && isCallable!func);
Альтернативное имя для ParameterDefaults, сохранено для обеспечения совместимости.

Переместиться к: const_ · immutable_ · inout_ · nogc · none · nothrow_ · property · pure_ · ref_ · return_ · safe · shared_ · system · trusted

enum FunctionAttribute: uint;

template functionAttributes(func...) if (func.length == 1 && isCallable!func)
Возвращает атрибуты, присоединённые к функции 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_
Эти флаги могут объединяться вместе через побитовое ИЛИ, чтобы представлять сложный атрибут.
template 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);
enum auto 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);
template 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");

Переместиться к: c · d · no · typesafe

enum Variadic: int;

template variadicFunctionStyle(func...) if (func.length == 1 && isCallable!func)
Определяет, какого рода переменный список (variadic) параметров имеет функция.
Примеры:
void func() {}
static assert(variadicFunctionStyle!func == Variadic.no);

extern(C) int printf(in char*, ...);
static assert(variadicFunctionStyle!printf == Variadic.c);
no
У функции нет переменного списка параметров.
c
У функции переменный список в C-стиле.
d
У функции переменный список в D-стиле, здесь используются
_argptr и _arguments.
typesafe
У функции переменный список typesafe.
template FunctionTypeOf(func...) if (func.length == 1 && isCallable!func)
Получить тип функции у вызываемого объекта func.
Использование встроенного typeof на методах-свойствах (с @property) даст тип значения свойства, а не самого метода. Тем не менее, 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 ));
template SetFunctionAttributes(T, string linkage, uint attrs) if (isFunctionPointer!T || isDelegate!T)

template 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;
}
template isInnerClass(T) if (is(T == class))
Определяет, является ли T классом, вложенным в другой класс и, что T.outer – подразумевающаяся ссылка на внешний класс (то есть outer не используется как имя поля или метода)
Параметры:
T проверяемый тип
Возвращает:
true, если T – класс, вложенный в другой, с условиями, описанными выше; false в противном случае
Примеры:
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));
template isNested(T) if (is(T == class) || is(T == struct) || is(T == union))
Определяет, содержит ли T свой указатель на контекст. T должен быть классом, структурой или объединением.
Примеры:
static struct S { }
static assert(!isNested!S);

int i;
struct NestedStruct { void f() { ++i; } }
static assert(isNested!NestedStruct);
template hasNested(T)
Определяет, содержит ли T или любой из представляющих его типов указатель на контекст.
Примеры:
static struct S { }

int i;
struct NS { void f() { ++i; } }

static assert(!hasNested!(S[2]));
static assert(hasNested!(NS[2]));
template Fields(T)
Получить в виде кортежа типы полей структуры, класса, или объединения. Он будет состоять из полей, которые занимают пространство памяти, за исключением скрытых полей, таких как указатель на таблицу виртуальных функций или указатель на контекст для вложенных типов. Если T не является структурой, классом, или объединением, возвращает кортеж с одним элементом T.
Примеры:
struct S { int x; float y; }
static assert(is(Fields!S == TypeTuple!(int, float)));
alias FieldTypeTuple = Fields(T);
Альтернативное имя для Fields, сохранено для обеспечения совместимости.
template FieldNameTuple(T)
Получить в виде кортежа выражений имена полей структуры, класса, или объединения. Он будет состоять из полей, которые занимают пространство памяти, за исключением скрытых полей, таких как указатель на таблицу виртуальных функций или указатель на контекст для вложенных типов. Если T не является структурой, классом, или объединением, возвращает кортеж с пустой строкой.
Примеры:
struct S { int x; float y; }
static assert(FieldNameTuple!S == TypeTuple!("x", "y"));
static assert(FieldNameTuple!int == TypeTuple!"");
template 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*));
template hasAliasing(T...)
Возвращает true тогда и только тогда, когда представление T включает в себя по крайней мере одно из следующего:
  1. сырой указатель U*, и U не является immutable;
  2. массив U[], и U не является immutable;
  3. ссылка на класс или интерфейс типа C, и C не является immutable.
  4. ассоциативный массив, который не является immutable.
  5. делегат.
Примеры:
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);
template hasIndirections(T)
Возвращает true тогда и только тогда, когда представление T включает в себя по крайней мере одно из следующего:
  1. сырой указатель U*;
  2. массив U[];
  3. ссылка на класс типа C.
  4. ассоциативный массив.
  5. делегат.
Примеры:
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]));
template hasUnsharedAliasing(T...)
Возвращает true тогда и только тогда, когда представление T включает в себя по крайней мере одно из следующего:
  1. сырой указатель U*, и U не является immutable или shared;
  2. массив U[], и U не является immutable или shared;
  3. ссылка на класс типа C, и C не является immutable или shared;
  4. ассоциативный массив, который не является immutable или shared;
  5. делегат, который не является shared;
Примеры:
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);
template hasElaborateCopyConstructor(S)
True, если S или любой тип, встроенный непосредственно в представление S, определяет сложный (elaborate) конструктор копирования. Сложные конструкторы копирования вводятся путем определения this(this) для структуры.
Классы и объединения никогда не имеют сложных конструкторов копирования.
Примеры:
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);
template hasElaborateAssign(S)
True, если S или любой тип, встроенный непосредственно в представление S, определяет сложное (elaborate) присвоение. Сложные присвоения вводятся с определением opAssign(typeof(this)) или opAssign(ref typeof(this)) для структур, или когда присутсвует сгенерированный компилятором opAssign.
Тип S получает сгенерированный компилятором opAssign в случае, если он имеет сложный конструктор копирования или сложный деструктор.
Классы и объединения никогда не имеют сложных присвоений.

Замечание: Структура с (возможно вложенным) 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]));
template hasElaborateDestructor(S)
True, если S или любой тип, встроенный непосредственно в представление S, определяет сложный (elaborate) деструктор. Сложные деструкторы вводятся путём определения ~this() для структуры.
Классы и объединения никогда не имеют сложных деструкторов, хотя классы могут определять ~this().
Так это чего, любой деструктор в структуре сразу сложный что-ли? – вопрос пер.
Примеры:
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);
enum auto hasMember(T, string name);
Даёт истину тогда и только тогда, когда T – это агрегат, который определяет идентификатор с именем 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"));
template EnumMembers(E) if (is(E == enum))
Извлекает члены из типа перечисления enum E.
Параметры:
E Тип перечисления. E может иметь дублированные значения.
Возвращает:
Статический кортеж, сформированный из членов типа перечисления 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);

template BaseTypeTuple(A)
Получить TypeTuple (кортеж типов) базового класса и базовых интерфейсов этого класса или интерфейса. 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)));
template BaseClassesTuple(T) if (is(T == class))
Получить TypeTuple всех базовых классов этого класса, в нисходящем порядке. Интерфейсы не включаются. 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)));
template InterfacesTuple(T)
Получить TypeTuple всех интерфейсов непосредственно или косвенно унаследованных этим классом или интерфейсом. Интерфейсы не повторяются, если присутсвует множественная реализация. InterfacesTuple!Object даёт пустой кортеж типов.
template TransitiveBaseTypeTuple(T)
Получить TypeTuple всех всех базовых классов T, в нисходящем порядке, с последующими за ними интерфейсами 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);
template MemberFunctionsTuple(C, string name) if (is(C == class) || is(C == interface))
Возвращает кортеж не-статических функций с именем name объявленных в классе или интерфейсе C. Ковариантные дубликаты сжаты в самый производный.
Примеры:
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));
template TemplateOf(alias T : Base!Args, alias Base, Args...)

template TemplateOf(T : Base!Args, alias Base, Args...)
Возвращает псевдоним шаблона, для которого T является экземпляром.
Примеры:
struct Foo(T, U) {}
static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
template TemplateArgsOf(alias T : Base!Args, alias Base, Args...)

template TemplateArgsOf(T : Base!Args, alias Base, Args...)
Возвращает TypeTuple аргументов шаблона, используемых для создания экземпляра T.
Примеры:
struct Foo(T, U) {}
static assert(is(TemplateArgsOf!(Foo!(int, real)) == TypeTuple!(int, real)));
template 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);
template CommonType(T...)
Получить тип, к которому все типы могут косвенно преобразовываться. Полезно, например, чтобы выяснить тип массива исходя из связки значений инициализации. Возвращает void, если передан пустой список, или если типы не имеют общего типа.
Примеры:
alias X = CommonType!(int, long, short);
assert(is(X == long));
alias Y = CommonType!(int, char[], short);
assert(is(Y == void));
template ImplicitConversionTargets(T)
Возвращает кортеж со всеми возможными целевыми типами, к которым неявно преобразуется величина типа T.
Важное замечание:
Возможные цели вычисляются консервативнее, чем это делает компилятор D 2.005, устраняя все опасные преобразования. Например, ImplicitConversionTargets!double не включает float.
enum bool isImplicitlyConvertible(From, To);
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)[]));
enum auto 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));
template isCovariantWith(F, G) if (is(F == function) && is(G == function))
Определяет, является ли тип функции F ковариантным с G, то есть функции типа F могут пегружать функции типа G.
Примеры:
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)));
@property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);

@property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
Создает lvalue или rvalue типа T в целях typeof(...) и _traits(compiles, ...) Никакое действительное значение не возвращается.

Замечание: Попытка использовать возвращённое значение закончится ошибкой "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; // ошибка, никакое действительное значение не возвращается

enum bool isBoolean(T);
Определяет, является ли T встроенным логическим типом.
Примеры:
static assert( isBoolean!bool);
enum EB : bool { a = true }
static assert( isBoolean!EB);
static assert(!isBoolean!(SubTypeOf!bool));
enum bool isIntegral(T);
Определяет, является ли T встроенным целым типом. Типы bool, char, wchar, и dchar не считаются целыми.
enum bool isFloatingPoint(T);
Определяет, является ли T встроенным типом с плавающей точкой.
enum bool isNumeric(T);
Определяет, является ли T встроенным числовым типом (целым или с плавающей точкой).
enum bool isScalarType(T);
Определяет, является ли 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)));
enum bool isBasicType(T);
Определяет, является ли T базовым типом (скалярным типом или void).
Примеры:
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)));
enum bool isUnsigned(T);
Определяет, является ли T встроенным беззнаковым числовым типом.
enum bool isSigned(T);
Определяет, является ли T встроенным знаковым числовым типом.
enum bool isSomeChar(T);
Определяет, является ли T одним из встроенных символьных типов.
Встроенные символьные типы – любой из char, wchar или dchar, с квалификатором или без него.
Примеры:
//Символьные типы
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]));
enum bool isSomeString(T);
Определяет, является ли T одним из встроенных строковых типов.
Встроенные строковые типы – это Char[], где Char – это любой из char, wchar или dchar, с квалификатором или без него.
Статические массивы символов (вроде char[80]) не считаются встроенными строковыми типами.
Примеры:
//Строковые типы
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]));
enum bool isNarrowString(T);
Определяет, является ли T узкой строкой.
Все массивы, которые используют char, wchar и их квалифицированные версии являются узкими строками. (К их числу относятся string и wstring).
Примеры:
static assert(isNarrowString!string);
static assert(isNarrowString!wstring);
static assert(isNarrowString!(char[]));
static assert(isNarrowString!(wchar[]));

static assert(!isNarrowString!dstring);
static assert(!isNarrowString!(dchar[]));
enum bool isAutodecodableString(T);
Определяет, является ли тип T строкой, которая будет автоматически декодирована.
Все массивы, которые используют char, wchar, и их квалифицированные версии являются узкими строками. (К их числу относятся string и wstring). Агрегаты, которые неявно преобразуются к узким строкам, включены.
Параметры:
T тестируемый тип
Возвращает:
true, если T представляет строку, подлежащую автоматическому декодированию
Смотрите также: isNarrowString
Примеры:
static struct Stringish
{
    string s;
    alias s this;
}
assert(isAutodecodableString!wstring);
assert(isAutodecodableString!Stringish);
assert(!isAutodecodableString!dstring);
enum bool isStaticArray(T);
Определяет, является ли тип 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);
enum bool isDynamicArray(T);
Определяет, является ли тип T динамическим массивом.
Примеры:
static assert( isDynamicArray!(int[]));
static assert( isDynamicArray!(string));
static assert( isDynamicArray!(long[3][]));

static assert(!isDynamicArray!(int[5]));
static assert(!isDynamicArray!(typeof(null)));
enum bool isArray(T);
Определяет, является ли тип T массивом (статическим или динамическим; по поводу ассоциативных массивов смотрите isAssociativeArray).
Примеры:
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)));
enum bool isAssociativeArray(T);
Определяет, является ли T типом ассоциативного массива.
enum bool isBuiltinType(T);
Определяет, является ли тип 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)));
enum bool isSIMDVector(T);
Определяет, является ли тип T типом SIMD-вектора.
enum bool isPointer(T);
Определяет, является ли тип T указателем.
template PointerTarget(T : T*)
Возвращает целевой тип указателя.
enum bool isAggregateType(T);
Определяет, является ли тип 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)));
enum bool 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);
enum bool 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));
enum bool isInstanceOf(alias S, T);

enum auto 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));
template isExpressions(T...)
Проверяет, является ли кортеж T кортежем выражений. Кортеж выражений содержит только выражения.
Смотрите также:
Примеры:
static assert(isExpressions!(1, 2.0, "a"));
static assert(!isExpressions!(int, double, string));
static assert(!isExpressions!(int, 2.0, "a"));
alias isExpressionTuple = isExpressions(T...);
Альтернативное имя для isExpressions, сохранено для обеспечения совместимости.
template isTypeTuple(T...)
Проверяет, является ли кортеж T кортежем типов. Кортеж типов содержит только типы.
Смотрите также:
Примеры:
static assert(isTypeTuple!(int, float, string));
static assert(!isTypeTuple!(1, 2.0, "a"));
static assert(!isTypeTuple!(1, double, string));
template isFunctionPointer(T...) if (T.length == 1)
Определяет, является ли идентификатор или тип T указателем на функцию.
Примеры:
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) {}));
template isDelegate(T...) if (T.length == 1)
Определяет, является ли идентификатор или тип T делегатом.
Примеры:
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)));
template isSomeFunction(T...) if (T.length == 1)
Определяет, является ли идентификатор или тип T функцией, указателем на функцию, или делегатом.
template isCallable(T...) if (T.length == 1)
Определяет, является ли T вызываемым объектом, который можно вызвать с помощью оператора вызова функции (...).
Примеры:
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);
template isAbstractFunction(T...) if (T.length == 1)
Определяет, является ли T абстрактной функцией.
template isFinalFunction(T...) if (T.length == 1)
Определяет, является ли T финальной функцией.
Примеры:
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));
enum auto isNestedFunction(alias f);
Определяет, требуется ли функции f указатель контекста.
template isAbstractClass(T...) if (T.length == 1)
Выясняет, является ли T абстрактным классом.
Примеры:
struct S { }
class C { }
abstract class AC { }
static assert(!isAbstractClass!S);
static assert(!isAbstractClass!C);
static assert( isAbstractClass!AC);
template isFinalClass(T...) if (T.length == 1)
Выясняет, является ли T финальным классом.
Примеры:
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);
template Unqual(T)
Удаляет все квалификаторы, если имеются, из типа 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));
template CopyTypeQualifiers(FromType, ToType)
Копирует квалификаторы от типа FromType к типу ToType.
Поддерживаемые типы квалификаторов:
  • const
  • inout
  • immutable
  • shared
Примеры:
static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
template CopyConstness(FromType, ToType)
Возвращает тип ToType с "константностью" типа FromType. Это может быть const, immutable, или inout. Если 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)));
template ForeachType(T)
Возвращает распознанный тип переменной цикла, когда переменная типа T итерируется с помощью цикла foreach с единственной переменной цикла и автоматически выводит тип возвращаемого значения. Заметьте, что это может не совпадать с std.range.ElementType!Range в случае узких строк, или если T имеет как метод opApply, так и интерфейс диапазона.
Примеры:
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)));
template OriginalType(T)
Удаляет все enum из типа 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));
template 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
template 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
template Unsigned(T)
Возвращает соответствующий беззнаковый тип для T. T должно быть числовым целым типом, в противном случае произойдёт ошибка времени компиляции.
template Largest(T...) if (T.length >= 1)
Возвращает наибольший тип, то есть такой T, что T.sizeof - самый большой. Если присутствует больше одного типа того же самого размера, возвращается самый левый аргумент из них.
Примеры:
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));
template Signed(T)
Возвращает соответствующий знаковый тип для T. 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));
}
template mostNegative(T) if (isNumeric!T || isSomeChar!T || isBoolean!T)
Возвращает наибольшее отрицательное значение числового типа 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);
template mangledName(sth...) if (sth.length == 1)
Возвращает mangled-имя идентификатора или типа sth.
"mangled" переводится как "искорёженный", это те имена, которые появляются в ошибках компоновщика – прим.пер.
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"
template Select(bool condition, T...) if (T.length == 2)
Создаёт псевдоним на T[0], если логическое условие condition истинно, и на T[1] в противном случае.
Примеры:
// может выбирать типы
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);
A select(bool cond : true, A, B)(A a, lazy B b);

B select(bool cond : false, A, B)(lazy A a, B b);
Если cond равно true, возвращает a без вычисления b. В противном случае, возвращает b без вычисления a.
enum auto hasUDA(alias symbol, alias attribute);
Определяет, имеет ли symbol данный определённый пользователем атрибут.
Смотрите также:
Примеры:
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()));
template getUDAs(alias symbol, alias attribute)
Получает соответствующие определённые пользователем атрибуты из данного symbol.
Если UDA – это тип, тогда любое UDA этого типа в symbol, будет соответствовать. Если UDA – это шаблон для типа, тогда любое UDA, которое является экземпляром этого шаблона, будет соответствовать. И если UDA – это значение, тогда любое UDA в symbol, которое равняется этой величине, будет соответствовать.
Смотрите также:
Примеры:
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);
template getSymbolsByUDA(alias symbol, alias attribute)
Получает все идентификаторы в пределах symbol, которые имеют данный определённый пользователем атрибут. Это не рекурсивно; не ведётся поиск идентификаторов внутри идентификаторов, например, во вложенных структурах или объединениях.
Примеры:
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);
template 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));
enum auto ifTestable(T, alias pred = (a) => a);
Возвращает:
true тогда и только тогда, когда тип T можно тестировать в выражении if, то есть, если if (pred(T.init)) {} является компилируемым.
template isType(X...) if (X.length == 1)
Проверяет, является ли X типом. Аналогично is(X). Это полезно, когда используется в связке с другими шаблонами, например, allSatisfy!(isType, X).
Возвращает:
true, если X – это тип, false в противном случае.
Примеры:
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!()));
template isFunction(X...) if (X.length == 1)
Проверяет, является ли идентификатор или тип X функцией. Это отличается от нахождения, является ли идентификатор вызываемым или удовлетворяющим is(X == function), он находит именно те случаи, когда идентификатор представляет нормально объявленную функцию, то есть не делегат, и не указатель на функцию.
Возвращает:
true, если X – это функция, false в противном случае.
Смотрите также:
Использование isFunctionPointer или isDelegate для определения этих типов соответственно.
Примеры:
static void func(){}
static assert(isFunction!func);

struct S
{
    void func(){}
}
static assert(isFunction!(S.func));
template isFinal(X...) if (X.length == 1)
Проверяет, является ли X финальным методом или классом.
Возвращает:
true, если X объявлено как final, false в противном случае.
Примеры:
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));
enum auto isCopyable(S);
Определяет, может ли тип S быть скопирован. Если тип не может быть скопирован, тогда такой код как, например, MyStruct x; auto y = x; не будет скомпилирован. Копирование для структур может быть отключено использованием @disable this(this).
Параметры:
S Проверяемый тип.
Возвращает:
true, если S может быть скопирован. false в противном случае.
Примеры:
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);