std.traits - D Programming Language
Description: D Programming Language
Keywords: D programming language

Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Discord (community-run)
  - Forums
  - IRC
  - Wiki
  - Issues
  - Contributing
  - Contributors
  - Foundation
  - Security Team
  - Store
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a GitHub 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.

# std.traits

Templates which extract information about types and symbols at compile time.

Category | Templates
--- | ---
Symbol Name traits | fullyQualifiedName mangledName 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 hasElaborateMove hasIndirections hasMember hasStaticMember hasNested hasUnsharedAliasing InterfacesTuple isInnerClass isNested MemberFunctionsTuple RepresentationTypeTuple TemplateArgsOf TemplateOf TransitiveBaseTypeTuple
Type Conversion | CommonType AllImplicitConversionTargets ImplicitConversionTargets CopyTypeQualifiers CopyConstness isAssignable isCovariantWith isImplicitlyConvertible isQualifierConvertible
Type Constructors | InoutOf ConstOf SharedOf SharedInoutOf SharedConstOf SharedConstInoutOf ImmutableOf QualifierOf
Categories of types | allSameType ifTestable isType isAggregateType isArray isAssociativeArray isAutodecodableString isBasicType isBoolean isBuiltinType isCopyable isDynamicArray isEqualityComparable isFloatingPoint isIntegral isNarrowString isConvertibleToString isNumeric isOrderingComparable isPointer isScalarType isSigned isSIMDVector 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 Unconst Unshared Unqual Unsigned ValueType Promoted
Misc | lvalueOf rvalueOf Select select
User-Defined Attributes | hasUDA getUDAs getSymbolsByUDA

License:
Boost License 1.0.
Authors:
Walter Bright, Tomasz Stachowiak (isExpressions), Andrei Alexandrescu, Shin Fujishiro, Robert Clipsham, David Nadlinger, Kenji Hara, Shoichi Kato

Source std/traits.d

template `InoutOf`(T)
  Parameters:

  T | The type to qualify

  Returns:
  T with the inout qualifier added.
  Examples:

      static assert(is(InoutOf!(int) == inout int));
      static assert(is(InoutOf!(inout int) == inout int));
      static assert(is(InoutOf!(const int) == inout const int));
      static assert(is(InoutOf!(shared int) == inout shared int));

template `ConstOf`(T)
  Parameters:

  T | The type to qualify

  Returns:
  T with the const qualifier added.
  Examples:

      static assert(is(ConstOf!(int) == const int));
      static assert(is(ConstOf!(const int) == const int));
      static assert(is(ConstOf!(inout int) == const inout int));
      static assert(is(ConstOf!(shared int) == const shared int));

template `SharedOf`(T)
  Parameters:

  T | The type to qualify

  Returns:
  T with the shared qualifier added.
  Examples:

      static assert(is(SharedOf!(int) == shared int));
      static assert(is(SharedOf!(shared int) == shared int));
      static assert(is(SharedOf!(inout int) == shared inout int));
      static assert(is(SharedOf!(immutable int) == shared immutable int));

template `SharedInoutOf`(T)
  Parameters:

  T | The type to qualify

  Returns:
  T with the inout and shared qualifiers added.
  Examples:

      static assert(is(SharedInoutOf!(int) == shared inout int));
      static assert(is(SharedInoutOf!(int) == inout shared int));

      static assert(is(SharedInoutOf!(const int) == shared inout const int));
      static assert(is(SharedInoutOf!(immutable int) == shared inout immutable int));

template `SharedConstOf`(T)
  Parameters:

  T | The type to qualify

  Returns:
  T with the const and shared qualifiers added.
  Examples:

      static assert(is(SharedConstOf!(int) == shared const int));
      static assert(is(SharedConstOf!(int) == const shared int));

      static assert(is(SharedConstOf!(inout int) == shared inout const int));
      // immutable variables are implicitly shared and const
      static assert(is(SharedConstOf!(immutable int) == immutable int));

template `SharedConstInoutOf`(T)
  Parameters:

  T | The type to qualify

  Returns:
  T with the const, shared, and inout qualifiers added.
  Examples:

      static assert(is(SharedConstInoutOf!(int) == shared const inout int));
      static assert(is(SharedConstInoutOf!(int) == const shared inout int));
      static assert(is(SharedConstInoutOf!(inout int) == shared inout const int));
      // immutable variables are implicitly shared and const
      static assert(is(SharedConstInoutOf!(immutable int) == immutable int));

template `ImmutableOf`(T)
  Parameters:

  T | The type to qualify

  Returns:
  T with the immutable qualifier added.
  Examples:

      static assert(is(ImmutableOf!(int) == immutable int));
      static assert(is(ImmutableOf!(const int) == immutable int));
      static assert(is(ImmutableOf!(inout int) == immutable int));
      static assert(is(ImmutableOf!(shared int) == immutable int));

template `QualifierOf`(T)
  Gives a template that can be used to apply the same attributes that are on the given type T. E.g. passing inout shared int will return SharedInoutOf.
  Parameters:

  T | the type to check qualifiers from

  Returns:
  The qualifier template from the given type T
  Examples:

      static assert(__traits(isSame, QualifierOf!(shared const inout int), SharedConstInoutOf));
      static assert(__traits(isSame, QualifierOf!(immutable int), ImmutableOf));
      static assert(__traits(isSame, QualifierOf!(shared int), SharedOf));
      static assert(__traits(isSame, QualifierOf!(shared inout int), SharedInoutOf));
      import std.meta : Alias;
      static assert(__traits(isSame, QualifierOf!(int), Alias));

template `packageName`(alias T)
  Get the full package name for the given symbol.
  Examples:

      static assert(packageName!packageName == "std");

  Examples:

      static assert(packageName!moduleName == "std");

template `moduleName`(alias T)
  Get the module name (including package) for the given symbol.
  Examples:

      static assert(moduleName!moduleName == "std.traits");

enum auto `fullyQualifiedName`(T);
enum auto `fullyQualifiedName`(alias T);
  Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string converter.

  Example

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

  Examples:

      static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName");

template `ReturnType`(alias func)
if (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).
  Note: To reduce template instantiations, consider instead using typeof(() { return func(args); } ()) if the argument types are known or static if (is(typeof(func) Ret == return)) if only that basic test is needed.
  Examples:

      int foo();
      ReturnType!foo x;   // x is declared as int

