D Programming Language
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 local clone. Page wiki View or edit the community-maintained wiki page associated with this page.

# std.traits

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

Category | Templates
--- | ---
Symbol Name traits | packageName moduleName fullyQualifiedName
Function traits | ReturnType ParameterTypeTuple arity ParameterStorageClassTuple ParameterIdentifierTuple ParameterDefaultValueTuple functionAttributes isSafe isUnsafe functionLinkage variadicFunctionStyle FunctionTypeOf SetFunctionAttributes
Aggregate Type traits | isNested hasNested FieldTypeTuple RepresentationTypeTuple hasAliasing hasIndirections hasUnsharedAliasing hasElaborateCopyConstructor hasElaborateAssign hasElaborateDestructor hasMember EnumMembers BaseTypeTuple BaseClassesTuple InterfacesTuple TransitiveBaseTypeTuple MemberFunctionsTuple TemplateOf TemplateArgsOf classInstanceAlignment
Type Conversion | CommonType ImplicitConversionTargets isImplicitlyConvertible isAssignable isCovariantWith
IsSomething | isBoolean isIntegral isFloatingPoint isNumeric isScalarType isBasicType isUnsigned isSigned isSomeChar isSomeString isNarrowString isStaticArray isDynamicArray isArray isAssociativeArray isBuiltinType isPointer isAggregateType
xxx | isIterable isMutable isInstanceOf isExpressionTuple isTypeTuple isFunctionPointer isDelegate isSomeFunction isCallable isAbstractFunction isFinalFunction isAbstractClass isFinalClass
General Types | Unqual ForeachType OriginalType PointerTarget KeyType ValueType Unsigned Largest Signed unsigned mostNegative
Misc | mangledName Select select

License:
Boost License 1.0.

Authors:
Walter Bright, Tomasz Stachowiak (isExpressionTuple), Andrei Alexandrescu, Shin Fujishiro, Robert Clipsham, David Nadlinger, Kenji Hara, Shoichi Kato

Source:
std/traits.d

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

  Example:

      import std.traits;
      static assert(packageName!packageName == "std");

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

  Example:

      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.

  Example:

      module mymodule;
      import std.traits;
      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).

  Example:

      import std.traits;
      int foo();
      ReturnType!foo x;   // x is declared as int

