Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.


Templates which extract information about types and symbols at compile time.
Category Templates
Symbol Name traits fullyQualifiedName moduleName packageName
Function traits isFunction arity functionAttributes hasFunctionAttributes functionLinkage FunctionTypeOf isSafe isUnsafe isFinal ParameterDefaults ParameterIdentifierTuple ParameterStorageClassTuple Parameters ReturnType SetFunctionAttributes variadicFunctionStyle
Aggregate Type traits BaseClassesTuple BaseTypeTuple classInstanceAlignment EnumMembers FieldNameTuple Fields hasAliasing hasElaborateAssign hasElaborateCopyConstructor hasElaborateDestructor hasIndirections hasMember hasNested hasUnsharedAliasing InterfacesTuple isInnerClass isNested MemberFunctionsTuple RepresentationTypeTuple TemplateArgsOf TemplateOf TransitiveBaseTypeTuple
Type Conversion CommonType ImplicitConversionTargets CopyTypeQualifiers CopyConstness isAssignable isCovariantWith isImplicitlyConvertible
SomethingTypeOf BooleanTypeOf IntegralTypeOf FloatingPointTypeOf NumericTypeOf UnsignedTypeOf SignedTypeOf CharTypeOf StaticArrayTypeOf DynamicArrayTypeOf ArrayTypeOf StringTypeOf AssocArrayTypeOf BuiltinTypeOf
Categories of types isType isAggregateType isArray isAssociativeArray isAutodecodableString isBasicType isBoolean isBuiltinType isCopyable isDynamicArray isFloatingPoint isIntegral isNarrowString isConvertibleToString isNumeric isPointer isScalarType isSigned isSomeChar isSomeString isStaticArray isUnsigned
Type behaviours isAbstractClass isAbstractFunction isCallable isDelegate isExpressions isFinalClass isFinalFunction isFunctionPointer isInstanceOf isIterable isMutable isSomeFunction isTypeTuple
General Types ForeachType KeyType Largest mostNegative OriginalType PointerTarget Signed Unqual Unsigned ValueType Promoted
Misc mangledName Select select
User-Defined Attributes hasUDA getUDAs getSymbolsByUDA
Walter Bright, Tomasz Stachowiak (isExpressions), Andrei Alexandrescu, Shin Fujishiro, Robert Clipsham, David Nadlinger, Kenji Hara, Shoichi Kato

Source: std/traits.d

template MutableOf(T)
Add specific qualifier to the given type T.
template InoutOf(T)
Add specific qualifier to the given type T.
template ConstOf(T)
template SharedOf(T)
template SharedInoutOf(T)
template SharedConstOf(T)
template ImmutableOf(T)
template packageName(alias T)
Get the full package name for the given symbol.
import std.traits;
static assert(packageName!packageName == "std");
template moduleName(alias T)
Get the module name (including package) for the given symbol.
import std.traits;
static assert(moduleName!moduleName == "std.traits");
template fullyQualifiedName(T...) if (T.length == 1)
Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string converter.


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)
Get the type of the return value from a function, a pointer to function, a delegate, a struct with an opCall, a pointer to a struct with an opCall, or a class with an opCall. Please note that ref is not part of a type, but the attribute of the function (see template functionAttributes).
int foo();
ReturnType!foo x;   // x is declared as int
template Parameters(func...) if (func.length == 1 && isCallable!func)
Get, as a tuple, the types of the parameters to a function, a pointer to function, a delegate, a struct with an opCall, a pointer to a struct with an opCall, or a class with an opCall.
int foo(int, long);
void bar(Parameters!foo);      // declares void bar(int, long);
void abc(Parameters!foo[1]);   // declares void abc(long);
alias ParameterTypeTuple = Parameters(func...) if (func.length == 1 && isCallable!func);
Alternate name for Parameters, kept for legacy compatibility.
template arity(alias func) if (isCallable!func && variadicFunctionStyle!func ==
Returns the number of arguments of function func. arity is undefined for variadic functions.
void foo(){}
static assert(arity!foo==0);
void bar(uint){}
static assert(arity!bar==1);
void variadicFoo(uint...){}
static assert(!__traits(compiles, arity!variadicFoo));
enum ParameterStorageClass: uint;

template ParameterStorageClassTuple(func...) if (func.length == 1 && isCallable!func)
Returns a tuple consisting of the storage classes of the parameters of a function func.
alias STC = ParameterStorageClass; // shorten the enum name

void func(ref int ctx, out real result, real param)
alias pstc = ParameterStorageClassTuple!func;
static assert(pstc.length == 3); // three parameters
static assert(pstc[0] == STC.ref_);
static assert(pstc[1] == STC.out_);
static assert(pstc[2] == STC.none);





These flags can be bitwise OR-ed together to represent complex storage class.
template ParameterIdentifierTuple(func...) if (func.length == 1 && isCallable!func)
Get, as a tuple, the identifiers of the parameters to a function symbol.
int foo(int num, string name, int);
static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
template ParameterDefaults(func...) if (func.length == 1 && isCallable!func)
Get, as a tuple, the default value of the parameters to a function symbol. If a parameter doesn't have the default value, void is returned instead.
int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0);
static assert(is(ParameterDefaults!foo[0] == void));
static assert(   ParameterDefaults!foo[1] == "hello");
static assert(   ParameterDefaults!foo[2] == [1,2,3]);
static assert(   ParameterDefaults!foo[3] == 0);
alias ParameterDefaultValueTuple = ParameterDefaults(func...) if (func.length == 1 && isCallable!func);
Alternate name for ParameterDefaults, kept for legacy compatibility.
enum FunctionAttribute: uint;