template `Parameters`(alias func)
if (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.
  Examples:

      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(alias func) if (isCallable!func);
  Alternate name for Parameters, kept for legacy compatibility.
template `arity`(alias func)
if (isCallable!func && (variadicFunctionStyle!func == Variadic.no))
  Returns the number of arguments of function func. arity is undefined for variadic functions.
  Examples:

      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`(alias func)
if (isCallable!func)
  Get a tuple of the storage classes of a function's parameters.
  Parameters:

  func | function symbol or type of function, delegate, or pointer to function

  Returns:
  A tuple of ParameterStorageClass bits
  Examples:

      alias STC = ParameterStorageClass; // shorten the enum name

      void func(ref int ctx, out real result, in real param, void* ptr)
      {
      }
      alias pstc = ParameterStorageClassTuple!func;
      static assert(pstc.length == 4); // number of parameters
      static assert(pstc[0] == STC.ref_);
      static assert(pstc[1] == STC.out_);
      static assert(pstc[2] == STC.in_);
      static assert(pstc[3] == STC.none);

  `none`
  `in_`
  `ref_`
  `out_`
  `lazy_`
  `scope_`
  `return_`
    These flags can be bitwise OR-ed together to represent complex storage class.
enum ParameterStorageClass `extractParameterStorageClassFlags`(Attribs...);
  Convert the result of __traits(getParameterStorageClasses) to ParameterStorageClass enums.
  Parameters:

  Attribs | The return value of __traits(getParameterStorageClasses)

  Returns:
  The bitwise OR of the equivalent ParameterStorageClass enums.
  Examples:

      static void func(ref int ctx, out real result);

      enum param1 = extractParameterStorageClassFlags!(
          __traits(getParameterStorageClasses, func, 0)
      );
      static assert(param1 == ParameterStorageClass.ref_);

      enum param2 = extractParameterStorageClassFlags!(
          __traits(getParameterStorageClasses, func, 1)
      );
      static assert(param2 == ParameterStorageClass.out_);

      enum param3 = extractParameterStorageClassFlags!(
          __traits(getParameterStorageClasses, func, 0),
          __traits(getParameterStorageClasses, func, 1)
      );
      static assert(param3 == (ParameterStorageClass.ref_ | ParameterStorageClass.out_));

template `ParameterIdentifierTuple`(alias func)
if (isCallable!func)
  Get, as a tuple, the identifiers of the parameters to a function symbol.
  Examples:

      int foo(int num, string name, int);
      static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);

template `ParameterDefaults`(alias func)
if (isCallable!func)
  Get, as a tuple, the default values of the parameters to a function symbol. If a parameter doesn't have the default value, void is returned instead.
  Examples:

      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(alias func) if (isCallable!func);
  Alternate name for ParameterDefaults, kept for legacy compatibility.
enum `FunctionAttribute`: uint;
template `functionAttributes`(alias func)
if (isCallable!func)
  Returns the FunctionAttribute mask for function func.
  See Also:
  hasFunctionAttributes
  Examples:

      alias FA = FunctionAttribute; // shorten the enum name

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

  `none`
  `pure_`
  `nothrow_`
  `ref_`
  `property`
  `trusted`
  `safe`
  `nogc`
  `system`
  `const_`
  `immutable_`
  `inout_`
  `shared_`
  `return_`
  `scope_`
  `live`
    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.
  Parameters:

  args | Function to check, followed by a variadic number of function attributes as strings

  Returns:
  true, if the function has the list of attributes attached and false otherwise.
  See Also:
  functionAttributes
  Examples:

      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.
  Examples:

      @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.
  Examples:

      @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`(alias func)
if (isCallable!func)
  Determine the linkage attribute of the function.
  Parameters:

  func | the function symbol, or the type of a function, delegate, or pointer to function

  Returns:
  one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System".
  Examples:

      extern(D) void Dfunc() {}
      extern(C) void Cfunc() {}
      static assert(functionLinkage!Dfunc == "D");
      static assert(functionLinkage!Cfunc == "C");

      string a = functionLinkage!Dfunc;
      writeln(a); // "D"

      auto fp = &Cfunc;
      string b = functionLinkage!fp;
      writeln(b); // "C"

enum `Variadic`: int;
template `variadicFunctionStyle`(alias func)
if (isCallable!func)
  Determines what kind of variadic parameters function has.
  Parameters:

  func | function symbol or type of function, delegate, or pointer to function

  Returns:
  enum Variadic
  Examples:

      void func() {}
      static assert(variadicFunctionStyle!func == Variadic.no);

      extern(C) int printf(const char*, ...);
      static assert(variadicFunctionStyle!printf == Variadic.c);

  `no`
    Function is not variadic.
  `c`
    Function is a C-style variadic function, which uses core.stdc.stdarg
  `d`
    Function is a D-style variadic function, which uses __argptr and __arguments.
  `typesafe`
    Function is a typesafe variadic function.
template `FunctionTypeOf`(alias func)
if (isCallable!func)
  Get the function type from a callable object func, or from a function pointer/delegate type.
  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.

  Examples:

      class C
      {
          int value() @property => 0;
          static string opCall() => "hi";
      }
      static assert(is( typeof(C.value) == int ));
      static assert(is( FunctionTypeOf!(C.value) == function ));
      static assert(is( FunctionTypeOf!C == typeof(C.opCall) ));

      int function() fp;
      alias IntFn = int();
      static assert(is( typeof(fp) == IntFn* ));
      static assert(is( FunctionTypeOf!fp == IntFn ));

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.
  Parameters:

  T | The base type.
  linkage | The desired linkage of the result type.
  attrs | The desired FunctionAttributes of the result type.

  Examples:

      alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T);

      auto assumePure(T)(T t)
      if (isFunctionPointer!T || isDelegate!T)
      {
          enum attrs = functionAttributes!T | FunctionAttribute.pure_;
          return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t;
      }

      int f()
      {
          import core.thread : getpid;
          return getpid();
      }

      int g() pure @trusted
      {
          auto pureF = assumePure(&f);
          return pureF();
      }
      assert(g() > 0);

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)
  Parameters:

  T | type to test

  Returns:
  true if T is a class nested inside another, with the conditions described above; false otherwise
  Examples:

      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.
  See also: __traits(`isNested`, T)
  Examples:

      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.
  Examples:

      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, interface or union returns a tuple with one element T.
  History:
  - Returned AliasSeq!(Interface) for interfaces prior to 2.097
  Examples:

      import std.meta : AliasSeq;
      struct S { int x; float y; }
      static assert(is(Fields!S == AliasSeq!(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. Inherited fields (for classes) are not included. If T isn't a struct, class, interface or union, an expression tuple with an empty string is returned.
  History:
  - Returned AliasSeq!"" for interfaces prior to 2.097
  Examples:

      import std.meta : AliasSeq;
      struct S { int x; float y; }
      static assert(FieldNameTuple!S == AliasSeq!("x", "y"));
      static assert(FieldNameTuple!int == AliasSeq!"");

template `RepresentationTypeTuple`(T)
  Get the primitive types of the fields of a struct or class, in topological order.
  Examples:

      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*));

enum auto `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.
  Examples:

      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;
  6. a `context pointer`.
  Examples:

      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]));

enum auto `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.
  Examples:

      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.
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 if it has an 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).

  Examples:

      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]));

