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

std.meta

Templates to manipulate template parameter sequences (also known as alias sequences).
Some operations on alias sequences are built into the language, such as S[i], which accesses the element at index i in the sequence. S[low .. high] returns a new alias sequence that is a slice of the old one.
For more information, see Compile-time Sequences.
Note: Several templates in this module use or operate on eponymous templates that take a single argument and evaluate to a boolean constant. Such templates are referred to as template predicates.
Category Templates
Building blocks Alias AliasSeq aliasSeqOf
Alias sequence filtering Erase EraseAll Filter NoDuplicates Stride
Alias sequence type hierarchy DerivedToFront MostDerived
Alias sequence transformation Repeat Replace ReplaceAll Reverse staticMap staticSort
Alias sequence searching allSatisfy anySatisfy staticIndexOf
Template predicates templateAnd templateNot templateOr staticIsSorted
Template instantiation ApplyLeft ApplyRight Instantiate

References Based on ideas in Table 3.1 from Modern C++ Design, Andrei Alexandrescu (Addison-Wesley Professional, 2001)

Source std/meta.d

template AliasSeq(TList...)
Creates a sequence of zero or more aliases. This is most commonly used as template parameters or arguments.
In previous versions of Phobos, this was known as TypeTuple.
Examples:
import std.meta;
alias TL = AliasSeq!(int, double);

int foo(TL td)  // same as int foo(int, double);
{
    return td[0] + cast(int) td[1];
}
Examples:
alias TL = AliasSeq!(int, double);

alias Types = AliasSeq!(TL, char);
static assert(is(Types == AliasSeq!(int, double, char)));
Examples:
// Creates a compile-time sequence of function call expressions
// that each call `func` with the next variadic template argument
template Map(alias func, args...)
{
    auto ref lazyItem() {return func(args[0]);}

    static if (args.length == 1)
    {
        alias Map = lazyItem;
    }
    else
    {
        // recurse
        alias Map = AliasSeq!(lazyItem, Map!(func, args[1 .. $]));
    }
}

static void test(int a, int b)
{
    writeln(a); // 4
    writeln(b); // 16
}

static int a = 2;
static int b = 4;

test(Map!(i => i ^^ 2, a, b));
writeln(a); // 2
writeln(b); // 4

test(Map!((ref i) => i *= i, a, b));
writeln(a); // 4
writeln(b); // 16

static void testRef(ref int a, ref int b)
{
    writeln(a++); // 16
    writeln(b++); // 256
}

testRef(Map!(function ref(ref i) => i *= i, a, b));
writeln(a); // 17
writeln(b); // 257
template Alias(alias a)

template Alias(T)
Allows aliasing of any single symbol, type or compile-time expression.
Not everything can be directly aliased. An alias cannot be declared of - for example - a literal:
alias a = 4; //Error
With this template any single entity can be aliased:
alias b = Alias!4; //OK
See Also:
To alias more than one thing at once, use AliasSeq.
Examples:
// Without Alias this would fail if Args[0] was e.g. a value and
// some logic would be needed to detect when to use enum instead
alias Head(Args...) = Alias!(Args[0]);
alias Tail(Args...) = Args[1 .. $];

alias Blah = AliasSeq!(3, int, "hello");
static assert(Head!Blah == 3);
static assert(is(Head!(Tail!Blah) == int));
static assert((Tail!Blah)[1] == "hello");
Examples:
alias a = Alias!(123);
static assert(a == 123);

enum abc = 1;
alias b = Alias!(abc);
static assert(b == 1);

alias c = Alias!(3 + 4);
static assert(c == 7);

alias concat = (s0, s1) => s0 ~ s1;
alias d = Alias!(concat("Hello", " World!"));
static assert(d == "Hello World!");

alias e = Alias!(int);
static assert(is(e == int));

alias f = Alias!(AliasSeq!(int));
static assert(!is(typeof(f[0]))); //not an AliasSeq
static assert(is(f == int));

auto g = 6;
alias h = Alias!g;
++h;
writeln(g); // 7
template staticIndexOf(args...) if (args.length >= 1)
Returns the index of the first occurrence of args[0] in the sequence args[1 .. $]. args may be types or compile-time values. If not found, -1 is returned.
Examples:
import std.stdio;

void foo()
{
    writefln("The index of long is %s",
             staticIndexOf!(long, AliasSeq!(int, long, double)));
    // prints: The index of long is 1
}
template Erase(T, TList...)

template Erase(alias T, TList...)
Returns an AliasSeq created from TList with the first occurrence, if any, of T removed.
Examples:
alias Types = AliasSeq!(int, long, double, char);
alias TL = Erase!(long, Types);
static assert(is(TL == AliasSeq!(int, double, char)));
template EraseAll(T, TList...)