template functionAttributes(func...) if (func.length == 1 && isCallable!func)
Returns the FunctionAttribute mask for function func.
import std.traits : functionAttributes, FunctionAttribute;

alias FA = FunctionAttribute; // shorten the enum name

real func(real x) pure nothrow @safe
    return x;
static assert(functionAttributes!func & FA.pure_);
static assert(functionAttributes!func &;
static assert(!(functionAttributes!func & FA.trusted)); // not @trusted













These flags can be bitwise OR-ed together to represent a complex attribute.
template hasFunctionAttributes(args...) if (args.length > 0 && isCallable!(args[0]) && allSatisfy!(isSomeString, typeof(args[1..$])))
Checks whether a function has the given attributes attached.
args Function to check, followed by a variadic number of function attributes as strings
true, if the function has the list of attributes attached and false otherwise.
real func(real x) pure nothrow @safe;
static assert(hasFunctionAttributes!(func, "@safe", "pure"));
static assert(!hasFunctionAttributes!(func, "@trusted"));

// for templates attributes are automatically inferred
bool myFunc(T)(T b)
    return !b;
static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow"));
static assert(!hasFunctionAttributes!(myFunc!bool, "shared"));
template isSafe(alias func) if (isCallable!func)
true if func is @safe or @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 if func is @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)
Returns the calling convention of function as a string.
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");
enum Variadic: int;

template variadicFunctionStyle(func...) if (func.length == 1 && isCallable!func)
Determines what kind of variadic parameters function has.
void func() {}
static assert(variadicFunctionStyle!func ==;

extern(C) int printf(in char*, ...);
static assert(variadicFunctionStyle!printf == Variadic.c);
Function is not variadic.
Function is a C-style variadic function.
Function is a D-style variadic function, which uses
_argptr and _arguments.
Function is a typesafe variadic function.
template FunctionTypeOf(func...) if (func.length == 1 && isCallable!func)
Get the function type from a callable object func.
Using builtin typeof on a property function yields the types of the property value, not of the property function itself. Still, FunctionTypeOf is able to obtain function types of properties.

Note: 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))
Constructs a new function or delegate type with the same basic signature as the given one, but different attributes (including linkage).
This is especially useful for adding/removing attributes to/from types in generic code, where the actual type name cannot be spelt out.
T The base type.
linkage The desired linkage of the result type.
attrs The desired FunctionAttributes of the result type.
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))
Determines whether T is a class nested inside another class and that T.outer is the implicit reference to the outer class (i.e. outer has not been used as a field or method name)
T type to test
true if T is a class nested inside another, with the conditions described above; false otherwise
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))
Determines whether T has its own context pointer. T must be either class, struct, or union.
static struct S { }
static assert(!isNested!S);

int i;
struct NestedStruct { void f() { ++i; } }
static assert(isNested!NestedStruct);
template hasNested(T)
Determines whether T or any of its representation types have a context pointer.
static struct S { }

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