enum auto `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().

  Note This just wraps __traits(needsDestruction, S).

  Examples:

      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);

template `hasElaborateMove`(S)
  True if S or any type embedded directly in the representation of S defines elaborate move semantics. Elaborate move semantics are introduced by defining opPostMove(ref typeof(this)) for a struct.
  Classes and unions never have elaborate move semantics.
enum auto `hasMember`(T, string name);
  Yields true if and only if T is an aggregate that defines a symbol called name.
  See also: __traits(`hasMember`, T, name)
  Examples:

      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 `hasStaticMember`(T, string member)
  Whether the symbol represented by the string, member, exists and is a static member of T.
  Parameters:

  T | Type containing symbol member.
  member | Name of symbol to test that resides in T.

  Returns:
  true iff member exists and is static.
  Examples:

      static struct S
      {
          static void sf() {}
          void f() {}

          static int si;
          int i;
      }

      static assert( hasStaticMember!(S, "sf"));
      static assert(!hasStaticMember!(S, "f"));

      static assert( hasStaticMember!(S, "si"));
      static assert(!hasStaticMember!(S, "i"));

      static assert(!hasStaticMember!(S, "hello"));

template `EnumMembers`(E)
if (is(E == enum))
  Retrieves the members of an enumerated type enum E.
  Parameters:

  E | An enumerated type. E may have duplicated values.

  Returns:
  Static tuple composed of the members of the enumerated type E. The members are arranged in the same order as declared in E. The name of the enum can be found by querying the compiler for the name of the identifier, i.e. __traits(identifier, `EnumMembers`!MyEnum[i]). For enumerations with unique values, std.conv.to can also be used.

  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.meta.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.
  Examples:
  Create an array of enumerated values

      enum Sqrts : real
      {
          one = 1,
          two = 1.41421,
          three = 1.73205
      }
      auto sqrts = [EnumMembers!Sqrts];
      writeln(sqrts); // [Sqrts.one, Sqrts.two, Sqrts.three]

  Examples:
  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.
      static size_t rank(E)(E e)
      if (is(E == enum))
      {
          static foreach (i, member; EnumMembers!E)
          {
              if (e == member)
                  return i;
          }
          assert(0, "Not an enum member");
      }

      enum Mode
      {
          read = 1,
          write = 2,
          map = 4
      }
      writeln(rank(Mode.read)); // 0
      writeln(rank(Mode.write)); // 1
      writeln(rank(Mode.map)); // 2

  Examples:
  Use EnumMembers to generate a switch statement using static foreach.

      import std.conv : to;
      class FooClass
      {
          string calledMethod;
          void foo() @safe { calledMethod = "foo"; }
          void bar() @safe { calledMethod = "bar"; }
          void baz() @safe { calledMethod = "baz"; }
      }

      enum FooEnum { foo, bar, baz }

      auto var = FooEnum.bar;
      auto fooObj = new FooClass();
      s: final switch (var)
      {
          static foreach (member; EnumMembers!FooEnum)
          {
              case member: // Generate a case for each enum value.
                  // Call fooObj.{name of enum value}().
                  __traits(getMember, fooObj, to!string(member))();
                  break s;
          }
      }
      // As we pass in FooEnum.bar, the bar() method gets called.
      writeln(fooObj.calledMethod); // "bar"

template `BaseTypeTuple`(A)
  Get a AliasSeq of the base class and base interfaces of this class or interface. BaseTypeTuple!Object returns the empty type tuple.
  Examples:

      import std.meta : AliasSeq;

      interface I1 { }
      interface I2 { }
      interface I12 : I1, I2 { }
      static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2)));

      interface I3 : I1 { }
      interface I123 : I1, I2, I3 { }
      static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3)));

template `BaseClassesTuple`(T)
if (is(T == class))
  Get a AliasSeq of all base classes of this class, in decreasing order. Interfaces are not included. BaseClassesTuple!Object yields the empty type tuple.
  Examples:

      import std.meta : AliasSeq;

      class C1 { }
      class C2 : C1 { }
      class C3 : C2 { }
      static assert(!BaseClassesTuple!Object.length);
      static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object)));
      static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object)));
      static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object)));

template `InterfacesTuple`(T)
  Parameters:

  T | The class or interface to search.

  Returns:
  std.meta.AliasSeq of all interfaces directly or indirectly inherited by this class or interface. Interfaces do not repeat if multiply implemented.
  `InterfacesTuple`!Object yields an empty AliasSeq.
  Examples:

      interface I1 {}
      interface I2 {}
      class A : I1, I2 {}
      class B : A, I1 {}
      class C : B {}

      alias TL = InterfacesTuple!C;
      static assert(is(TL[0] == I1) && is(TL[1] == I2));

template `TransitiveBaseTypeTuple`(T)
  Get a AliasSeq of all base classes of T, in decreasing order, followed by T's interfaces. TransitiveBaseTypeTuple!Object yields the empty type tuple.
  Examples:

      interface J1 {}
      interface J2 {}
      class B1 {}
      class B2 : B1, J1, J2 {}
      class B3 : B2, J1 {}
      alias TL = TransitiveBaseTypeTuple!B3;
      writeln(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));

      writeln(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.
  Examples:

      interface I { I foo(); }
      class B
      {
          real foo(real v) { return v; }
      }
      class C : B, I
      {
          override C foo() { return this; } // covariant overriding of I.foo()
      }
      alias foos = MemberFunctionsTuple!(C, "foo");
      static assert(foos.length == 2);
      static assert(__traits(isSame, foos[0], C.foo));
      static assert(__traits(isSame, foos[1], B.foo));

template `TemplateOf`(alias T : Base!Args, alias Base, Args...)
template `TemplateOf`(alias T)
  Returns an alias to the template that T is an instance of. It will return void if a symbol without a template is given.
  Examples:

      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 AliasSeq of the template arguments used to instantiate T.
  Examples:

      import std.meta : AliasSeq;

      struct Foo(T, U) {}
      static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));

template `classInstanceAlignment`(T)
if (is(T == class))
  Returns class instance alignment.
  See also: __traits(`classInstanceAlignment`, T)
  Examples:

      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.
  Examples:

      alias X = CommonType!(int, long, short);
      assert(is(X == long));
      alias Y = CommonType!(int, char[], short);
      assert(is(Y == void));

  Examples:

      static assert(is(CommonType!(3) == int));
      static assert(is(CommonType!(double, 4, float) == double));
      static assert(is(CommonType!(string, char[]) == const(char)[]));
      static assert(is(CommonType!(3, 3U) == uint));
      static assert(is(CommonType!(double, int) == double));

template `AllImplicitConversionTargets`(T)
  Parameters:

  T | The type to check

  Returns:
  An std.meta.AliasSeq with all possible target types of an implicit conversion T.
  If T is a class derived from Object, the result of TransitiveBaseTypeTuple is returned.
  If the type is not a built-in value type or a class derived from Object, an empty std.meta.AliasSeq is returned.
  See Also:
  isImplicitlyConvertible
  Examples:

      import std.meta : AliasSeq;

      static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
      static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
      static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
      static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));

      static assert(is(AllImplicitConversionTargets!(char) ==
          AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
              ulong, float, double, real)
      ));
      static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
          short, ushort, dchar, int, uint, long, ulong, float, double, real
      )));
      static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
          int, uint, long, ulong, float, double, real
      )));

      static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
      static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));

      interface A {}
      interface B {}
      class C : A, B {}

      static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
      static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
      static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!(
          immutable Object, immutable A, immutable B
      )));

      interface I : A, B {}

      static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B)));
      static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B)));
      static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!(
          immutable A, immutable B
      )));

template `ImplicitConversionTargets`(T)
  Parameters:

  T | The type to check

  Warning This template is considered out-dated. It will be removed from Phobos in 2.107.0. Please use AllImplicitConversionTargets instead.

  Returns:
  An std.meta.AliasSeq with all possible target types of an implicit conversion T.
  If T is a class derived from Object, the result of TransitiveBaseTypeTuple is returned.
  If the type is not a built-in value type or a class derived from Object, an empty std.meta.AliasSeq is returned.

  Note The possible targets are computed more conservatively than the language allows, eliminating all dangerous conversions. For example, `ImplicitConversionTargets`!double does not include float.

  See Also:
  isImplicitlyConvertible
enum bool `isImplicitlyConvertible`(From, To);
  Is From implicitly convertible to To?
  Examples:

      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 bool `isQualifierConvertible`(From, To);
  Is From qualifier-convertible to To?
  Examples:

      // Mutable and immmutable both convert to const...
      static assert( isQualifierConvertible!(char, const(char)));
      static assert( isQualifierConvertible!(immutable(char), const(char)));
      // ...but const does not convert back to mutable or immutable
      static assert(!isQualifierConvertible!(const(char), char));
      static assert(!isQualifierConvertible!(const(char), immutable(char)));

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.
  Examples:

      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));

enum auto `isRvalueAssignable`(Lhs, Rhs = Lhs);
  Returns true iff an rvalue of type Rhs can be assigned to a variable of type Lhs.
  Examples:

      struct S1
      {
          void opAssign(S1);
      }

      struct S2
      {
          void opAssign(ref S2);
      }

      static assert( isRvalueAssignable!(long, int));
      static assert(!isRvalueAssignable!(int, long));
      static assert( isRvalueAssignable!S1);
      static assert(!isRvalueAssignable!S2);

enum auto `isLvalueAssignable`(Lhs, Rhs = Lhs);
  Returns true iff an lvalue of type Rhs can be assigned to a variable of type Lhs.
  Examples:

      struct S1
      {
          void opAssign(S1);
      }

      struct S2
      {
          void opAssign(ref S2);
      }

      static assert( isLvalueAssignable!(long, int));
      static assert(!isLvalueAssignable!(int, long));
      static assert( isLvalueAssignable!S1);
      static assert( isLvalueAssignable!S2);

template `isCovariantWith`(F, G)
if (is(F == function) && is(G == function) || is(F == delegate) && is(G == delegate) || isFunctionPointer!F && isFunctionPointer!G)
  Determines whether the function type F is covariant with G, i.e., functions of the type F can override ones of the type G.
  Examples:

      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.
  Parameters:

  T | The type to transform

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

  Examples:

      static int f(int);
      static assert(is(typeof(f(rvalueOf!int)) == int));

  Examples:

      static bool f(ref int);
      static assert(is(typeof(f(lvalueOf!int)) == bool));

enum bool `isBoolean`(T);
  Detect whether T is a built-in boolean type or enum of boolean base type.
  Examples:

      static assert( isBoolean!bool);
      enum EB : bool { a = true }
      static assert( isBoolean!EB);

      struct SubTypeOfBool
      {
          bool val;
          alias val this;
      }
      static assert(!isBoolean!(SubTypeOfBool));

template `isIntegral`(T)
  Detect whether T is a built-in integral type. Integral types are byte, ubyte, short, ushort, int, uint, long, ulong, cent, ucent, and enums with an integral type as its base type.
  Parameters:

  T | type to test

  Returns:
  true if T is an integral type

  Note this is not the same as __traits(`isIntegral`)

  Examples:

      static assert(
          isIntegral!byte &&
          isIntegral!short &&
          isIntegral!int &&
          isIntegral!long &&
          isIntegral!(const(long)) &&
          isIntegral!(immutable(long))
      );

      static assert(
          !isIntegral!bool &&
          !isIntegral!char &&
          !isIntegral!double
      );

      // types which act as integral values do not pass
      struct S
      {
          int val;
          alias val this;
      }

      static assert(!isIntegral!S);

enum bool `isFloatingPoint`(T);
  Detect whether T is a built-in floating point type.
  See also: __traits(isFloating, T)
  Examples:

      static assert(
          isFloatingPoint!float &&
          isFloatingPoint!double &&
          isFloatingPoint!real &&
          isFloatingPoint!(const(real)) &&
          isFloatingPoint!(immutable(real))
      );

      static assert(!isFloatingPoint!int);

      // types which act as floating point values do not pass
      struct S
      {
          float val;
          alias val this;
      }

      static assert(!isFloatingPoint!S);

template `isNumeric`(T)
  Detect whether T is a built-in numeric type (integral or floating point).
  Examples:

      static assert(
          isNumeric!byte &&
          isNumeric!short &&
          isNumeric!int &&
          isNumeric!long &&
          isNumeric!float &&
          isNumeric!double &&
          isNumeric!real &&
          isNumeric!(const(real)) &&
          isNumeric!(immutable(real))
      );

      static assert(
          !isNumeric!void &&
          !isNumeric!bool &&
          !isNumeric!char &&
          !isNumeric!wchar &&
          !isNumeric!dchar
      );

      // types which act as numeric values do not pass
      struct S
      {
          int val;
          alias val this;
      }

      static assert(!isNumeric!S);

enum bool `isScalarType`(T);
  Detect whether T is a scalar type (a built-in numeric, character or boolean type).
  See also: __traits(isScalar, T)
  Examples:

      static assert(!isScalarType!void);
      static assert( isScalarType!(immutable(byte)));
      static assert( isScalarType!(immutable(ushort)));
      static assert( isScalarType!(immutable(int)));
      static assert( isScalarType!(ulong));
      static assert( isScalarType!(shared(float)));
      static assert( isScalarType!(shared(const bool)));
      static assert( isScalarType!(const(char)));
      static assert( isScalarType!(wchar));
      static assert( isScalarType!(const(dchar)));
      static assert( isScalarType!(const(double)));
      static assert( isScalarType!(const(real)));

enum bool `isBasicType`(T);
  Detect whether T is a basic type (scalar type or void).
  Examples:

      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)));

template `isUnsigned`(T)
  Detect whether T is a built-in unsigned numeric type.
  Examples:

      static assert(
          isUnsigned!uint &&
          isUnsigned!ulong
      );

      static assert(
          !isUnsigned!char &&
          !isUnsigned!int &&
          !isUnsigned!long &&
          !isUnsigned!char &&
          !isUnsigned!wchar &&
          !isUnsigned!dchar
      );

enum bool `isSigned`(T);
  Detect whether T is a built-in signed numeric type.
  Examples:

      static assert(
          isSigned!int &&
          isSigned!long
      );

      static assert(
          !isSigned!uint &&
          !isSigned!ulong
      );

template `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.
  Examples:

      //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.
  Examples:

      //String types
      static assert( isSomeString!string);
      static assert( isSomeString!(wchar[]));
      static assert( isSomeString!(dchar[]));
      static assert( isSomeString!(typeof("aaa")));
      static assert( isSomeString!(const(char)[]));

      //Non string types
      static assert(!isSomeString!int);
      static assert(!isSomeString!(int[]));
      static assert(!isSomeString!(byte[]));
      static assert(!isSomeString!(typeof(null)));
      static assert(!isSomeString!(char[4]));

      enum ES : string { a = "aaa", b = "bbb" }
      static assert(!isSomeString!ES);

      static struct Stringish
      {
          string str;
          alias str this;
      }
      static assert(!isSomeString!Stringish);

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).
  Examples:

      static assert(isNarrowString!string);
      static assert(isNarrowString!wstring);
      static assert(isNarrowString!(char[]));
      static assert(isNarrowString!(wchar[]));

      static assert(!isNarrowString!dstring);
      static assert(!isNarrowString!(dchar[]));

      static assert(!isNarrowString!(typeof(null)));
      static assert(!isNarrowString!(char[4]));

      enum ES : string { a = "aaa", b = "bbb" }
      static assert(!isNarrowString!ES);

      static struct Stringish
      {
          string str;
          alias str this;
      }
      static assert(!isNarrowString!Stringish);