template EraseAll(alias T, TList...)
Returns an AliasSeq created from TList with the all occurrences, if any, of T removed.
Examples:
alias Types = AliasSeq!(int, long, long, int);

alias TL = EraseAll!(long, Types);
static assert(is(TL == AliasSeq!(int, int)));
template NoDuplicates(TList...)
Returns an AliasSeq created from TList with the all duplicate types removed.
Examples:
alias Types = AliasSeq!(int, long, long, int, float);

alias TL = NoDuplicates!(Types);
static assert(is(TL == AliasSeq!(int, long, float)));
template Replace(T, U, TList...)

template Replace(alias T, U, TList...)

template Replace(T, alias U, TList...)

template Replace(alias T, alias U, TList...)
Returns an AliasSeq created from TList with the first occurrence of T, if found, replaced with U.
Examples:
alias Types = AliasSeq!(int, long, long, int, float);

alias TL = Replace!(long, char, Types);
static assert(is(TL == AliasSeq!(int, char, long, int, float)));
template ReplaceAll(T, U, TList...)

template ReplaceAll(alias T, U, TList...)

template ReplaceAll(T, alias U, TList...)

template ReplaceAll(alias T, alias U, TList...)
Returns an AliasSeq created from TList with all occurrences of T, if found, replaced with U.
Examples:
alias Types = AliasSeq!(int, long, long, int, float);

alias TL = ReplaceAll!(long, char, Types);
static assert(is(TL == AliasSeq!(int, char, char, int, float)));
template Reverse(TList...)
Returns an AliasSeq created from TList with the order reversed.
Examples:
alias Types = AliasSeq!(int, long, long, int, float, byte, ubyte, short, ushort, uint);

alias TL = Reverse!(Types);
static assert(is(TL == AliasSeq!(uint, ushort, short, ubyte, byte, float, int, long, long, int)));
template MostDerived(T, TList...)
Returns the type from TList that is the most derived from type T. If none are found, T is returned.
Examples:
class A { }
class B : A { }
class C : B { }
alias Types = AliasSeq!(A, C, B);

MostDerived!(Object, Types) x;  // x is declared as type C
static assert(is(typeof(x) == C));
template DerivedToFront(TList...)
Returns an AliasSeq with the elements of TList sorted so that the most derived types come first.
Examples:
class A { }
class B : A { }
class C : B { }
alias Types = AliasSeq!(A, C, B);

alias TL = DerivedToFront!(Types);
static assert(is(TL == AliasSeq!(C, B, A)));
template staticMap(alias F, Args...)
Evaluates to AliasSeq!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1])).
Examples:
import std.traits : Unqual;
alias TL = staticMap!(Unqual, int, const int, immutable int, uint, ubyte, byte, short, ushort);
static assert(is(TL == AliasSeq!(int, int, int, uint, ubyte, byte, short, ushort)));
template allSatisfy(alias F, T...)
Tests whether all given items satisfy a template predicate, i.e. evaluates to F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1]).
Evaluation is not short-circuited if a false result is encountered; the template predicate must be instantiable with all the given items.
Examples:
import std.traits : isIntegral;

static assert(!allSatisfy!(isIntegral, int, double));
static assert( allSatisfy!(isIntegral, int, long));
template anySatisfy(alias F, T...)
Tests whether any given items satisfy a template predicate, i.e. evaluates to F!(T[0]) || F!(T[1]) || ... || F!(T[$ - 1]).
Evaluation is short-circuited if a true result is encountered; the template predicate must be instantiable with one of the given items.
Examples:
import std.traits : isIntegral;

static assert(!anySatisfy!(isIntegral, string, double));
static assert( anySatisfy!(isIntegral, int, double));
template Filter(alias pred, TList...)
Filters an AliasSeq using a template predicate. Returns an AliasSeq of the elements which satisfy the predicate.
Examples:
import std.traits : isNarrowString, isUnsigned;

alias Types1 = AliasSeq!(string, wstring, dchar[], char[], dstring, int);
alias TL1 = Filter!(isNarrowString, Types1);
static assert(is(TL1 == AliasSeq!(string, wstring, char[])));

alias Types2 = AliasSeq!(int, byte, ubyte, dstring, dchar, uint, ulong);
alias TL2 = Filter!(isUnsigned, Types2);
static assert(is(TL2 == AliasSeq!(ubyte, uint, ulong)));
template templateNot(alias pred)
Negates the passed template predicate.
Examples:
import std.traits : isPointer;