template ParameterTypeTuple(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.

  Example:

      import std.traits;
      int foo(int, long);
      void bar(ParameterTypeTuple!foo);      // declares void bar(int, long);
      void abc(ParameterTypeTuple!foo[1]);   // declares void abc(long);

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.

  Example:

      void foo(){}
      static assert(arity!foo==0);
      void bar(uint){}
      static assert(arity!bar==1);

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.

  Example:

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

  none
  scope_
  out_
  ref_
  lazy_
    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.

  Examples:

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

template ParameterDefaultValueTuple(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.

  Examples:

      import std.traits;
      int foo(int num, string name = "hello", int[] arr = [1,2,3]);
      static assert(is(ParameterDefaultValueTuple!foo[0] == void));
      static assert(   ParameterDefaultValueTuple!foo[1] == "hello");
      static assert(   ParameterDefaultValueTuple!foo[2] == [1,2,3]);

enum FunctionAttribute: uint;
template functionAttributes(func...) if (func.length == 1 && isCallable!func)
  Returns the attributes attached to a function func.

  Example:

      alias FA = FunctionAttribute; // shorten the enum name

      real func(real x) @safe pure nothrow
      {
          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
    These flags can be bitwise OR-ed together to represent complex attribute.

template isSafe(alias func) if (isCallable!func)
  true if func is @safe or @trusted.

  Example:

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

template isUnsafe(alias func)
  true if func is @system.

  Example:

      @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 areAllSafe(funcs...) if (funcs.length > 0)
  Deprecated. It's badly named and provides redundant functionality. It was also badly broken prior to 2.060 (bug# 8362), so any code which uses it probably needs to be changed anyway. Please use allSatisfy(isSafe, ...) instead. This will be removed in June 2015.

  true all functions are isSafe.

  Example:

      @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( areAllSafe!(add, add));
      static assert( areAllSafe!(add, sub));
      static assert(!areAllSafe!(sub, mul));

template functionLinkage(func...) if (func.length == 1 && isCallable!func)
  Returns the calling convention of function as a string.

  Example:

      string a = functionLinkage!(writeln!(string, int));
      assert(a == "D"); // extern(D)

      auto fp = &printf;
      string b = functionLinkage!fp;
      assert(b == "C"); // extern(C)

enum Variadic: int;
template variadicFunctionStyle(func...) if (func.length == 1 && isCallable!func)
  Determines what kind of variadic parameters function has.

  Example:

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

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

  no
    Function is not variadic.

  c
    Function is a C-style variadic function.

  d
    Function is a D-style variadic function, which uses

    _argptr and _arguments.

  typesafe
    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.

      class C
      {
          int value() @property;
      }
      static assert(is( typeof(C.value) == int ));
      static assert(is( FunctionTypeOf!(C.value) == function ));

  Note:
  Do not confuse function types with function pointer types; function types are usually used for compile-time reflection purposes.

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

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.

  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 FieldTypeTuple(T)
  Get as a typetuple 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 typetuple with one element T.

  Examples:

      struct S { int x; float y; }
      static assert(is(FieldTypeTuple!S == TypeTuple!(int, float)));

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

  Example:

      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.

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.

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.

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

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().

template hasMember(T, string name)
  Yields true if and only if T is an aggregate that defines a symbol called name.

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.

  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.

  Examples:
  Creating an array of enumerated values:

      enum Sqrts : real
      {
          one   = 1,
          two   = 1.41421,
          three = 1.73205,
      }
      auto sqrts = [ EnumMembers!Sqrts ];
      assert(sqrts == [ Sqrts.one, 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(Mode.read ) == 0);
      assert(rank(Mode.write) == 1);
      assert(rank(Mode.map  ) == 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.

  Example:

      import std.traits, std.typetuple, std.stdio;
      interface I { }
      class A { }
      class B : A, I { }

      void main()
      {
          alias TL = BaseTypeTuple!B;
          writeln(typeid(TL));        // prints: (A,I)
      }

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.

  Example:

      import std.traits, std.typetuple, std.stdio;
      interface I { }
      class A { }
      class B : A, I { }
      class C : B { }

      void main()
      {
          alias TL = BaseClassesTuple!C;
          writeln(typeid(TL));        // prints: (B,A,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.

  Example:

      import std.traits, std.typetuple, std.stdio;
      interface I1 { }
      interface I2 { }
      class A : I1, I2 { }
      class B : A, I1 { }
      class C : B { }

      void main()
      {
          alias TL = InterfacesTuple!C;
          writeln(typeid(TL));        // prints: (I1, I2)
      }

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.

  Example:

      import std.traits, std.typetuple, std.stdio;
      interface I { }
      class A { }
      class B : A, I { }
      class C : B { }

      void main()
      {
          alias TL = TransitiveBaseTypeTuple!C;
          writeln(typeid(TL));        // prints: (B,A,Object,I)
      }

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.

  Example:

      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 MemberFunctionsTuple!(C, "foo") foos;
      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...)
  Returns an alias to the template that T is an instance of.

  Example:

      struct Foo(T, U) {}
      static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));

template TemplateArgsOf(alias T : Base!Args, alias Base, Args...)
  Returns a TypeTuple of the template arguments used to instantiate T.

  Example:

      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.

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

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.

template isImplicitlyConvertible(From, To)
  Is From implicitly convertible to To?

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.

  Example:

      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.

  Examples:

      // 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

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

deprecated alias pointerTarget = PointerTarget(T : T*);
  Deprecated. Please use PointerTarget instead. This will be removed in June 2015.

template isExpressionTuple(T...)
  Check whether the tuple T is an expression tuple. An expression tuple only contains expressions. See also isTypeTuple.

  Examples:

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

template isTypeTuple(T...)
  Check whether the tuple T is a type tuple. A type tuple only contains types. See also isExpressionTuple.

  Examples:

      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.

template isDelegate(T...) if (T.length == 1)
  Detect whether symbol or type T is a delegate.

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 (...).

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.

template 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.

template isFinalClass(T...) if (T.length == 1)
  Detect whether T is a a final class.

template Unqual(T)
  Removes all qualifiers, if any, from type T.

  Example:

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

template OriginalType(T)
  Strips off all typedefs (including enum ones) from type T.

  Example:

      enum E : int { a }
      typedef E F;
      typedef const F G;
      static assert(is(OriginalType!G == const int));

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

  Examples:

      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.

  Examples:

      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.

template Signed(T)
  Returns the corresponding signed type for T. T must be a numeric integral type, otherwise a compile-time error occurs.

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

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

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

template mangledName(sth...) if (sth.length == 1)
  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.

  Examples:

      // can select types
      static assert(is(Select!(true, int, long) == int));
      static assert(is(Select!(false, int, long) == long));

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

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.

Copyright Digital Mars 2005 - 2009. | Page generated by Ddoc.