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 |
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
.
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]; }
alias TL = AliasSeq!(int, double); alias Types = AliasSeq!(TL, char); static assert(is(Types == AliasSeq!(int, double, char)));
AliasSeq
expression of Func
being applied to every variadic template argument. auto ref ArgCall(alias Func, alias arg)() { return Func(arg); } template Map(alias Func, args...) { static if (args.length > 1) { alias Map = AliasSeq!(ArgCall!(Func, args[0]), Map!(Func, args[1 .. $])); } else { alias Map = ArgCall!(Func, args[0]); } } static int square(int arg) { return arg * arg; } static int refSquare(ref int arg) { arg *= arg; return arg; } static ref int refRetSquare(ref int arg) { arg *= arg; return arg; } static void test(int a, int b) { writeln(a); // 4 writeln(b); // 16 } static void testRef(ref int a, ref int b) { writeln(a++); // 16 writeln(b++); // 256 } static int a = 2; static int b = 4; test(Map!(square, a, b)); test(Map!(refSquare, a, b)); writeln(a); // 4 writeln(b); // 16 testRef(Map!(refRetSquare, a, b)); writeln(a); // 17 writeln(b); // 257
Allows alias
ing 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; //ErrorWith this template any single entity can be aliased:
alias b = Alias!4; //OK
AliasSeq
.// 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");
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
Returns the index of the first occurrence of type T in the sequence of zero or more types TList. If not found, -1 is returned.
Returns an AliasSeq
created from TList with the first occurrence, if any, of T removed.
Returns an AliasSeq
created from TList with the all occurrences, if any, of T removed.
Returns an AliasSeq
created from TList with the all duplicate types removed.
Returns an AliasSeq
created from TList with the first occurrence of type T, if found, replaced with type U.
Returns an AliasSeq
created from TList with all occurrences of type T, if found, replaced with type U.
Returns an AliasSeq
created from TList with the order reversed.
Returns the type from TList that is the most derived from type T. If none are found, T is returned.
Returns an AliasSeq
with the elements of TList sorted so that the most derived types come first.
Evaluates to AliasSeq!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))
.
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.
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.
Filters an AliasSeq
using a template predicate. Returns an AliasSeq
of the elements which satisfy the predicate.
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)));
Negates the passed template predicate.
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.
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);
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.
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);
Converts any foreach-iterable entity (e.g. an input range) to an alias sequence.
iter | the entity to convert into an AliasSeq . It must be able to be able to be iterated over using a foreach-statement. |
AliasSeq
containing the values produced by iterating over iter
.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");
Partially applies Template by binding its first (left) or last (right) arguments to args.
Behaves like the identity function when args is empty.
Template | template to partially apply |
args | arguments to bind |
// 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)));
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));
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)));
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));
Creates an AliasSeq
which repeats TList
exactly n
times.
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)));
Sorts an AliasSeq
using cmp
.
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) AliasSeq
to sort Checks if an AliasSeq
is sorted according to cmp
.
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) AliasSeq
to check true
if Seq
is sorted; otherwise false
Selects a subset of Args
by stepping with fixed stepSize
over the sequence. A negative stepSize
starts iteration with the last element.
stepSize | Number of elements to increment on each iteration. Can't be 0 . |
Args | Template arguments. |
AliasSeq
filtered by the selected stride.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)));
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).
Template | The template to instantiate. |
Params | The parameters with which to instantiate the template. |
// 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;"
© 1999–2019 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_meta.html