static assert(!hasNested!(S[2]));
static assert(hasNested!(NS[2]));
template Fields(T)
Get as a tuple the types of the fields of a struct, class, or union. This consists of the fields that take up memory space, excluding the hidden fields like the virtual function table pointer or a context pointer for nested types. If T isn't a struct, class, or union returns a tuple with one element T.
struct S { int x; float y; }
static assert(is(Fields!S == TypeTuple!(int, float)));
alias FieldTypeTuple = Fields(T);
Alternate name for Fields, kept for legacy compatibility.
template FieldNameTuple(T)
Get as an expression tuple the names of the fields of a struct, class, or union. This consists of the fields that take up memory space, excluding the hidden fields like the virtual function table pointer or a context pointer for nested types. If T isn't a struct, class, or union returns an expression tuple with an empty string.
struct S { int x; float y; }
static assert(FieldNameTuple!S == TypeTuple!("x", "y"));
static assert(FieldNameTuple!int == TypeTuple!"");
template RepresentationTypeTuple(T)
Get the primitive types of the fields of a struct or class, in topological order.
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...)
Returns true if and only if T's representation includes at least one of the following:
  1. a raw pointer U* and U is not immutable;
  2. an array U[] and U is not immutable;
  3. a reference to a class or interface type C and C is not immutable.
  4. an associative array that is not immutable.
  5. a delegate.
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)
Returns true if and only if T's representation includes at least one of the following:
  1. a raw pointer U*;
  2. an array U[];
  3. a reference to a class type C.
  4. an associative array.
  5. a delegate.
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...)
Returns true if and only if T's representation includes at least one of the following:
  1. a raw pointer U* and U is not immutable or shared;
  2. an array U[] and U is not immutable or shared;
  3. a reference to a class type C and C is not immutable or shared.
  4. an associative array that is not immutable or shared.
  5. a delegate that is not 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 if S or any type embedded directly in the representation of S defines an elaborate copy constructor. Elaborate copy constructors are introduced by defining this(this) for a struct.
Classes and unions never have elaborate copy constructors.
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 if S or any type directly embedded in the representation of S defines an elaborate assignment. Elaborate assignments are introduced by defining opAssign(typeof(this)) or opAssign(ref typeof(this)) for a struct or when there is a compiler-generated opAssign.
A type S gets compiler-generated opAssign in case it has an elaborate copy constructor or elaborate destructor.
Classes and unions never have elaborate assignments.

Note: Structs with (possibly nested) postblit operator(s) will have a hidden yet elaborate compiler generated assignment operator (unless explicitly disabled).

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 if S or any type directly embedded in the representation of S defines an elaborate destructor. Elaborate destructors are introduced by defining ~this() for a struct.
Classes and unions never have elaborate destructors, even though classes may define ~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);
Yields true if and only if T is an aggregate that defines a symbol called 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))
Retrieves the members of an enumerated type enum E.
E An enumerated type. E may have duplicated values.
Static tuple composed of the members of the enumerated type E. The members are arranged in the same order as declared in E.

Note: An enum can have multiple members which have the same value. If you want to use EnumMembers to e.g. generate switch cases at compile-time, you should use the std.typetuple.NoDuplicates template to avoid generating duplicate switch cases.

Note: Returned values are strictly typed with E. Thus, the following code does not work without the explicit cast:

enum E : int { a, b, c }
int[] abc = cast(int[]) [ EnumMembers!E ];
Cast is not necessary if the type of the variable is inferred. See the example below.

Example: Creating an array of enumerated values:

enum Sqrts : real
    one   = 1,
    two   = 1.41421,
    three = 1.73205,
auto sqrts = [ EnumMembers!Sqrts ];
assert(sqrts == [, Sqrts.two, Sqrts.three ]);
A generic function rank(v) in the following example uses this template for finding a member e in an enumerated type E.
// Returns i if e is the i-th enumerator of 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( ) == 0);
assert(rank(Mode.write) == 1);
assert(rank(  ) == 2);