enum bool `isOrderingComparable`(T);
enum bool `isEqualityComparable`(T);
  Detects whether T is a comparable type. Basic types and structs and classes that implement opCmp are ordering comparable.
  Examples:

      static assert(isOrderingComparable!int);
      static assert(isOrderingComparable!string);

      static struct Foo {}
      static assert(!isOrderingComparable!Foo);

      static struct Bar
      {
          int a;
          auto opCmp(Bar b1) const { return a - b1.a; }
      }

      Bar b1 = Bar(5);
      Bar b2 = Bar(7);
      assert(isOrderingComparable!Bar && b2 > b1);

enum auto `isConvertibleToString`(T);
  Warning: This trait will be deprecated as soon as it is no longer used in Phobos. For a function parameter to safely accept a type that implicitly converts to string as a string, the conversion needs to happen at the callsite; otherwise, the conversion is done inside the function, and in many cases, that means that local memory is sliced (e.g. if a static array is passed to the function, then it's copied, and the resulting dynamic array will be a slice of a local variable). So, if the resulting string escapes the function, the string refers to invalid memory, and accessing it would mean accessing invalid memory. As such, the only safe way for a function to accept types that implicitly convert to string is for the implicit conversion to be done at the callsite, and that can only occur if the parameter is explicitly typed as an array, whereas using isConvertibleToString in a template constraint would result in the conversion being done inside the function. As such, isConvertibleToString is inherently unsafe and is going to be deprecated.
  Detect whether T is a struct, static array, or enum that is implicitly convertible to a string.
  Examples:

      static struct AliasedString
      {
          string s;
          alias s this;
      }

      enum StringEnum { a = "foo" }

      assert(!isConvertibleToString!string);
      assert(isConvertibleToString!AliasedString);
      assert(isConvertibleToString!StringEnum);
      assert(isConvertibleToString!(char[25]));
      assert(!isConvertibleToString!(char[]));

enum auto `isAutodecodableString`(T);
  Detect whether type T is a string that will be autodecoded.
  Given a type S that is one of:
  1. const(char)[]
  2. const(wchar)[]
  Type T can be one of:
  1. S
  2. implicitly convertible to T
  3. an enum with a base type T
  4. an aggregate with a base type T
  with the proviso that T cannot be a static array.
  Parameters:

  T | type to be tested

  Returns:
  true if T represents a string that is subject to autodecoding
  See Also: isNarrowString
  Examples:

      static struct Stringish
      {
          string s;
          alias s this;
      }
      static assert(isAutodecodableString!wstring);
      static assert(isAutodecodableString!Stringish);
      static assert(!isAutodecodableString!dstring);

      enum E : const(char)[3] { X = "abc" }
      enum F : const(char)[] { X = "abc" }
      enum G : F { X = F.init }

      static assert(isAutodecodableString!(char[]));
      static assert(!isAutodecodableString!(E));
      static assert(isAutodecodableString!(F));
      static assert(isAutodecodableString!(G));

      struct Stringish2
      {
          Stringish s;
          alias s this;
      }

      enum H : Stringish { X = Stringish() }
      enum I : Stringish2 { X = Stringish2() }

      static assert(isAutodecodableString!(H));
      static assert(isAutodecodableString!(I));

      static assert(!isAutodecodableString!(noreturn[]));
      static assert(!isAutodecodableString!(immutable(noreturn)[]));

enum bool `isStaticArray`(T);
  Detect whether type T is a static array.
  See also: __traits(`isStaticArray`, T)
  Examples:

      static assert( isStaticArray!(int[3]));
      static assert( isStaticArray!(const(int)[5]));
      static assert( isStaticArray!(const(int)[][5]));

      static assert(!isStaticArray!(const(int)[]));
      static assert(!isStaticArray!(immutable(int)[]));
      static assert(!isStaticArray!(const(int)[4][]));
      static assert(!isStaticArray!(int[]));
      static assert(!isStaticArray!(int[char]));
      static assert(!isStaticArray!(int[1][]));
      static assert(!isStaticArray!(int[int]));
      static assert(!isStaticArray!int);

template `isDynamicArray`(T)
  Detect whether type T is a dynamic array.
  Examples:

      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).
  Examples:

      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
  See also: __traits(`isAssociativeArray`, T)
  Examples:

      struct S;

      static assert( isAssociativeArray!(int[string]));
      static assert( isAssociativeArray!(S[S]));
      static assert(!isAssociativeArray!(string[]));
      static assert(!isAssociativeArray!S);
      static assert(!isAssociativeArray!(int[4]));