alias isNoPointer = templateNot!isPointer;
static assert(!isNoPointer!(int*));
static assert(allSatisfy!(isNoPointer, string, char, float));
template templateAnd(Preds...)
Combines several template predicates using logical AND, i.e. constructs a new predicate which evaluates to true for a given input T if and only if all of the passed predicates are true for T.
The predicates are evaluated from left to right, aborting evaluation in a short-cut manner if a false result is encountered, in which case the latter instantiations do not need to compile.
Examples:
import std.traits : isNumeric, isUnsigned;

alias storesNegativeNumbers = templateAnd!(isNumeric, templateNot!isUnsigned);
static assert(storesNegativeNumbers!int);
static assert(!storesNegativeNumbers!string && !storesNegativeNumbers!uint);

// An empty sequence of predicates always yields true.
alias alwaysTrue = templateAnd!();
static assert(alwaysTrue!int);
template templateOr(Preds...)
Combines several template predicates using logical OR, i.e. constructs a new predicate which evaluates to true for a given input T if and only at least one of the passed predicates is true for T.
The predicates are evaluated from left to right, aborting evaluation in a short-cut manner if a true result is encountered, in which case the latter instantiations do not need to compile.
Examples:
import std.traits : isPointer, isUnsigned;

alias isPtrOrUnsigned = templateOr!(isPointer, isUnsigned);
static assert( isPtrOrUnsigned!uint &&  isPtrOrUnsigned!(short*));
static assert(!isPtrOrUnsigned!int  && !isPtrOrUnsigned!(string));

// An empty sequence of predicates never yields true.
alias alwaysFalse = templateOr!();
static assert(!alwaysFalse!int);
template aliasSeqOf(alias iter) if (isIterable!(typeof(iter)) && !isInfinite!(typeof(iter)))
Converts any foreach-iterable entity (e.g. an input range) to an alias sequence.
Parameters:
iter the entity to convert into an AliasSeq. It must be able to be able to be iterated over using a foreach-statement.
Returns:
An AliasSeq containing the values produced by iterating over iter.
Examples:
import std.algorithm.iteration : map;
import std.algorithm.sorting : sort;
import std.string : capitalize;

struct S
{
    int a;
    int c;
    int b;
}

alias capMembers = aliasSeqOf!([__traits(allMembers, S)].sort().map!capitalize());
static assert(capMembers[0] == "A");
static assert(capMembers[1] == "B");
static assert(capMembers[2] == "C");
Examples:
static immutable REF = [0, 1, 2, 3];
foreach (I, V; aliasSeqOf!([0, 1, 2, 3]))
{
    static assert(V == I);
    static assert(V == REF[I]);
}
template ApplyLeft(alias Template, args...)

template ApplyRight(alias Template, args...)
Partially applies Template by binding its first (left) or last (right) arguments to args.
Behaves like the identity function when args is empty.
Parameters:
Template template to partially apply
args arguments to bind
Returns:
Template with arity smaller than or equal to Template
Examples:
// enum bool isImplicitlyConvertible(From, To)
import std.traits : isImplicitlyConvertible;

static assert(allSatisfy!(
    ApplyLeft!(isImplicitlyConvertible, ubyte),
    short, ushort, int, uint, long, ulong));

static assert(is(Filter!(ApplyRight!(isImplicitlyConvertible, short),
    ubyte, string, short, float, int) == AliasSeq!(ubyte, short)));
Examples:
import std.traits : hasMember, ifTestable;

struct T1
{
    bool foo;
}

struct T2
{
    struct Test
    {
        bool opCast(T : bool)() { return true; }
    }

    Test foo;
}

static assert(allSatisfy!(ApplyRight!(hasMember, "foo"), T1, T2));
static assert(allSatisfy!(ApplyRight!(ifTestable, a => a.foo), T1, T2));
Examples:
import std.traits : Largest;

alias Types = AliasSeq!(byte, short, int, long);

static assert(is(staticMap!(ApplyLeft!(Largest, short), Types) ==
            AliasSeq!(short, short, int, long)));
static assert(is(staticMap!(ApplyLeft!(Largest, int), Types) ==
            AliasSeq!(int, int, int, long)));
Examples:
import std.traits : FunctionAttribute, SetFunctionAttributes;

static void foo() @system;
static int bar(int) @system;

alias SafeFunctions = AliasSeq!(
    void function() @safe,
    int function(int) @safe);

static assert(is(staticMap!(ApplyRight!(
    SetFunctionAttributes, "D", FunctionAttribute.safe),
    typeof(&foo), typeof(&bar)) == SafeFunctions));
template Repeat(size_t n, TList...)
Creates an AliasSeq which repeats TList exactly n times.
Examples:
alias ImInt0 = Repeat!(0, int);
static assert(is(ImInt0 == AliasSeq!()));