template BaseTypeTuple(A)
Get a TypeTuple of the base class and base interfaces of this class or interface. BaseTypeTuple!Object returns the empty type tuple.
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))
Get a TypeTuple of all base classes of this class, in decreasing order. Interfaces are not included. BaseClassesTuple!Object yields the empty type tuple.
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)
Get a TypeTuple of all interfaces directly or indirectly inherited by this class or interface. Interfaces do not repeat if multiply implemented. InterfacesTuple!Object yields the empty type tuple.
template TransitiveBaseTypeTuple(T)
Get a TypeTuple of all base classes of T, in decreasing order, followed by T's interfaces. TransitiveBaseTypeTuple!Object yields the empty type tuple.
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))
Returns a tuple of non-static functions with the name name declared in the class or interface C. Covariant duplicates are shrunk into the most derived one.
interface I { I foo(); }
class B
    real foo(real v) { return v; }
class C : B, I
    override C foo() { return this; } // covariant overriding of
alias foos = MemberFunctionsTuple!(C, "foo");
static assert(foos.length == 2);
static assert(__traits(isSame, foos[0],;
static assert(__traits(isSame, foos[1],;
template TemplateOf(alias T : Base!Args, alias Base, Args...)

template TemplateOf(T : Base!Args, alias Base, Args...)
Returns an alias to the template that T is an instance of.
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...)
Returns a TypeTuple of the template arguments used to instantiate T.
struct Foo(T, U) {}
static assert(is(TemplateArgsOf!(Foo!(int, real)) == TypeTuple!(int, real)));
template classInstanceAlignment(T) if (is(T == class))
Returns class instance alignment.
class A { byte b; }
class B { long l; }

// As class instance always has a hidden pointer
static assert(classInstanceAlignment!A == (void*).alignof);
static assert(classInstanceAlignment!B == long.alignof);
template CommonType(T...)
Get the type that all types can be implicitly converted to. Useful e.g. in figuring out an array type from a bunch of initializing values. Returns void if passed an empty list, or if the types have no common type.
alias X = CommonType!(int, long, short);
assert(is(X == long));
alias Y = CommonType!(int, char[], short);
assert(is(Y == void));
template ImplicitConversionTargets(T)
Returns a tuple with all possible target types of an implicit conversion of a value of type T.
Important note:
The possible targets are computed more conservatively than the D 2.005 compiler does, eliminating all dangerous conversions. For example, ImplicitConversionTargets!double does not include float.
enum bool isImplicitlyConvertible(From, To);
Is From implicitly convertible to 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);
Returns true iff a value of type Rhs can be assigned to a variable of type Lhs.
isAssignable returns whether both an lvalue and rvalue can be assigned.
If you omit Rhs, isAssignable will check identity assignable of Lhs.
static assert( isAssignable!(long, int));
static assert(!isAssignable!(int, long));
static assert( isAssignable!(const(char)[], string));
static assert(!isAssignable!(string, char[]));

// int is assignable to int
static assert( isAssignable!int);

// immutable int is not assignable to immutable int
static assert(!isAssignable!(immutable int));
template isCovariantWith(F, G) if (is(F == function) && is(G == function))
Determines whether the function type F is covariant with G, i.e., functions of the type F can override ones of the type G.
interface I { I clone(); }
interface J { J clone(); }
class C : I
    override C clone()   // covariant overriding of I.clone()
        return new C;

// C.clone() can override I.clone(), indeed.
static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));

// C.clone() can't override J.clone(); the return type C is not implicitly
// convertible to J.
static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
@property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);

@property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
Creates an lvalue or rvalue of type T for typeof(...) and _traits(compiles, ...) purposes. No actual value is returned.

Note: Trying to use returned value will result in a "Symbol Undefined" error at link time.


// Note that `f` doesn't have to be implemented
// as is isn't called.
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; // error, no actual value is returned