enum bool `isBuiltinType`(T);
  Detect whether type T is a builtin type.
  Examples:

      class C;
      union U;
      struct S;
      interface I;

      static assert( isBuiltinType!void);
      static assert( isBuiltinType!string);
      static assert( isBuiltinType!(int[]));
      static assert( isBuiltinType!(C[string]));
      static assert( isBuiltinType!(typeof(null)));
      static assert(!isBuiltinType!C);
      static assert(!isBuiltinType!U);
      static assert(!isBuiltinType!S);
      static assert(!isBuiltinType!I);
      static assert(!isBuiltinType!(void delegate(int)));

enum bool `isSIMDVector`(T);
  Detect whether type T is a SIMD vector type.
  Examples:

      static if (is(__vector(float[4])))
      {
          alias SimdVec = __vector(float[4]);
          static assert(isSIMDVector!(__vector(float[4])));
          static assert(isSIMDVector!SimdVec);
      }
      static assert(!isSIMDVector!uint);
      static assert(!isSIMDVector!(float[4]));

enum bool `isPointer`(T);
  Detect whether type T is a pointer.
  Examples:

      void fun();

      static assert( isPointer!(int*));
      static assert( isPointer!(int function()));
      static assert(!isPointer!int);
      static assert(!isPointer!string);
      static assert(!isPointer!(typeof(null)));
      static assert(!isPointer!(typeof(fun)));
      static assert(!isPointer!(int delegate()));