alias ImInt1 = Repeat!(1, immutable(int));
static assert(is(ImInt1 == AliasSeq!(immutable(int))));

alias Real3 = Repeat!(3, real);
static assert(is(Real3 == AliasSeq!(real, real, real)));

alias Real12 = Repeat!(4, Real3);
static assert(is(Real12 == AliasSeq!(real, real, real, real, real, real,
    real, real, real, real, real, real)));

alias Composite = AliasSeq!(uint, int);
alias Composite2 = Repeat!(2, Composite);
static assert(is(Composite2 == AliasSeq!(uint, int, uint, int)));

alias ImInt10 = Repeat!(10, int);
static assert(is(ImInt10 == AliasSeq!(int, int, int, int, int, int, int, int, int, int)));
Examples:
auto staticArray(T, size_t n)(Repeat!(n, T) elems)
{
    T[n] a = [elems];
    return a;
}

auto a = staticArray!(long, 3)(3, 1, 4);
assert(is(typeof(a) == long[3]));
writeln(a); // [3, 1, 4]
template staticSort(alias cmp, Seq...)
Sorts an AliasSeq using cmp.

Parameters cmp = A template that returns a bool (if its first argument is less than the second one) or an int (-1 means less than, 0 means equal, 1 means greater than)

Seq = The AliasSeq to sort

Returns:
The sorted alias sequence
Examples:
alias Nums = AliasSeq!(7, 2, 3, 23);
enum Comp(int N1, int N2) = N1 < N2;
static assert(AliasSeq!(2, 3, 7, 23) == staticSort!(Comp, Nums));
Examples:
alias Types = AliasSeq!(uint, short, ubyte, long, ulong);
enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
static assert(is(AliasSeq!(uint, ubyte, ulong, short, long) == staticSort!(Comp,
    Types)));
enum auto staticIsSorted(alias cmp, items...);
Checks if an AliasSeq is sorted according to cmp.

Parameters cmp = A template that returns a bool (if its first argument is less than the second one) or an int (-1 means less than, 0 means equal, 1 means greater than)

Seq = The AliasSeq to check

Returns:
true if Seq is sorted; otherwise false
Examples:
enum Comp(int N1, int N2) = N1 < N2;
static assert( staticIsSorted!(Comp, 2, 2));
static assert( staticIsSorted!(Comp, 2, 3, 7, 23));
static assert(!staticIsSorted!(Comp, 7, 2, 3, 23));
Examples:
enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
static assert( staticIsSorted!(Comp, uint, ubyte, ulong, short, long));
static assert(!staticIsSorted!(Comp, uint, short, ubyte, long, ulong));
template Stride(int stepSize, Args...) if (stepSize != 0)
Selects a subset of Args by stepping with fixed stepSize over the sequence. A negative stepSize starts iteration with the last element.
Parameters:
stepSize Number of elements to increment on each iteration. Can't be 0.
Args Template arguments.
Returns:
An AliasSeq filtered by the selected stride.
Examples:
static assert(is(Stride!(1, short, int, long) == AliasSeq!(short, int, long)));
static assert(is(Stride!(2, short, int, long) == AliasSeq!(short, long)));
static assert(is(Stride!(-1, short, int, long) == AliasSeq!(long, int, short)));
static assert(is(Stride!(-2, short, int, long) == AliasSeq!(long, short)));

alias attribs = AliasSeq!(short, int, long, ushort, uint, ulong);
static assert(is(Stride!(3, attribs) == AliasSeq!(short, ushort)));
static assert(is(Stride!(3, attribs[1 .. $]) == AliasSeq!(int, uint)));
static assert(is(Stride!(-3, attribs) == AliasSeq!(ulong, long)));
template Instantiate(alias Template, Params...)
Instantiates the given template with the given parameters.
Used to work around syntactic limitations of D with regard to instantiating a template from an alias sequence (e.g. T[0]!(...) is not valid) or a template returning another template (e.g. Foo!(Bar)!(Baz) is not allowed).
Parameters:
Template The template to instantiate.
Params The parameters with which to instantiate the template.
Returns:
The instantiated template.
Examples:
// ApplyRight combined with Instantiate can be used to apply various
// templates to the same parameters.
import std.string : leftJustify, center, rightJustify;
alias functions = staticMap!(ApplyRight!(Instantiate, string),
                             leftJustify, center, rightJustify);
string result = "";
static foreach (f; functions)
{
    {
        auto x = &f; // not a template, but a function instantiation
        result ~= x("hello", 7);
        result ~= ";";
    }
}

writeln(result); // "hello  ; hello ;  hello;"