enum bool isBoolean(T);
Detect whether T is a built-in boolean type.
static assert( isBoolean!bool);
enum EB : bool { a = true }
static assert( isBoolean!EB);
static assert(!isBoolean!(SubTypeOf!bool));
enum bool isIntegral(T);
Detect whether T is a built-in integral type. Types bool, char, wchar, and dchar are not considered integral.
enum bool isFloatingPoint(T);
Detect whether T is a built-in floating point type.
enum bool isNumeric(T);
Detect whether T is a built-in numeric type (integral or floating point).
enum bool isScalarType(T);
Detect whether T is a scalar type (a built-in numeric, character or boolean type).
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);
Detect whether T is a basic type (scalar type or void).
static assert(isBasicType!void);
static assert(isBasicType!(const(void)));
static assert(isBasicType!(shared(void)));
static assert(isBasicType!(immutable(void)));
static assert(isBasicType!(shared const(void)));
static assert(isBasicType!(shared inout(void)));
static assert(isBasicType!(shared inout const(void)));
static assert(isBasicType!(inout(void)));
static assert(isBasicType!(inout const(void)));
static assert(isBasicType!(immutable(int)));
static assert(isBasicType!(shared(float)));
static assert(isBasicType!(shared(const bool)));
static assert(isBasicType!(const(dchar)));
enum bool isUnsigned(T);
Detect whether T is a built-in unsigned numeric type.
enum bool isSigned(T);
Detect whether T is a built-in signed numeric type.
enum bool isSomeChar(T);
Detect whether T is one of the built-in character types.
The built-in char types are any of char, wchar or dchar, with or without qualifiers.
//Char types
static assert( isSomeChar!char);
static assert( isSomeChar!wchar);
static assert( isSomeChar!dchar);
static assert( isSomeChar!(typeof('c')));
static assert( isSomeChar!(immutable char));
static assert( isSomeChar!(const dchar));

//Non char types
static assert(!isSomeChar!int);
static assert(!isSomeChar!byte);
static assert(!isSomeChar!string);
static assert(!isSomeChar!wstring);
static assert(!isSomeChar!dstring);
static assert(!isSomeChar!(char[4]));
enum bool isSomeString(T);
Detect whether T is one of the built-in string types.
The built-in string types are Char[], where Char is any of char, wchar or dchar, with or without qualifiers.
Static arrays of characters (like char[80]) are not considered built-in string types.
//String types
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);

//Non string types
static assert(!isSomeString!int);
static assert(!isSomeString!(int[]));
static assert(!isSomeString!(byte[]));
static assert(!isSomeString!(typeof(null)));
static assert(!isSomeString!(char[4]));
enum bool isNarrowString(T);
Detect whether type T is a narrow string.
All arrays that use char, wchar, and their qualified versions are narrow strings. (Those include string and 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 auto isConvertibleToString(T);
Detect whether T is a struct, static array, or enum that is implicitly convertible to a string.
static struct AliasedString
    string s;
    alias s this;

enum StringEnum { a = "foo" }

enum bool isAutodecodableString(T);
Detect whether type T is a string that will be autodecoded.
All arrays that use char, wchar, and their qualified versions are narrow strings. (Those include string and wstring). Aggregates that implicitly cast to narrow strings are included.
T type to be tested
true if T represents a string that is subject to autodecoding
See Also: isNarrowString
static struct Stringish
    string s;
    alias s this;
enum bool isStaticArray(T);
Detect whether type T is a static array.
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);
Detect whether type T is a dynamic array.
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);
Detect whether type T is an array (static or dynamic; for associative arrays see 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);
Detect whether T is an associative array type
enum bool isBuiltinType(T);
Detect whether type T is a builtin type.
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);
Detect whether type T is a SIMD vector type.
enum bool isPointer(T);
Detect whether type T is a pointer.
template PointerTarget(T : T*)
Returns the target type of a pointer.
enum bool isAggregateType(T);
Detect whether type T is an aggregate type.
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);
Returns true if T can be iterated over using a foreach loop with a single loop variable of automatically inferred type, regardless of how the foreach loop is implemented. This includes ranges, structs/classes that define opApply with a single loop variable, and builtin dynamic, static and associative arrays.
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);
Returns true if T is not const or immutable. Note that isMutable is true for string, or immutable(char)[], because the 'head' is mutable.
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);
Returns true if T is an instance of the template 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...)
Check whether the tuple T is an expression tuple. An expression tuple only contains expressions.
See Also:
static assert(isExpressions!(1, 2.0, "a"));
static assert(!isExpressions!(int, double, string));
static assert(!isExpressions!(int, 2.0, "a"));
alias isExpressionTuple = isExpressions(T...);
Alternate name for isExpressions, kept for legacy compatibility.
template isTypeTuple(T...)
Check whether the tuple T is a type tuple. A type tuple only contains types.
See Also:
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)
Detect whether symbol or type T is a function pointer.
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)
Detect whether symbol or type T is a delegate.
static void sfunc() { }
int x;
void func() { x++; }