template `PointerTarget`(T : T*)
  Returns the target type of a pointer.
  Examples:

      static assert(is(PointerTarget!(int*) == int));
      static assert(is(PointerTarget!(void*) == void));

template `isAggregateType`(T)
  Detect whether type T is an aggregate type.
  Examples:

      class C {}
      union U {}
      struct S {}
      interface I {}

      static assert( isAggregateType!C);
      static assert( isAggregateType!U);
      static assert( isAggregateType!S);
      static assert( isAggregateType!I);
      static assert(!isAggregateType!void);
      static assert(!isAggregateType!string);
      static assert(!isAggregateType!(int[]));
      static assert(!isAggregateType!(C[string]));
      static assert(!isAggregateType!(void delegate(int)));

      enum ES : S { a = S.init }
      enum EC : C { a = C.init }
      enum EI : I { a = I.init }
      enum EU : U { a = U.init }

      static assert( isAggregateType!ES);
      static assert( isAggregateType!EC);
      static assert( isAggregateType!EI);
      static assert( isAggregateType!EU);

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.
  Examples:

      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.
  Examples:

      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.
  Examples:

      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));

  Examples:
  To use `isInstanceOf` to check the identity of a template while inside of said template, use TemplateOf.

      static struct A(T = void)
      {
          // doesn't work as expected, only accepts A when T = void
          void func(B)(B b)
          if (isInstanceOf!(A, B)) {}

          // correct behavior
          void method(B)(B b)
          if (isInstanceOf!(TemplateOf!(A), B)) {}
      }

      A!(void) a1;
      A!(void) a2;
      A!(int) a3;

      static assert(!__traits(compiles, a1.func(a3)));
      static assert( __traits(compiles, a1.method(a2)));
      static assert( __traits(compiles, a1.method(a3)));

template `isExpressions`(T...)
  Check whether the tuple T is an expression tuple. An expression tuple only contains expressions.
  See Also:
  isTypeTuple.
  Examples:

      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.
enum auto `isTypeTuple`(T...);
  Check whether the tuple T is a type tuple. A type tuple only contains types.
  See Also:
  isExpressions.
  Examples:

      static assert(isTypeTuple!(int, float, string));
      static assert(!isTypeTuple!(1, 2.0, "a"));
      static assert(!isTypeTuple!(1, double, string));

enum bool `isFunctionPointer`(alias T);
  Detect whether symbol or type T is a function pointer.
  Examples:

      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) {}));

enum bool `isDelegate`(alias T);
  Detect whether symbol or type T is a delegate.
  Examples:

      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)));

enum bool `isSomeFunction`(alias T);
  Detect whether symbol or type T is a function, a function pointer or a delegate.
  Parameters:

  T | The type to check

  Returns:
  A bool
  Examples:

      static real func(ref int) { return 0; }
      static void prop() @property { }
      class C
      {
          real method(ref int) { return 0; }
          real prop() @property { return 0; }
      }
      auto c = new C;
      auto fp = &func;
      auto dg = &c.method;

      static assert( isSomeFunction!func);
      static assert( isSomeFunction!prop);
      static assert( isSomeFunction!(C.method));
      static assert( isSomeFunction!(C.prop));
      static assert( isSomeFunction!(c.prop));
      static assert( isSomeFunction!fp);
      static assert( isSomeFunction!dg);

      real val;
      static assert(!isSomeFunction!int);
      static assert(!isSomeFunction!val);

