Wolfgang Thallergcc16 merge934c3885 months agoHistory
1462 lines · 38.8 KB · D
RawDownload
// 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t