int delegate() dg;
assert(isDelegate!(int delegate()));

int function() fp;
assert(!isDelegate!(int function()));
template isSomeFunction(T...) if (T.length == 1)
Detect whether symbol or type T is a function, a function pointer or a delegate.
template isCallable(T...) if (T.length == 1)
Detect whether T is a callable object, which can be called with the function call operator (...).
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)
Detect whether T is a an abstract function.
template isFinalFunction(T...) if (T.length == 1)
Detect whether T is a a final function.
struct S { void bar() { } }
final class FC { void foo(); }
class C
    void bar() { }
    final void foo();
static assert(!isFinalFunction!(;
static assert( isFinalFunction!(;
static assert(!isFinalFunction!(;
static assert( isFinalFunction!(;
enum auto isNestedFunction(alias f);
Determines whether function f requires a context pointer.
template isAbstractClass(T...) if (T.length == 1)
Detect whether T is a an abstract class.
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)
Detect whether T is a a final class.
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)
Removes all qualifiers, if any, from type 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)
Copies type qualifiers from FromType to ToType.
Supported type qualifiers:
  • const
  • inout
  • immutable
  • shared
static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
template CopyConstness(FromType, ToType)
Returns the type of Target with the "constness" of Source. A type's refers to whether it is const, immutable, or inout. If source has no constness, the returned type will be the same as Target.
const(int) i;
CopyConstness!(typeof(i), float) f;
assert( is(typeof(f) == const float));

CopyConstness!(char, uint) u;
assert( is(typeof(u) == uint));

//The 'shared' qualifier will not be copied
assert(!is(CopyConstness!(shared bool, int) == shared int));

//But the constness will be
assert( is(CopyConstness!(shared const real, double) == const double));

//Careful, const(int)[] is a mutable array of const(int)
alias MutT = CopyConstness!(const(int)[], int);
assert(!is(MutT == const(int)));

//Okay, const(int[]) applies to array and contained ints
alias CstT = CopyConstness!(const(int[]), int);
assert( is(CstT == const(int)));
template ForeachType(T)
Returns the inferred type of the loop variable when a variable of type T is iterated over using a foreach loop with a single loop variable and automatically inferred return type. Note that this may not be the same as std.range.ElementType!Range in the case of narrow strings, or if T has both opApply and a range interface.
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)
Strips off all enums from type 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)
Get the Key type of an Associative Array.
import std.traits;
alias Hash = int[string];
static assert(is(KeyType!Hash == string));
static assert(is(ValueType!Hash == int));
KeyType!Hash str = "a"; // str is declared as string
ValueType!Hash num = 1; // num is declared as int
template ValueType(V : V[K], K)
Get the Value type of an Associative Array.
import std.traits;
alias Hash = int[string];
static assert(is(KeyType!Hash == string));
static assert(is(ValueType!Hash == int));
KeyType!Hash str = "a"; // str is declared as string
ValueType!Hash num = 1; // num is declared as int
template Unsigned(T)
Returns the corresponding unsigned type for T. T must be a numeric integral type, otherwise a compile-time error occurs.
template Largest(T...) if (T.length >= 1)
Returns the largest type, i.e. T such that T.sizeof is the largest. If more than one type is of the same size, the leftmost argument of these in will be returned.
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)
Returns the corresponding signed type for T. T must be a numeric integral type, otherwise a compile-time error occurs.
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)
Returns the most negative value of the numeric type 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 Promoted(T) if (isScalarType!T)
Get the type that a scalar type T will promote to in multi-term arithmetic expressions.
ubyte a = 3, b = 5;
static assert(is(typeof(a * b) == Promoted!ubyte));
static assert(is(Promoted!ubyte == int));

static assert(is(Promoted!(shared(bool)) == shared(int)));
static assert(is(Promoted!(const(int)) == const(int)));
static assert(is(Promoted!double == double));
template mangledName(sth...) if (sth.length == 1)
Returns the mangled name of symbol or type sth.
mangledName is the same as builtin .mangleof property, except that the correct names of property functions are obtained.
module test;
import std.traits : mangledName;

class C
    int value() @property;
pragma(msg, C.value.mangleof);      // prints "i"
pragma(msg, mangledName!(C.value)); // prints "_D4test1C5valueMFNdZi"
template Select(bool condition, T...) if (T.length == 2)
Aliases itself to T[0] if the boolean condition is true and to T[1] otherwise.
// can select types
static assert(is(Select!(true, int, long) == int));
static assert(is(Select!(false, int, long) == long));
static struct Foo {}
static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));