template `isCallable`(alias callable)
  Detect whether callable is a callable object, which can be called with the function call operator (...).
  Note: Implicit Function Template Instantiation is not attempted - see below.
  Examples:
  Functions, function pointers, delegates, non-template function literals.

      void f() { }
      int g(int x) { return x; }

      static assert( isCallable!f);
      static assert( isCallable!g);

      auto fp = &f;
      static assert( isCallable!fp);
      static assert( isCallable!((int x) {}));

      int x;
      static assert(!isCallable!x);
      auto d = () => x;
      static assert( isCallable!d);

  Examples:
  Aggregate types with (static) opCall.

      class C { int opCall(int) { return 0; } }
      auto c = new C;
      struct S { static int opCall(int) { return 0; } }
      interface I { real value() @property; }

      static assert( isCallable!c);
      static assert( isCallable!(c.opCall));
      static assert( isCallable!S);
      static assert( isCallable!(I.value));

      static assert(!isCallable!I);

  Examples:
  Template functions are only detected if they are instantiable with !().

      void f()() { }
      T g(T = int)(T x) { return x; }
      int h(T)();
      struct S1 { static void opCall()() { } }
      struct S2 { static T opCall(T = int)(T x) {return x; } }

      static assert( isCallable!f);
      static assert( isCallable!g);
      static assert(!isCallable!h);
      static assert( isCallable!S1);
      static assert( isCallable!S2);

      static assert(!isCallable!((x) {}));

  Examples:
  Overloaded functions and function templates instantiable with !().

      static struct Wrapper
      {
          void f() { }
          int f(int x) { return x; }

          void g()() { }
          T g(T = int)(T x) { return x; }
      }

      static assert(isCallable!(Wrapper.f));
      static assert(isCallable!(Wrapper.g));

enum auto `isAbstractFunction`(alias S);
  Detect whether S is an abstract function.
  See also: __traits(`isAbstractFunction`, S)
  Parameters:

  S | The symbol to check

  Returns:
  A bool
  Examples:

      struct S { void foo() { } }
      class C { void foo() { } }
      class AC { abstract void foo(); }
      static assert(!isAbstractFunction!(int));
      static assert(!isAbstractFunction!(S.foo));
      static assert(!isAbstractFunction!(C.foo));
      static assert( isAbstractFunction!(AC.foo));

enum auto `isFinalFunction`(alias S);
  Detect whether S is a final function.
  See also: __traits(`isFinalFunction`, S)
  Examples:

      struct S { void bar() { } }
      final class FC { void foo(); }
      class C
      {
          void bar() { }
          final void foo();
      }
      static assert(!isFinalFunction!(int));
      static assert(!isFinalFunction!(S.bar));
      static assert( isFinalFunction!(FC.foo));
      static assert(!isFinalFunction!(C.bar));
      static assert( isFinalFunction!(C.foo));

enum auto `isNestedFunction`(alias f);
  Determines if f is a function that requires a context pointer.
  Parameters:

  f | The type to check Returns A bool

  Examples:

      static void f() {}
      static void fun()
      {
          int i;
          int f() { return i; }

          static assert(isNestedFunction!(f));
      }

      static assert(!isNestedFunction!f);

enum auto `isAbstractClass`(alias S);
  Detect whether S is an abstract class.
  See also: __traits(`isAbstractClass`, S)
  Examples:

      struct S { }
      class C { }
      abstract class AC { }
      static assert(!isAbstractClass!S);
      static assert(!isAbstractClass!C);
      static assert( isAbstractClass!AC);
      C c;
      static assert(!isAbstractClass!c);
      AC ac;
      static assert( isAbstractClass!ac);

enum auto `isFinalClass`(alias S);
  Detect whether S is a final class.
  See also: __traits(`isFinalClass`, S)
  Examples:

      class C { }
      abstract class AC { }
      final class FC1 : C { }
      final class FC2 { }
      static assert(!isFinalClass!C);
      static assert(!isFinalClass!AC);
      static assert( isFinalClass!FC1);
      static assert( isFinalClass!FC2);
      C c;
      static assert(!isFinalClass!c);
      FC1 fc1;
      static assert( isFinalClass!fc1);

template `Unconst`(T)
  Removes const, inout and immutable qualifiers, if any, from type T.
template `Unshared`(T)
  Removes shared qualifier, if any, from type T.
  Note that while immutable is implicitly shared, it is unaffected by Unshared. Only explicit shared is removed.
  Examples:

      static assert(is(Unshared!int == int));
      static assert(is(Unshared!(const int) == const int));
      static assert(is(Unshared!(immutable int) == immutable int));

      static assert(is(Unshared!(shared int) == int));
      static assert(is(Unshared!(shared(const int)) == const int));

      static assert(is(Unshared!(shared(int[])) == shared(int)[]));

template `Unqual`(T)
  Removes all qualifiers, if any, from type T.
template `CopyTypeQualifiers`(FromType, ToType)
  Copies type qualifiers from FromType to ToType.
  Supported type qualifiers:
  - const
  - inout
  - immutable
  - shared
  Examples:

      static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));

template `CopyConstness`(FromType, ToType)
  Returns the type of ToType with the "constness" of FromType. A type's constness refers to whether it is const, immutable, or inout. If FromType has no constness, the returned type will be the same as ToType.
  Examples:

      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.
  Examples:

      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.
  Examples:

      enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
      enum F : E    { a = E.a }
      alias G = const(F);
      static assert(is(OriginalType!E == real));
      static assert(is(OriginalType!F == real));
      static assert(is(OriginalType!G == const real));

