// Written in the D programming language. /** * Templates to manipulate * $(DDSUBLINK spec/template, variadic-templates, template parameter sequences) * (also known as $(I 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 $(DDLINK ctarguments, Compile-time Sequences, Compile-time Sequences). * * $(B 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 $(I template predicates). * * $(SCRIPT inhibitQuickIndex = 1;) * $(DIVC quickindex, * $(BOOKTABLE , * $(TR $(TH Category) $(TH Templates)) * $(TR $(TD Building blocks) $(TD * $(LREF Alias) * $(LREF AliasSeq) * $(LREF aliasSeqOf) * )) * $(TR $(TD Alias sequence filtering) $(TD * $(LREF Erase) * $(LREF EraseAll) * $(LREF Filter) * $(LREF NoDuplicates) * $(LREF Stride) * )) * $(TR $(TD Alias sequence type hierarchy) $(TD * $(LREF DerivedToFront) * $(LREF MostDerived) * )) * $(TR $(TD Alias sequence transformation) $(TD * $(LREF Repeat) * $(LREF Replace) * $(LREF ReplaceAll) * $(LREF Reverse) * $(LREF staticMap) * $(LREF staticSort) * )) * $(TR $(TD Alias sequence searching) $(TD * $(LREF allSatisfy) * $(LREF anySatisfy) * $(LREF staticIndexOf) * )) * $(TR $(TD Template predicates) $(TD * $(LREF templateAnd) * $(LREF templateNot) * $(LREF templateOr) * $(LREF staticIsSorted) * )) * $(TR $(TD Template instantiation) $(TD * $(LREF ApplyLeft) * $(LREF ApplyRight) * $(LREF Instantiate) * )) * )) * * References: * Based on ideas in Table 3.1 from * $(LINK2 http://amazon.com/exec/obidos/ASIN/0201704315/ref=ase_classicempire/102-2957199-2585768, * Modern C++ Design), * Andrei Alexandrescu (Addison-Wesley Professional, 2001) * Copyright: Copyright The D Language Foundation 2005 - 2015. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: * $(HTTP digitalmars.com, Walter Bright), * $(HTTP klickverbot.at, David Nadlinger) * Source: $(PHOBOSSRC std/meta.d) */ module std.meta; import std.traits : isAggregateType, Unqual, isIterable;import std.range.primitives : isInfinite; /** * 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`. */alias AliasSeq(TList...) = TList; ///@safe unittest{ 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]; }} ///@safe unittest{ alias TL = AliasSeq!(int, double); alias Types = AliasSeq!(TL, char); static assert(is(Types == AliasSeq!(int, double, char)));} ///@safe unittest{ // 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) { assert(a == 4); assert(b == 16); } static int a = 2; static int b = 4; test(Map!(i => i ^^ 2, a, b)); assert(a == 2); assert(b == 4); test(Map!((ref i) => i *= i, a, b)); assert(a == 4); assert(b == 16); static void testRef(ref int a, ref int b) { assert(a++ == 16); assert(b++ == 256); } testRef(Map!(function ref(ref i) => i *= i, a, b)); assert(a == 17); assert(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; //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 $(LREF AliasSeq). */alias Alias(alias a) = a; ///@safe unittest{ // 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");} ///@safe unittest{ 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; assert(g == 7);} /** * Returns the index of the first occurrence of `A` in the * sequence `args`. `A` and `args` may be types or compile-time values. * If not found, `-1` is returned. */template staticIndexOf(alias A, args...){ enum staticIndexOf = { static foreach (idx, arg; args) static if (isSame!(A, arg)) // `if (__ctfe)` is redundant here but avoids the "Unreachable code" warning. if (__ctfe) return idx; return -1; }();} ///@safe unittest{ alias Types = AliasSeq!(int, long, double); static assert(staticIndexOf!(long, Types) == 1); static assert(staticIndexOf!(void, 0, "void", void) == 2);} @safe unittest{ static assert(staticIndexOf!( byte, byte, short, int, long) == 0); static assert(staticIndexOf!(short, byte, short, int, long) == 1); static assert(staticIndexOf!( int, byte, short, int, long) == 2); static assert(staticIndexOf!( long, byte, short, int, long) == 3); static assert(staticIndexOf!( char, byte, short, int, long) == -1); static assert(staticIndexOf!( -1, byte, short, int, long) == -1); static assert(staticIndexOf!(void) == -1); static assert(staticIndexOf!("abc", "abc", "def", "ghi", "jkl") == 0); static assert(staticIndexOf!("def", "abc", "def", "ghi", "jkl") == 1); static assert(staticIndexOf!("ghi", "abc", "def", "ghi", "jkl") == 2); static assert(staticIndexOf!("jkl", "abc", "def", "ghi", "jkl") == 3); static assert(staticIndexOf!("mno", "abc", "def", "ghi", "jkl") == -1); static assert(staticIndexOf!( void, "abc", "def", "ghi", "jkl") == -1); static assert(staticIndexOf!(42) == -1); static assert(staticIndexOf!(void, 0, "void", void) == 2); static assert(staticIndexOf!("void", 0, void, "void") == 2);} /** * Returns an `AliasSeq` created from `args` with the first occurrence, * if any, of `A` removed. */template Erase(alias A, args...){ private enum pos = staticIndexOf!(A, args); static if (pos < 0) alias Erase = args; else alias Erase = AliasSeq!(args[0 .. pos], args[pos + 1 .. $]);} ///@safe unittest{ alias Types = AliasSeq!(int, long, double, char); alias TL = Erase!(long, Types); static assert(is(TL == AliasSeq!(int, double, char)));} @safe unittest{ static assert(Pack!(Erase!(int, short, int, int, 4)). equals!(short, int, 4)); static assert(Pack!(Erase!(1, real, 3, 1, 4, 1, 5, 9)). equals!(real, 3, 4, 1, 5, 9));} /** * Returns an `AliasSeq` created from `args` with all occurrences, * if any, of `A` removed. */template EraseAll(alias A, args...){ alias EraseAll = AliasSeq!(); static foreach (arg; args) static if (!isSame!(A, arg)) EraseAll = AliasSeq!(EraseAll, arg);} ///@safe unittest{ alias Types = AliasSeq!(int, long, long, int); static assert(is(EraseAll!(long, Types) == AliasSeq!(int, int)));} @safe unittest{ static assert(Pack!(EraseAll!(int, short, int, int, 4)). equals!(short, 4)); static assert(Pack!(EraseAll!(1, real, 3, 1, 4, 1, 5, 9)). equals!(real, 3, 4, 5, 9));} /* * Returns `items[0 .. $ - 1]` if `item[$ - 1]` found in `items[0 .. $ - 1]`, and * `items` otherwise. * * Params: * items = list to be processed * * See_Also: $(LREF NoDuplicates) */private template AppendUnique(items...){ alias head = items[0 .. $ - 1]; static if (staticIndexOf!(items[$ - 1], head) >= 0) alias AppendUnique = head; else alias AppendUnique = items;} /** * Returns an `AliasSeq` created from `args` with all duplicate * types removed. */template NoDuplicates(args...){ alias NoDuplicates = AliasSeq!(); static foreach (arg; args) NoDuplicates = AppendUnique!(NoDuplicates, arg);} ///@safe unittest{ alias Types = AliasSeq!(int, long, long, int, float); alias TL = NoDuplicates!(Types); static assert(is(TL == AliasSeq!(int, long, float)));} @safe unittest{ import std.range : iota; // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums alias LongList = Repeat!(1500, int); static assert(NoDuplicates!LongList.length == 1); // https://issues.dlang.org/show_bug.cgi?id=17995: huge enums, revisited alias a = NoDuplicates!(AliasSeq!(1, Repeat!(1000, 3))); alias b = NoDuplicates!(AliasSeq!(1, Repeat!(10, 3))); static assert(a.length == b.length); static assert(NoDuplicates!(aliasSeqOf!(iota(7)), aliasSeqOf!(iota(7))) == aliasSeqOf!(iota(7))); static assert(NoDuplicates!(aliasSeqOf!(iota(8)), aliasSeqOf!(iota(8))) == aliasSeqOf!(iota(8)));} @safe unittest{ static assert( Pack!( NoDuplicates!(1, int, 1, NoDuplicates, int, NoDuplicates, real)) .equals!(1, int, NoDuplicates, real));} /** * Returns an `AliasSeq` created from `Args` with the first occurrence * of T, if found, replaced with U. */template Replace(alias T, alias U, Args...){ static if (Args.length) { alias head = Args[0 .. 1]; // use unary sequence instead of Alias alias tail = Args[1 .. $]; static if (isSame!(T, head)) alias Replace = AliasSeq!(U, tail); else alias Replace = AliasSeq!(head, Replace!(T, U, tail)); } else { alias Replace = AliasSeq!(); }} ///@safe unittest{ alias Types = AliasSeq!(int, long, long, int, float); alias TL = Replace!(long, char, Types); static assert(is(TL == AliasSeq!(int, char, long, int, float)));} @safe unittest{ static assert(Pack!(Replace!(byte, ubyte, short, byte, byte, byte)). equals!(short, ubyte, byte, byte)); static assert(Pack!(Replace!(1111, byte, 2222, 1111, 1111, 1111)). equals!(2222, byte, 1111, 1111)); static assert(Pack!(Replace!(byte, 1111, short, byte, byte, byte)). equals!(short, 1111, byte, byte)); static assert(Pack!(Replace!(1111, "11", 2222, 1111, 1111, 1111)). equals!(2222, "11", 1111, 1111));} /** * Returns an `AliasSeq` created from `args` with all occurrences * of T, if found, replaced with U. */template ReplaceAll(alias T, alias U, args...){ alias ReplaceAll = AliasSeq!(); static foreach (arg; args) { static if (isSame!(T, arg)) ReplaceAll = AliasSeq!(ReplaceAll, U); else ReplaceAll = AliasSeq!(ReplaceAll, arg); }} ///@safe unittest{ alias Types = AliasSeq!(int, long, long, int, float); alias TL = ReplaceAll!(long, char, Types); static assert(is(TL == AliasSeq!(int, char, char, int, float)));} @safe unittest{ static assert(Pack!(ReplaceAll!(byte, ubyte, byte, short, byte, byte)). equals!(ubyte, short, ubyte, ubyte)); static assert(Pack!(ReplaceAll!(1111, byte, 1111, 2222, 1111, 1111)). equals!(byte, 2222, byte, byte)); static assert(Pack!(ReplaceAll!(byte, 1111, byte, short, byte, byte)). equals!(1111, short, 1111, 1111)); static assert(Pack!(ReplaceAll!(1111, "11", 1111, 2222, 1111, 1111)). equals!("11", 2222, "11", "11"));} /** * Returns an `AliasSeq` created from `args` with the order reversed. */template Reverse(args...){ alias Reverse = AliasSeq!(); static foreach_reverse (arg; args) Reverse = AliasSeq!(Reverse, arg);} Lines 1–500 of 1462. Load more
// Written in the D programming language. /** * Templates to manipulate * $(DDSUBLINK spec/template, variadic-templates, template parameter sequences) * (also known as $(I 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 $(DDLINK ctarguments, Compile-time Sequences, Compile-time Sequences). * * $(B 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 $(I template predicates). * * $(SCRIPT inhibitQuickIndex = 1;) * $(DIVC quickindex, * $(BOOKTABLE , * $(TR $(TH Category) $(TH Templates)) * $(TR $(TD Building blocks) $(TD * $(LREF Alias) * $(LREF AliasSeq) * $(LREF aliasSeqOf) * )) * $(TR $(TD Alias sequence filtering) $(TD * $(LREF Erase) * $(LREF EraseAll) * $(LREF Filter) * $(LREF NoDuplicates) * $(LREF Stride) * )) * $(TR $(TD Alias sequence type hierarchy) $(TD * $(LREF DerivedToFront) * $(LREF MostDerived) * )) * $(TR $(TD Alias sequence transformation) $(TD * $(LREF Repeat) * $(LREF Replace) * $(LREF ReplaceAll) * $(LREF Reverse) * $(LREF staticMap) * $(LREF staticSort) * )) * $(TR $(TD Alias sequence searching) $(TD * $(LREF allSatisfy) * $(LREF anySatisfy) * $(LREF staticIndexOf) * )) * $(TR $(TD Template predicates) $(TD * $(LREF templateAnd) * $(LREF templateNot) * $(LREF templateOr) * $(LREF staticIsSorted) * )) * $(TR $(TD Template instantiation) $(TD * $(LREF ApplyLeft) * $(LREF ApplyRight) * $(LREF Instantiate) * )) * )) * * References: * Based on ideas in Table 3.1 from * $(LINK2 http://amazon.com/exec/obidos/ASIN/0201704315/ref=ase_classicempire/102-2957199-2585768, * Modern C++ Design), * Andrei Alexandrescu (Addison-Wesley Professional, 2001) * Copyright: Copyright The D Language Foundation 2005 - 2015. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: * $(HTTP digitalmars.com, Walter Bright), * $(HTTP klickverbot.at, David Nadlinger) * Source: $(PHOBOSSRC std/meta.d) */ module std.meta; import std.traits : isAggregateType, Unqual, isIterable; import std.range.primitives : isInfinite; /** * 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`. */ alias AliasSeq(TList...) = TList; /// @safe unittest { 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]; } } /// @safe unittest { alias TL = AliasSeq!(int, double); alias Types = AliasSeq!(TL, char); static assert(is(Types == AliasSeq!(int, double, char))); } /// @safe unittest { // 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) { assert(a == 4); assert(b == 16); } static int a = 2; static int b = 4; test(Map!(i => i ^^ 2, a, b)); assert(a == 2); assert(b == 4); test(Map!((ref i) => i *= i, a, b)); assert(a == 4); assert(b == 16); static void testRef(ref int a, ref int b) { assert(a++ == 16); assert(b++ == 256); } testRef(Map!(function ref(ref i) => i *= i, a, b)); assert(a == 17); assert(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; //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 $(LREF AliasSeq). */ alias Alias(alias a) = a; /// @safe unittest { // 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"); } /// @safe unittest { 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; assert(g == 7); } /** * Returns the index of the first occurrence of `A` in the * sequence `args`. `A` and `args` may be types or compile-time values. * If not found, `-1` is returned. */ template staticIndexOf(alias A, args...) { enum staticIndexOf = { static foreach (idx, arg; args) static if (isSame!(A, arg)) // `if (__ctfe)` is redundant here but avoids the "Unreachable code" warning. if (__ctfe) return idx; return -1; }(); } /// @safe unittest { alias Types = AliasSeq!(int, long, double); static assert(staticIndexOf!(long, Types) == 1); static assert(staticIndexOf!(void, 0, "void", void) == 2); } @safe unittest { static assert(staticIndexOf!( byte, byte, short, int, long) == 0); static assert(staticIndexOf!(short, byte, short, int, long) == 1); static assert(staticIndexOf!( int, byte, short, int, long) == 2); static assert(staticIndexOf!( long, byte, short, int, long) == 3); static assert(staticIndexOf!( char, byte, short, int, long) == -1); static assert(staticIndexOf!( -1, byte, short, int, long) == -1); static assert(staticIndexOf!(void) == -1); static assert(staticIndexOf!("abc", "abc", "def", "ghi", "jkl") == 0); static assert(staticIndexOf!("def", "abc", "def", "ghi", "jkl") == 1); static assert(staticIndexOf!("ghi", "abc", "def", "ghi", "jkl") == 2); static assert(staticIndexOf!("jkl", "abc", "def", "ghi", "jkl") == 3); static assert(staticIndexOf!("mno", "abc", "def", "ghi", "jkl") == -1); static assert(staticIndexOf!( void, "abc", "def", "ghi", "jkl") == -1); static assert(staticIndexOf!(42) == -1); static assert(staticIndexOf!(void, 0, "void", void) == 2); static assert(staticIndexOf!("void", 0, void, "void") == 2); } /** * Returns an `AliasSeq` created from `args` with the first occurrence, * if any, of `A` removed. */ template Erase(alias A, args...) { private enum pos = staticIndexOf!(A, args); static if (pos < 0) alias Erase = args; else alias Erase = AliasSeq!(args[0 .. pos], args[pos + 1 .. $]); } /// @safe unittest { alias Types = AliasSeq!(int, long, double, char); alias TL = Erase!(long, Types); static assert(is(TL == AliasSeq!(int, double, char))); } @safe unittest { static assert(Pack!(Erase!(int, short, int, int, 4)). equals!(short, int, 4)); static assert(Pack!(Erase!(1, real, 3, 1, 4, 1, 5, 9)). equals!(real, 3, 4, 1, 5, 9)); } /** * Returns an `AliasSeq` created from `args` with all occurrences, * if any, of `A` removed. */ template EraseAll(alias A, args...) { alias EraseAll = AliasSeq!(); static foreach (arg; args) static if (!isSame!(A, arg)) EraseAll = AliasSeq!(EraseAll, arg); } /// @safe unittest { alias Types = AliasSeq!(int, long, long, int); static assert(is(EraseAll!(long, Types) == AliasSeq!(int, int))); } @safe unittest { static assert(Pack!(EraseAll!(int, short, int, int, 4)). equals!(short, 4)); static assert(Pack!(EraseAll!(1, real, 3, 1, 4, 1, 5, 9)). equals!(real, 3, 4, 5, 9)); } /* * Returns `items[0 .. $ - 1]` if `item[$ - 1]` found in `items[0 .. $ - 1]`, and * `items` otherwise. * * Params: * items = list to be processed * * See_Also: $(LREF NoDuplicates) */ private template AppendUnique(items...) { alias head = items[0 .. $ - 1]; static if (staticIndexOf!(items[$ - 1], head) >= 0) alias AppendUnique = head; else alias AppendUnique = items; } /** * Returns an `AliasSeq` created from `args` with all duplicate * types removed. */ template NoDuplicates(args...) { alias NoDuplicates = AliasSeq!(); static foreach (arg; args) NoDuplicates = AppendUnique!(NoDuplicates, arg); } /// @safe unittest { alias Types = AliasSeq!(int, long, long, int, float); alias TL = NoDuplicates!(Types); static assert(is(TL == AliasSeq!(int, long, float))); } @safe unittest { import std.range : iota; // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums alias LongList = Repeat!(1500, int); static assert(NoDuplicates!LongList.length == 1); // https://issues.dlang.org/show_bug.cgi?id=17995: huge enums, revisited alias a = NoDuplicates!(AliasSeq!(1, Repeat!(1000, 3))); alias b = NoDuplicates!(AliasSeq!(1, Repeat!(10, 3))); static assert(a.length == b.length); static assert(NoDuplicates!(aliasSeqOf!(iota(7)), aliasSeqOf!(iota(7))) == aliasSeqOf!(iota(7))); static assert(NoDuplicates!(aliasSeqOf!(iota(8)), aliasSeqOf!(iota(8))) == aliasSeqOf!(iota(8))); } @safe unittest { static assert( Pack!( NoDuplicates!(1, int, 1, NoDuplicates, int, NoDuplicates, real)) .equals!(1, int, NoDuplicates, real)); } /** * Returns an `AliasSeq` created from `Args` with the first occurrence * of T, if found, replaced with U. */ template Replace(alias T, alias U, Args...) { static if (Args.length) { alias head = Args[0 .. 1]; // use unary sequence instead of Alias alias tail = Args[1 .. $]; static if (isSame!(T, head)) alias Replace = AliasSeq!(U, tail); else alias Replace = AliasSeq!(head, Replace!(T, U, tail)); } else { alias Replace = AliasSeq!(); } } /// @safe unittest { alias Types = AliasSeq!(int, long, long, int, float); alias TL = Replace!(long, char, Types); static assert(is(TL == AliasSeq!(int, char, long, int, float))); } @safe unittest { static assert(Pack!(Replace!(byte, ubyte, short, byte, byte, byte)). equals!(short, ubyte, byte, byte)); static assert(Pack!(Replace!(1111, byte, 2222, 1111, 1111, 1111)). equals!(2222, byte, 1111, 1111)); static assert(Pack!(Replace!(byte, 1111, short, byte, byte, byte)). equals!(short, 1111, byte, byte)); static assert(Pack!(Replace!(1111, "11", 2222, 1111, 1111, 1111)). equals!(2222, "11", 1111, 1111)); } /** * Returns an `AliasSeq` created from `args` with all occurrences * of T, if found, replaced with U. */ template ReplaceAll(alias T, alias U, args...) { alias ReplaceAll = AliasSeq!(); static foreach (arg; args) { static if (isSame!(T, arg)) ReplaceAll = AliasSeq!(ReplaceAll, U); else ReplaceAll = AliasSeq!(ReplaceAll, arg); } } /// @safe unittest { alias Types = AliasSeq!(int, long, long, int, float); alias TL = ReplaceAll!(long, char, Types); static assert(is(TL == AliasSeq!(int, char, char, int, float))); } @safe unittest { static assert(Pack!(ReplaceAll!(byte, ubyte, byte, short, byte, byte)). equals!(ubyte, short, ubyte, ubyte)); static assert(Pack!(ReplaceAll!(1111, byte, 1111, 2222, 1111, 1111)). equals!(byte, 2222, byte, byte)); static assert(Pack!(ReplaceAll!(byte, 1111, byte, short, byte, byte)). equals!(1111, short, 1111, 1111)); static assert(Pack!(ReplaceAll!(1111, "11", 1111, 2222, 1111, 1111)). equals!("11", 2222, "11", "11")); } /** * Returns an `AliasSeq` created from `args` with the order reversed. */ template Reverse(args...) { alias Reverse = AliasSeq!(); static foreach_reverse (arg; args) Reverse = AliasSeq!(Reverse, arg); }