// can select symbols
int a = 1;
int b = 2;
alias selA = Select!(true, a, b);
alias selB = Select!(false, a, b);
assert(selA == 1);
assert(selB == 2);

// can select (compile-time) expressions
enum val = Select!(false, -4, 9 - 6);
static assert(val == 3);
A select(bool cond : true, A, B)(A a, lazy B b);

B select(bool cond : false, A, B)(lazy A a, B b);
If cond is true, returns a without evaluating b. Otherwise, returns b without evaluating a.
enum auto hasUDA(alias symbol, alias attribute);
Determine if a symbol has a given user-defined attribute.
See Also:
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)
Gets the matching user-defined attributes from the given symbol.
If the UDA is a type, then any UDAs of the same type on the symbol will match. If the UDA is a template for a type, then any UDA which is an instantiation of that template will match. And if the UDA is a value, then any UDAs on the symbol which are equal to that value will match.
See Also:
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)
Gets all symbols within symbol that have the given user-defined attribute. This is not recursive; it will not search for symbols within symbols such as nested structs or unions.
enum Attr;

static struct A
    @Attr int a;
    int b;
    @Attr void doStuff() {}
    void doOtherStuff() {}
    static struct Inner
        // Not found by getSymbolsByUDA
        @Attr int c;

// Finds both variables and functions with the attribute, but
// doesn't include the variables and functions without it.
static assert(getSymbolsByUDA!(A, Attr).length == 2);
// Can access attributes on the symbols returned by getSymbolsByUDA.
static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));

static struct UDA { string name; }

static struct B
    int x;
    int y;
    int z;

// Finds both UDA attributes.
static assert(getSymbolsByUDA!(B, UDA).length == 2);
// Finds one `100` attribute.
static assert(getSymbolsByUDA!(B, 100).length == 1);
// Can get the value of the UDA from the return value
static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");

static struct C
    int d;

// Also checks the symbol itself
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;

//Finds nothing if there is no member with specific UDA
static assert(getSymbolsByUDA!(D,UDA).length == 0);
template allSameType(T...)
true iff all types T are the same.
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 iff the type T can be tested in an if-expression, that is if if (pred(T.init)) {} is compilable.
template isType(X...) if (X.length == 1)
Detect whether X is a type. Analogous to is(X). This is useful when used in conjunction with other templates, e.g. allSatisfy!(isType, X).
true if X is a type, false otherwise
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)
Detect whether symbol or type X is a function. This is different that finding if a symbol is callable or satisfying is(X == function), it finds specifically if the symbol represents a normal function declaration, i.e. not a delegate or a function pointer.
true if X is a function, false otherwise
See Also:
Use isFunctionPointer or isDelegate for detecting those types respectively.
static void func(){}
static assert(isFunction!func);

struct S
    void func(){}
static assert(isFunction!(S.func));
template isFinal(X...) if (X.length == 1)
Detect whether X is a final method or class.
true if X is final, false otherwise
class C
    void nf() {}
    static void sf() {}
    final void ff() {}
final class FC { }

static assert(!isFinal!(C));
static assert( isFinal!(FC));

static assert(!isFinal!(;
static assert(!isFinal!(C.sf));
static assert( isFinal!(C.ff));
enum auto isCopyable(S);
Determines whether the type S can be copied. If a type cannot be copied, then code such as MyStruct x; auto y = x; will fail to compile. Copying for structs can be disabled by using @disable this(this).
S The type to check.
true if S can be copied. false otherwise.
struct S1 {}                        // Fine. Can be copied
struct S2 {         this(this) {}}  // Fine. Can be copied
struct S3 {@disable this(this) {}}  // Not fine. Copying is disabled.
struct S4 {S3 s;}                   // Not fine. A field has copying disabled.

class C1 {}

static assert( isCopyable!S1);
static assert( isCopyable!S2);
static assert(!isCopyable!S3);
static assert(!isCopyable!S4);

static assert(isCopyable!C1);
static assert(isCopyable!int);