template `KeyType`(V : V[K], K)
  Get the Key type of an Associative Array.
  Examples:

      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.
  Examples:

      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)
  Parameters:

  T | A built in integral or vector type.

  Returns:
  The corresponding unsigned numeric type for T with the same type qualifiers.
  If T is not a integral or vector, a compile-time error is given.
  Examples:

      static assert(is(Unsigned!(int) == uint));
      static assert(is(Unsigned!(long) == ulong));
      static assert(is(Unsigned!(const short) == const ushort));
      static assert(is(Unsigned!(immutable byte) == immutable ubyte));
      static assert(is(Unsigned!(inout int) == inout uint));

  Examples:
  Unsigned types are forwarded

      static assert(is(Unsigned!(uint) == uint));
      static assert(is(Unsigned!(const uint) == const uint));

      static assert(is(Unsigned!(ubyte) == ubyte));
      static assert(is(Unsigned!(immutable uint) == immutable uint));

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.
  Examples:

      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.
  Examples:

      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.
  Examples:

      static assert(mostNegative!float == -float.max);
      static assert(mostNegative!double == -double.max);
      static assert(mostNegative!real == -real.max);
      static assert(mostNegative!bool == false);

  Examples:

      import std.meta : AliasSeq;

      static foreach (T; AliasSeq!(bool, byte, short, int, long))
          static assert(mostNegative!T == T.min);

      static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
          static assert(mostNegative!T == 0);

template `Promoted`(T)
if (isScalarType!T)
  Get the type that a scalar type T will promote to in multi-term arithmetic expressions.
  Examples:

      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));

enum auto `mangledName`(alias sth);
  Returns the mangled name of symbol or type sth.
  `mangledName` is the same as builtin .mangleof property, but might be more convenient in generic code, e.g. as a template argument when invoking staticMap.
  Examples:

      import std.meta : AliasSeq;
      alias TL = staticMap!(mangledName, int, const int, immutable int);
      static assert(TL == AliasSeq!("i", "xi", "yi"));

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.
  Examples:

      // 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);
      writeln(selA); // 1
      writeln(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`);
  Select one of two functions to run via template parameter.
  Parameters:

  cond | A bool which determines which function is run
  A `a` | The first function
  B `b` | The second function

  Returns:
  `a` without evaluating `b` if cond is true. Otherwise, returns `b` without evaluating `a`.
  Examples:

      real run() { return 0; }
      int fail() { assert(0); }
      auto a = select!true(run(), fail());
      auto b = select!false(fail(), run());
      static assert(is(typeof(a) == real));
      static assert(is(typeof(b) == real));

enum auto `hasUDA`(alias symbol, alias attribute);
  Determine if a symbol has a given user-defined attribute.
  See Also:
  getUDAs
  Examples:

      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:
  hasUDA
  Examples:

      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)
  Parameters:

  symbol | The aggregate type or module to search
  attribute | The user-defined attribute to search for

  Returns:
  All symbols within symbol that have the given UDA attribute.

  Note This is not recursive; it will not search for symbols within symbols such as nested structs or unions.

  Examples:

      enum Attr;
      struct A
      {
          @Attr int a;
          int b;
      }

      static assert(getSymbolsByUDA!(A, Attr).length == 1);
      static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));

  Examples:

      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));

  Examples:
  Finds multiple attributes

      static struct UDA { string name; }

      static struct B
      {
          @UDA("X")
          int x;
          @UDA("Y")
          int y;
          @(100)
          int z;
      }

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

  Examples:
  Checks for UDAs on the aggregate symbol itself

      static struct UDA { string name; }

      @UDA("A")
      static struct C
      {
          @UDA("B")
          int d;
      }

      static assert(getSymbolsByUDA!(C, UDA).length == 2);
      static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
      static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");

  Examples:
  Finds nothing if there is no member with specific UDA

      static struct UDA { string name; }

      static struct D
      {
          int x;
      }

      static assert(getSymbolsByUDA!(D, UDA).length == 0);

enum bool `allSameType`(Ts...);
  Returns:
  true iff all types Ts are the same.
  Examples:

      static assert(allSameType!());
      static assert(allSameType!(int));
      static assert(allSameType!(int, int));
      static assert(allSameType!(int, int, int));
      static assert(allSameType!(float, float, float));
      static assert(!allSameType!(int, double));
      static assert(!allSameType!(int, float, double));
      static assert(!allSameType!(int, float, double, real));
      static assert(!allSameType!(short, int, float, double, real));

enum auto `ifTestable`(T, alias pred = (a) => a);
  Returns:
  true iff the type T can be tested in an if-expression, that is if if (pred(T.init)) {} is compilable.
  Examples:

      class C;
      struct S1;
      struct S2
      {
          T opCast(T)() const;
      }

      static assert( ifTestable!bool);
      static assert( ifTestable!int);
      static assert( ifTestable!(S1*));
      static assert( ifTestable!(typeof(null)));
      static assert( ifTestable!(int[]));
      static assert( ifTestable!(int[string]));
      static assert( ifTestable!S2);
      static assert( ifTestable!C);
      static assert(!ifTestable!S1);

enum auto `isType`(alias X);
  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).
  Returns:
  true if X is a type, false otherwise
  Examples:

      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`(alias X)
  Detect whether symbol or type X is a function. This is different from finding if a symbol is callable or satisfying is(X == return). It finds specifically if the symbol represents a normal function (or method) declaration, i.e. not a delegate or a function pointer.
  Returns:
  true if X is a function, false otherwise
  See Also:
  Use isFunctionPointer or isDelegate for detecting those types respectively.
  Examples:

      static void func(){}
      static assert(isFunction!func);
      static assert(isFunction!(typeof(func)));

      auto fp = &func; // function pointer
      static assert(!isFunction!fp);

      int i;
      int f2() => i; // nested function
      static assert(isFunction!f2);

      struct S
      {
          void func(){}
      }
      static assert(isFunction!(S.func));

template `isFinal`(alias X)
  Detect whether X is a final method or class.
  Returns:
  true if X is final, false otherwise
  Examples:

      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);
  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).
  See also: __traits(`isCopyable`, S)
  Parameters:

  S | The type to check.

  Returns:
  true if S can be copied. false otherwise.
  Examples:

      struct S1 {}                        // Fine. Can be copied
      struct S2 {         this(this) {}}  // Fine. Can be copied
      struct S3 {@disable this(this);  }  // Not fine. Copying is disabled.
      struct S4 {S3 s;}                   // Not fine. A field has copying disabled.

      class C1 {}

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

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

template `DeducedParameterType`(T)
template `DeducedParameterType`(alias T)
  The parameter type deduced by IFTI when an expression of type T is passed as an argument to a template function.
  For all types other than pointer and slice types, `DeducedParameterType`!T is the same as T. For pointer and slice types, it is T with the outer-most layer of qualifiers dropped.

Copyright © 1999-2026 by the D Language Foundation | Page generated by Ddoc on Wed Aug 19 13:30:07 2026