1// Written in the D programming language.
2
3/**
4 * Templates to manipulate template argument lists (also known as type lists).
5 *
6 * Some operations on alias sequences are built in to the language,
7 * such as TL[$(I n)] which gets the $(I n)th type from the
8 * alias sequence. TL[$(I lwr) .. $(I upr)] returns a new type
9 * list that is a slice of the old one.
10 *
11 * Several templates in this module use or operate on eponymous templates that
12 * take a single argument and evaluate to a boolean constant. Such templates
13 * are referred to as $(I template predicates).
14 *
15 * $(SCRIPT inhibitQuickIndex = 1;)
16 * $(DIVC quickindex,
17 * $(BOOKTABLE ,
18 * $(TR $(TH Category) $(TH Templates))
19 * $(TR $(TD Building blocks) $(TD
20 *           $(LREF Alias)
21 *           $(LREF AliasSeq)
22 *           $(LREF aliasSeqOf)
23 * ))
24 * $(TR $(TD Alias sequence filtering) $(TD
25 *           $(LREF Erase)
26 *           $(LREF EraseAll)
27 *           $(LREF Filter)
28 *           $(LREF NoDuplicates)
29 *           $(LREF Stride)
30 * ))
31 * $(TR $(TD Alias sequence type hierarchy) $(TD
32 *           $(LREF DerivedToFront)
33 *           $(LREF MostDerived)
34 * ))
35 * $(TR $(TD Alias sequence transformation) $(TD
36 *           $(LREF Repeat)
37 *           $(LREF Replace)
38 *           $(LREF ReplaceAll)
39 *           $(LREF Reverse)
40 *           $(LREF staticMap)
41 *           $(LREF staticSort)
42 * ))
43 * $(TR $(TD Alias sequence searching) $(TD
44 *           $(LREF allSatisfy)
45 *           $(LREF anySatisfy)
46 *           $(LREF staticIndexOf)
47 * ))
48 * $(TR $(TD Template predicates) $(TD
49 *           $(LREF templateAnd)
50 *           $(LREF templateNot)
51 *           $(LREF templateOr)
52 *           $(LREF staticIsSorted)
53 * ))
54 * $(TR $(TD Template instantiation) $(TD
55 *           $(LREF ApplyLeft)
56 *           $(LREF ApplyRight)
57 * ))
58 * ))
59 *
60 * References:
61 *  Based on ideas in Table 3.1 from
62 *  $(LINK2 http://amazon.com/exec/obidos/ASIN/0201704315/ref=ase_classicempire/102-2957199-2585768,
63 *      Modern C++ Design),
64 *   Andrei Alexandrescu (Addison-Wesley Professional, 2001)
65 * Copyright: Copyright Digital Mars 2005 - 2015.
66 * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
67 * Authors:
68 *     $(HTTP digitalmars.com, Walter Bright),
69 *     $(HTTP klickverbot.at, David Nadlinger)
70 * Source:    $(PHOBOSSRC std/_meta.d)
71 */
72
73module std.meta;
74
75/**
76 * Creates a sequence of zero or more aliases. This is most commonly
77 * used as template parameters or arguments.
78 *
79 * In previous versions of Phobos, this was known as `TypeTuple`.
80 */
81template AliasSeq(TList...)
82{
83    alias AliasSeq = TList;
84}
85
86///
87@safe unittest
88{
89    import std.meta;
90    alias TL = AliasSeq!(int, double);
91
92    int foo(TL td)  // same as int foo(int, double);
93    {
94        return td[0] + cast(int) td[1];
95    }
96}
97
98///
99@safe unittest
100{
101    alias TL = AliasSeq!(int, double);
102
103    alias Types = AliasSeq!(TL, char);
104    static assert(is(Types == AliasSeq!(int, double, char)));
105}
106
107
108/**
109  Returns an `AliasSeq` expression of `Func` being
110  applied to every variadic template argument.
111 */
112
113///
114@safe unittest
115{
116    auto ref ArgCall(alias Func, alias arg)()
117    {
118        return Func(arg);
119    }
120
121    template Map(alias Func, args...)
122    {
123        static if (args.length > 1)
124        {
125            alias Map = AliasSeq!(ArgCall!(Func, args[0]), Map!(Func, args[1 .. $]));
126        }
127        else
128        {
129            alias Map = ArgCall!(Func, args[0]);
130        }
131    }
132
133    static int square(int arg)
134    {
135        return arg * arg;
136    }
137
138    static int refSquare(ref int arg)
139    {
140        arg *= arg;
141        return arg;
142    }
143
144    static ref int refRetSquare(ref int arg)
145    {
146        arg *= arg;
147        return arg;
148    }
149
150    static void test(int a, int b)
151    {
152        assert(a == 4);
153        assert(b == 16);
154    }
155
156    static void testRef(ref int a, ref int b)
157    {
158        assert(a++ == 16);
159        assert(b++ == 256);
160    }
161
162    static int a = 2;
163    static int b = 4;
164
165    test(Map!(square, a, b));
166
167    test(Map!(refSquare, a, b));
168    assert(a == 4);
169    assert(b == 16);
170
171    testRef(Map!(refRetSquare, a, b));
172    assert(a == 17);
173    assert(b == 257);
174}
175
176/**
177 * Allows `alias`ing of any single symbol, type or compile-time expression.
178 *
179 * Not everything can be directly aliased. An alias cannot be declared
180 * of - for example - a literal:
181 *
182 * `alias a = 4; //Error`
183 *
184 * With this template any single entity can be aliased:
185 *
186 * `alias b = Alias!4; //OK`
187 *
188 * See_Also:
189 * To alias more than one thing at once, use $(LREF AliasSeq)
190 */
191alias Alias(alias a) = a;
192
193/// Ditto
194alias Alias(T) = T;
195
196///
197@safe unittest
198{
199    // Without Alias this would fail if Args[0] was e.g. a value and
200    // some logic would be needed to detect when to use enum instead
201    alias Head(Args ...) = Alias!(Args[0]);
202    alias Tail(Args ...) = Args[1 .. $];
203
204    alias Blah = AliasSeq!(3, int, "hello");
205    static assert(Head!Blah == 3);
206    static assert(is(Head!(Tail!Blah) == int));
207    static assert((Tail!Blah)[1] == "hello");
208}
209
210///
211@safe unittest
212{
213    alias a = Alias!(123);
214    static assert(a == 123);
215
216    enum abc = 1;
217    alias b = Alias!(abc);
218    static assert(b == 1);
219
220    alias c = Alias!(3 + 4);
221    static assert(c == 7);
222
223    alias concat = (s0, s1) => s0 ~ s1;
224    alias d = Alias!(concat("Hello", " World!"));
225    static assert(d == "Hello World!");
226
227    alias e = Alias!(int);
228    static assert(is(e == int));
229
230    alias f = Alias!(AliasSeq!(int));
231    static assert(!is(typeof(f[0]))); //not an AliasSeq
232    static assert(is(f == int));
233
234    auto g = 6;
235    alias h = Alias!g;
236    ++h;
237    assert(g == 7);
238}
239
240package template OldAlias(alias a)
241{
242    static if (__traits(compiles, { alias x = a; }))
243        alias OldAlias = a;
244    else static if (__traits(compiles, { enum x = a; }))
245        enum OldAlias = a;
246    else
247        static assert(0, "Cannot alias " ~ a.stringof);
248}
249
250import std.traits : isAggregateType, Unqual;
251
252package template OldAlias(T)
253if (!isAggregateType!T || is(Unqual!T == T))
254{
255    alias OldAlias = T;
256}
257
258@safe unittest
259{
260    static struct Foo {}
261    static assert(is(OldAlias!(const(Foo)) == Foo));
262    static assert(is(OldAlias!(const(int)) == const(int)));
263    static assert(OldAlias!123 == 123);
264    enum abc = 123;
265    static assert(OldAlias!abc == 123);
266}
267
268/**
269 * Returns the index of the first occurrence of type T in the
270 * sequence of zero or more types TList.
271 * If not found, -1 is returned.
272 */
273template staticIndexOf(T, TList...)
274{
275    enum staticIndexOf = genericIndexOf!(T, TList).index;
276}
277
278/// Ditto
279template staticIndexOf(alias T, TList...)
280{
281    enum staticIndexOf = genericIndexOf!(T, TList).index;
282}
283
284///
285@safe unittest
286{
287    import std.stdio;
288
289    void foo()
290    {
291        writefln("The index of long is %s",
292                 staticIndexOf!(long, AliasSeq!(int, long, double)));
293        // prints: The index of long is 1
294    }
295}
296
297// [internal]
298private template genericIndexOf(args...)
299if (args.length >= 1)
300{
301    alias e     = OldAlias!(args[0]);
302    alias tuple = args[1 .. $];
303
304    static if (tuple.length)
305    {
306        alias head = OldAlias!(tuple[0]);
307        alias tail = tuple[1 .. $];
308
309        static if (isSame!(e, head))
310        {
311            enum index = 0;
312        }
313        else
314        {
315            enum next  = genericIndexOf!(e, tail).index;
316            enum index = (next == -1) ? -1 : 1 + next;
317        }
318    }
319    else
320    {
321        enum index = -1;
322    }
323}
324
325@safe unittest
326{
327    static assert(staticIndexOf!( byte, byte, short, int, long) ==  0);
328    static assert(staticIndexOf!(short, byte, short, int, long) ==  1);
329    static assert(staticIndexOf!(  int, byte, short, int, long) ==  2);
330    static assert(staticIndexOf!( long, byte, short, int, long) ==  3);
331    static assert(staticIndexOf!( char, byte, short, int, long) == -1);
332    static assert(staticIndexOf!(   -1, byte, short, int, long) == -1);
333    static assert(staticIndexOf!(void) == -1);
334
335    static assert(staticIndexOf!("abc", "abc", "def", "ghi", "jkl") ==  0);
336    static assert(staticIndexOf!("def", "abc", "def", "ghi", "jkl") ==  1);
337    static assert(staticIndexOf!("ghi", "abc", "def", "ghi", "jkl") ==  2);
338    static assert(staticIndexOf!("jkl", "abc", "def", "ghi", "jkl") ==  3);
339    static assert(staticIndexOf!("mno", "abc", "def", "ghi", "jkl") == -1);
340    static assert(staticIndexOf!( void, "abc", "def", "ghi", "jkl") == -1);
341    static assert(staticIndexOf!(42) == -1);
342
343    static assert(staticIndexOf!(void, 0, "void", void) == 2);
344    static assert(staticIndexOf!("void", 0, void, "void") == 2);
345}
346
347/**
348 * Returns an `AliasSeq` created from TList with the first occurrence,
349 * if any, of T removed.
350 */
351template Erase(T, TList...)
352{
353    alias Erase = GenericErase!(T, TList).result;
354}
355
356/// Ditto
357template Erase(alias T, TList...)
358{
359    alias Erase = GenericErase!(T, TList).result;
360}
361
362///
363@safe unittest
364{
365    alias Types = AliasSeq!(int, long, double, char);
366    alias TL = Erase!(long, Types);
367    static assert(is(TL == AliasSeq!(int, double, char)));
368}
369
370// [internal]
371private template GenericErase(args...)
372if (args.length >= 1)
373{
374    alias e     = OldAlias!(args[0]);
375    alias tuple = args[1 .. $] ;
376
377    static if (tuple.length)
378    {
379        alias head = OldAlias!(tuple[0]);
380        alias tail = tuple[1 .. $];
381
382        static if (isSame!(e, head))
383            alias result = tail;
384        else
385            alias result = AliasSeq!(head, GenericErase!(e, tail).result);
386    }
387    else
388    {
389        alias result = AliasSeq!();
390    }
391}
392
393@safe unittest
394{
395    static assert(Pack!(Erase!(int,
396                short, int, int, 4)).
397        equals!(short,      int, 4));
398
399    static assert(Pack!(Erase!(1,
400                real, 3, 1, 4, 1, 5, 9)).
401        equals!(real, 3,    4, 1, 5, 9));
402}
403
404
405/**
406 * Returns an `AliasSeq` created from TList with the all occurrences,
407 * if any, of T removed.
408 */
409template EraseAll(T, TList...)
410{
411    alias EraseAll = GenericEraseAll!(T, TList).result;
412}
413
414/// Ditto
415template EraseAll(alias T, TList...)
416{
417    alias EraseAll = GenericEraseAll!(T, TList).result;
418}
419
420///
421@safe unittest
422{
423    alias Types = AliasSeq!(int, long, long, int);
424
425    alias TL = EraseAll!(long, Types);
426    static assert(is(TL == AliasSeq!(int, int)));
427}
428
429// [internal]
430private template GenericEraseAll(args...)
431if (args.length >= 1)
432{
433    alias e     = OldAlias!(args[0]);
434    alias tuple = args[1 .. $];
435
436    static if (tuple.length)
437    {
438        alias head = OldAlias!(tuple[0]);
439        alias tail = tuple[1 .. $];
440        alias next = AliasSeq!(
441            GenericEraseAll!(e, tail[0..$/2]).result,
442            GenericEraseAll!(e, tail[$/2..$]).result
443            );
444
445        static if (isSame!(e, head))
446            alias result = next;
447        else
448            alias result = AliasSeq!(head, next);
449    }
450    else
451    {
452        alias result = AliasSeq!();
453    }
454}
455
456@safe unittest
457{
458    static assert(Pack!(EraseAll!(int,
459                short, int, int, 4)).
460        equals!(short,           4));
461
462    static assert(Pack!(EraseAll!(1,
463                real, 3, 1, 4, 1, 5, 9)).
464        equals!(real, 3,    4,    5, 9));
465}
466
467
468/**
469 * Returns an `AliasSeq` created from TList with the all duplicate
470 * types removed.
471 */
472template NoDuplicates(TList...)
473{
474    template EraseAllN(uint N, T...)
475    {
476        static if (N <= 1)
477        {
478            alias EraseAllN = T;
479        }
480        else
481        {
482            alias EraseAllN = EraseAllN!(N-1, T[1 .. N], EraseAll!(T[0], T[N..$]));
483        }
484    }
485    static if (TList.length > 500)
486    {
487        enum steps = 16;
488        alias first = NoDuplicates!(TList[0 .. steps]);
489        alias NoDuplicates = NoDuplicates!(EraseAllN!(first.length, first, TList[steps..$]));
490    }
491    else static if (TList.length == 0)
492    {
493        alias NoDuplicates = TList;
494    }
495    else
496    {
497        alias NoDuplicates =
498            AliasSeq!(TList[0], NoDuplicates!(EraseAll!(TList[0], TList[1 .. $])));
499    }
500}
501
502///
503@safe unittest
504{
505    alias Types = AliasSeq!(int, long, long, int, float);
506
507    alias TL = NoDuplicates!(Types);
508    static assert(is(TL == AliasSeq!(int, long, float)));
509}
510
511@safe unittest
512{
513    // Bugzilla 14561: huge enums
514    alias LongList = Repeat!(1500, int);
515    static assert(NoDuplicates!LongList.length == 1);
516}
517
518@safe unittest
519{
520    static assert(
521        Pack!(
522            NoDuplicates!(1, int, 1, NoDuplicates, int, NoDuplicates, real))
523        .equals!(1, int,    NoDuplicates,                    real));
524}
525
526
527/**
528 * Returns an `AliasSeq` created from TList with the first occurrence
529 * of type T, if found, replaced with type U.
530 */
531template Replace(T, U, TList...)
532{
533    alias Replace = GenericReplace!(T, U, TList).result;
534}
535
536/// Ditto
537template Replace(alias T, U, TList...)
538{
539    alias Replace = GenericReplace!(T, U, TList).result;
540}
541
542/// Ditto
543template Replace(T, alias U, TList...)
544{
545    alias Replace = GenericReplace!(T, U, TList).result;
546}
547
548/// Ditto
549template Replace(alias T, alias U, TList...)
550{
551    alias Replace = GenericReplace!(T, U, TList).result;
552}
553
554///
555@safe unittest
556{
557    alias Types = AliasSeq!(int, long, long, int, float);
558
559    alias TL = Replace!(long, char, Types);
560    static assert(is(TL == AliasSeq!(int, char, long, int, float)));
561}
562
563// [internal]
564private template GenericReplace(args...)
565if (args.length >= 2)
566{
567    alias from  = OldAlias!(args[0]);
568    alias to    = OldAlias!(args[1]);
569    alias tuple = args[2 .. $];
570
571    static if (tuple.length)
572    {
573        alias head = OldAlias!(tuple[0]);
574        alias tail = tuple[1 .. $];
575
576        static if (isSame!(from, head))
577            alias result = AliasSeq!(to, tail);
578        else
579            alias result = AliasSeq!(head,
580                GenericReplace!(from, to, tail).result);
581    }
582    else
583    {
584        alias result = AliasSeq!();
585    }
586 }
587
588@safe unittest
589{
590    static assert(Pack!(Replace!(byte, ubyte,
591                short,  byte, byte, byte)).
592        equals!(short, ubyte, byte, byte));
593
594    static assert(Pack!(Replace!(1111, byte,
595                2222, 1111, 1111, 1111)).
596        equals!(2222, byte, 1111, 1111));
597
598    static assert(Pack!(Replace!(byte, 1111,
599                short, byte, byte, byte)).
600        equals!(short, 1111, byte, byte));
601
602    static assert(Pack!(Replace!(1111, "11",
603                2222, 1111, 1111, 1111)).
604        equals!(2222, "11", 1111, 1111));
605}
606
607/**
608 * Returns an `AliasSeq` created from TList with all occurrences
609 * of type T, if found, replaced with type U.
610 */
611template ReplaceAll(T, U, TList...)
612{
613    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
614}
615
616/// Ditto
617template ReplaceAll(alias T, U, TList...)
618{
619    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
620}
621
622/// Ditto
623template ReplaceAll(T, alias U, TList...)
624{
625    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
626}
627
628/// Ditto
629template ReplaceAll(alias T, alias U, TList...)
630{
631    alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
632}
633
634///
635@safe unittest
636{
637    alias Types = AliasSeq!(int, long, long, int, float);
638
639    alias TL = ReplaceAll!(long, char, Types);
640    static assert(is(TL == AliasSeq!(int, char, char, int, float)));
641}
642
643// [internal]
644private template GenericReplaceAll(args...)
645if (args.length >= 2)
646{
647    alias from  = OldAlias!(args[0]);
648    alias to    = OldAlias!(args[1]);
649    alias tuple = args[2 .. $];
650
651    static if (tuple.length)
652    {
653        alias head = OldAlias!(tuple[0]);
654        alias tail = tuple[1 .. $];
655        alias next = GenericReplaceAll!(from, to, tail).result;
656
657        static if (isSame!(from, head))
658            alias result = AliasSeq!(to, next);
659        else
660            alias result = AliasSeq!(head, next);
661    }
662    else
663    {
664        alias result = AliasSeq!();
665    }
666}
667
668@safe unittest
669{
670    static assert(Pack!(ReplaceAll!(byte, ubyte,
671                 byte, short,  byte,  byte)).
672        equals!(ubyte, short, ubyte, ubyte));
673
674    static assert(Pack!(ReplaceAll!(1111, byte,
675                1111, 2222, 1111, 1111)).
676        equals!(byte, 2222, byte, byte));
677
678    static assert(Pack!(ReplaceAll!(byte, 1111,
679                byte, short, byte, byte)).
680        equals!(1111, short, 1111, 1111));
681
682    static assert(Pack!(ReplaceAll!(1111, "11",
683                1111, 2222, 1111, 1111)).
684        equals!("11", 2222, "11", "11"));
685}
686
687/**
688 * Returns an `AliasSeq` created from TList with the order reversed.
689 */
690template Reverse(TList...)
691{
692    static if (TList.length <= 1)
693    {
694        alias Reverse = TList;
695    }
696    else
697    {
698        alias Reverse =
699            AliasSeq!(
700                Reverse!(TList[$/2 ..  $ ]),
701                Reverse!(TList[ 0  .. $/2]));
702    }
703}
704
705///
706@safe unittest
707{
708    alias Types = AliasSeq!(int, long, long, int, float);
709
710    alias TL = Reverse!(Types);
711    static assert(is(TL == AliasSeq!(float, int, long, long, int)));
712}
713
714/**
715 * Returns the type from TList that is the most derived from type T.
716 * If none are found, T is returned.
717 */
718template MostDerived(T, TList...)
719{
720    static if (TList.length == 0)
721        alias MostDerived = T;
722    else static if (is(TList[0] : T))
723        alias MostDerived = MostDerived!(TList[0], TList[1 .. $]);
724    else
725        alias MostDerived = MostDerived!(T, TList[1 .. $]);
726}
727
728///
729@safe unittest
730{
731    class A { }
732    class B : A { }
733    class C : B { }
734    alias Types = AliasSeq!(A, C, B);
735
736    MostDerived!(Object, Types) x;  // x is declared as type C
737    static assert(is(typeof(x) == C));
738}
739
740/**
741 * Returns the `AliasSeq` TList with the types sorted so that the most
742 * derived types come first.
743 */
744template DerivedToFront(TList...)
745{
746    static if (TList.length == 0)
747        alias DerivedToFront = TList;
748    else
749        alias DerivedToFront =
750            AliasSeq!(MostDerived!(TList[0], TList[1 .. $]),
751                       DerivedToFront!(ReplaceAll!(MostDerived!(TList[0], TList[1 .. $]),
752                                TList[0],
753                                TList[1 .. $])));
754}
755
756///
757@safe unittest
758{
759    class A { }
760    class B : A { }
761    class C : B { }
762    alias Types = AliasSeq!(A, C, B);
763
764    alias TL = DerivedToFront!(Types);
765    static assert(is(TL == AliasSeq!(C, B, A)));
766}
767
768/**
769Evaluates to $(D AliasSeq!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))).
770 */
771template staticMap(alias F, T...)
772{
773    static if (T.length == 0)
774    {
775        alias staticMap = AliasSeq!();
776    }
777    else static if (T.length == 1)
778    {
779        alias staticMap = AliasSeq!(F!(T[0]));
780    }
781    else
782    {
783        alias staticMap =
784            AliasSeq!(
785                staticMap!(F, T[ 0  .. $/2]),
786                staticMap!(F, T[$/2 ..  $ ]));
787    }
788}
789
790///
791@safe unittest
792{
793    import std.traits : Unqual;
794    alias TL = staticMap!(Unqual, int, const int, immutable int);
795    static assert(is(TL == AliasSeq!(int, int, int)));
796}
797
798@safe unittest
799{
800    import std.traits : Unqual;
801
802    // empty
803    alias Empty = staticMap!(Unqual);
804    static assert(Empty.length == 0);
805
806    // single
807    alias Single = staticMap!(Unqual, const int);
808    static assert(is(Single == AliasSeq!int));
809
810    alias T = staticMap!(Unqual, int, const int, immutable int);
811    static assert(is(T == AliasSeq!(int, int, int)));
812}
813
814/**
815Tests whether all given items satisfy a template predicate, i.e. evaluates to
816$(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])).
817
818Evaluation is $(I not) short-circuited if a false result is encountered; the
819template predicate must be instantiable with all the given items.
820 */
821template allSatisfy(alias F, T...)
822{
823    static if (T.length == 0)
824    {
825        enum allSatisfy = true;
826    }
827    else static if (T.length == 1)
828    {
829        enum allSatisfy = F!(T[0]);
830    }
831    else
832    {
833        enum allSatisfy =
834            allSatisfy!(F, T[ 0  .. $/2]) &&
835            allSatisfy!(F, T[$/2 ..  $ ]);
836    }
837}
838
839///
840@safe unittest
841{
842    import std.traits : isIntegral;
843
844    static assert(!allSatisfy!(isIntegral, int, double));
845    static assert( allSatisfy!(isIntegral, int, long));
846}
847
848/**
849Tests whether any given items satisfy a template predicate, i.e. evaluates to
850$(D F!(T[0]) || F!(T[1]) || ... || F!(T[$ - 1])).
851
852Evaluation is short-circuited if a true result is encountered; the
853template predicate must be instantiable with one of the given items.
854 */
855template anySatisfy(alias F, T...)
856{
857    static if (T.length == 0)
858    {
859        enum anySatisfy = false;
860    }
861    else static if (T.length == 1)
862    {
863        enum anySatisfy = F!(T[0]);
864    }
865    else
866    {
867        enum anySatisfy =
868            anySatisfy!(F, T[ 0  .. $/2]) ||
869            anySatisfy!(F, T[$/2 ..  $ ]);
870    }
871}
872
873///
874@safe unittest
875{
876    import std.traits : isIntegral;
877
878    static assert(!anySatisfy!(isIntegral, string, double));
879    static assert( anySatisfy!(isIntegral, int, double));
880}
881
882
883/**
884 * Filters an $(D AliasSeq) using a template predicate. Returns a
885 * $(D AliasSeq) of the elements which satisfy the predicate.
886 */
887template Filter(alias pred, TList...)
888{
889    static if (TList.length == 0)
890    {
891        alias Filter = AliasSeq!();
892    }
893    else static if (TList.length == 1)
894    {
895        static if (pred!(TList[0]))
896            alias Filter = AliasSeq!(TList[0]);
897        else
898            alias Filter = AliasSeq!();
899    }
900    else
901    {
902        alias Filter =
903            AliasSeq!(
904                Filter!(pred, TList[ 0  .. $/2]),
905                Filter!(pred, TList[$/2 ..  $ ]));
906    }
907}
908
909///
910@safe unittest
911{
912    import std.traits : isNarrowString, isUnsigned;
913
914    alias Types1 = AliasSeq!(string, wstring, dchar[], char[], dstring, int);
915    alias TL1 = Filter!(isNarrowString, Types1);
916    static assert(is(TL1 == AliasSeq!(string, wstring, char[])));
917
918    alias Types2 = AliasSeq!(int, byte, ubyte, dstring, dchar, uint, ulong);
919    alias TL2 = Filter!(isUnsigned, Types2);
920    static assert(is(TL2 == AliasSeq!(ubyte, uint, ulong)));
921}
922
923@safe unittest
924{
925    import std.traits : isPointer;
926
927    static assert(is(Filter!(isPointer, int, void*, char[], int*) == AliasSeq!(void*, int*)));
928    static assert(is(Filter!isPointer == AliasSeq!()));
929}
930
931
932// Used in template predicate unit tests below.
933private version (unittest)
934{
935    template testAlways(T...)
936    {
937        enum testAlways = true;
938    }
939
940    template testNever(T...)
941    {
942        enum testNever = false;
943    }
944
945    template testError(T...)
946    {
947        static assert(false, "Should never be instantiated.");
948    }
949}
950
951
952/**
953 * Negates the passed template predicate.
954 */
955template templateNot(alias pred)
956{
957    enum templateNot(T...) = !pred!T;
958}
959
960///
961@safe unittest
962{
963    import std.traits : isPointer;
964
965    alias isNoPointer = templateNot!isPointer;
966    static assert(!isNoPointer!(int*));
967    static assert(allSatisfy!(isNoPointer, string, char, float));
968}
969
970@safe unittest
971{
972    foreach (T; AliasSeq!(int, staticMap, 42))
973    {
974        static assert(!Instantiate!(templateNot!testAlways, T));
975        static assert(Instantiate!(templateNot!testNever, T));
976    }
977}
978
979
980/**
981 * Combines several template predicates using logical AND, i.e. constructs a new
982 * predicate which evaluates to true for a given input T if and only if all of
983 * the passed predicates are true for T.
984 *
985 * The predicates are evaluated from left to right, aborting evaluation in a
986 * short-cut manner if a false result is encountered, in which case the latter
987 * instantiations do not need to compile.
988 */
989template templateAnd(Preds...)
990{
991    template templateAnd(T...)
992    {
993        static if (Preds.length == 0)
994        {
995            enum templateAnd = true;
996        }
997        else
998        {
999            static if (Instantiate!(Preds[0], T))
1000                alias templateAnd = Instantiate!(.templateAnd!(Preds[1 .. $]), T);
1001            else
1002                enum templateAnd = false;
1003        }
1004    }
1005}
1006
1007///
1008@safe unittest
1009{
1010    import std.traits : isNumeric, isUnsigned;
1011
1012    alias storesNegativeNumbers = templateAnd!(isNumeric, templateNot!isUnsigned);
1013    static assert(storesNegativeNumbers!int);
1014    static assert(!storesNegativeNumbers!string && !storesNegativeNumbers!uint);
1015
1016    // An empty list of predicates always yields true.
1017    alias alwaysTrue = templateAnd!();
1018    static assert(alwaysTrue!int);
1019}
1020
1021@safe unittest
1022{
1023    foreach (T; AliasSeq!(int, staticMap, 42))
1024    {
1025        static assert( Instantiate!(templateAnd!(), T));
1026        static assert( Instantiate!(templateAnd!(testAlways), T));
1027        static assert( Instantiate!(templateAnd!(testAlways, testAlways), T));
1028        static assert(!Instantiate!(templateAnd!(testNever), T));
1029        static assert(!Instantiate!(templateAnd!(testAlways, testNever), T));
1030        static assert(!Instantiate!(templateAnd!(testNever, testAlways), T));
1031
1032        static assert(!Instantiate!(templateAnd!(testNever, testError), T));
1033        static assert(!is(typeof(Instantiate!(templateAnd!(testAlways, testError), T))));
1034    }
1035}
1036
1037
1038/**
1039 * Combines several template predicates using logical OR, i.e. constructs a new
1040 * predicate which evaluates to true for a given input T if and only at least
1041 * one of the passed predicates is true for T.
1042 *
1043 * The predicates are evaluated from left to right, aborting evaluation in a
1044 * short-cut manner if a true result is encountered, in which case the latter
1045 * instantiations do not need to compile.
1046 */
1047template templateOr(Preds...)
1048{
1049    template templateOr(T...)
1050    {
1051        static if (Preds.length == 0)
1052        {
1053            enum templateOr = false;
1054        }
1055        else
1056        {
1057            static if (Instantiate!(Preds[0], T))
1058                enum templateOr = true;
1059            else
1060                alias templateOr = Instantiate!(.templateOr!(Preds[1 .. $]), T);
1061        }
1062    }
1063}
1064
1065///
1066@safe unittest
1067{
1068    import std.traits : isPointer, isUnsigned;
1069
1070    alias isPtrOrUnsigned = templateOr!(isPointer, isUnsigned);
1071    static assert( isPtrOrUnsigned!uint &&  isPtrOrUnsigned!(short*));
1072    static assert(!isPtrOrUnsigned!int  && !isPtrOrUnsigned!(string));
1073
1074    // An empty list of predicates never yields true.
1075    alias alwaysFalse = templateOr!();
1076    static assert(!alwaysFalse!int);
1077}
1078
1079@safe unittest
1080{
1081    foreach (T; AliasSeq!(int, staticMap, 42))
1082    {
1083        static assert( Instantiate!(templateOr!(testAlways), T));
1084        static assert( Instantiate!(templateOr!(testAlways, testAlways), T));
1085        static assert( Instantiate!(templateOr!(testAlways, testNever), T));
1086        static assert( Instantiate!(templateOr!(testNever, testAlways), T));
1087        static assert(!Instantiate!(templateOr!(), T));
1088        static assert(!Instantiate!(templateOr!(testNever), T));
1089
1090        static assert( Instantiate!(templateOr!(testAlways, testError), T));
1091        static assert( Instantiate!(templateOr!(testNever, testAlways, testError), T));
1092        // DMD @@BUG@@: Assertion fails for int, seems like a error gagging
1093        // problem. The bug goes away when removing some of the other template
1094        // instantiations in the module.
1095        // static assert(!is(typeof(Instantiate!(templateOr!(testNever, testError), T))));
1096    }
1097}
1098
1099/**
1100 * Converts an input range $(D range) to an alias sequence.
1101 */
1102template aliasSeqOf(alias range)
1103{
1104    import std.traits : isArray, isNarrowString;
1105
1106    alias ArrT = typeof(range);
1107    static if (isArray!ArrT && !isNarrowString!ArrT)
1108    {
1109        static if (range.length == 0)
1110        {
1111            alias aliasSeqOf = AliasSeq!();
1112        }
1113        else static if (range.length == 1)
1114        {
1115            alias aliasSeqOf = AliasSeq!(range[0]);
1116        }
1117        else
1118        {
1119            alias aliasSeqOf = AliasSeq!(aliasSeqOf!(range[0 .. $/2]), aliasSeqOf!(range[$/2 .. $]));
1120        }
1121    }
1122    else
1123    {
1124        import std.range.primitives : isInputRange;
1125        static if (isInputRange!ArrT)
1126        {
1127            import std.array : array;
1128            alias aliasSeqOf = aliasSeqOf!(array(range));
1129        }
1130        else
1131        {
1132            static assert(false, "Cannot transform range of type " ~ ArrT.stringof ~ " into a AliasSeq.");
1133        }
1134    }
1135}
1136
1137///
1138@safe unittest
1139{
1140    import std.algorithm.iteration : map;
1141    import std.algorithm.sorting : sort;
1142    import std.string : capitalize;
1143
1144    struct S
1145    {
1146        int a;
1147        int c;
1148        int b;
1149    }
1150
1151    alias capMembers = aliasSeqOf!([__traits(allMembers, S)].sort().map!capitalize());
1152    static assert(capMembers[0] == "A");
1153    static assert(capMembers[1] == "B");
1154    static assert(capMembers[2] == "C");
1155}
1156
1157///
1158@safe unittest
1159{
1160    static immutable REF = [0, 1, 2, 3];
1161    foreach (I, V; aliasSeqOf!([0, 1, 2, 3]))
1162    {
1163        static assert(V == I);
1164        static assert(V == REF[I]);
1165    }
1166}
1167
1168@safe unittest
1169{
1170    import std.conv : to, octal;
1171    import std.range : iota;
1172    //Testing compile time octal
1173    foreach (I2; aliasSeqOf!(iota(0, 8)))
1174        foreach (I1; aliasSeqOf!(iota(0, 8)))
1175        {
1176            enum oct = I2 *  8 + I1;
1177            enum dec = I2 * 10 + I1;
1178            enum str = to!string(dec);
1179            static assert(octal!dec == oct);
1180            static assert(octal!str == oct);
1181        }
1182}
1183
1184@safe unittest
1185{
1186    enum REF = "���������"d;
1187    foreach (I, V; aliasSeqOf!"���������"c)
1188    {
1189        static assert(V == REF[I]);
1190    }
1191}
1192
1193/**
1194  * $(LINK2 http://en.wikipedia.org/wiki/Partial_application, Partially applies)
1195  * $(D_PARAM Template) by binding its first (left) or last (right) arguments
1196  * to $(D_PARAM args).
1197  *
1198  * Behaves like the identity function when $(D_PARAM args) is empty.
1199  * Params:
1200  *    Template = template to partially apply
1201  *    args     = arguments to bind
1202  * Returns:
1203  *    _Template with arity smaller than or equal to $(D_PARAM Template)
1204  */
1205template ApplyLeft(alias Template, args...)
1206{
1207    alias ApplyLeft(right...) = SmartAlias!(Template!(args, right));
1208}
1209
1210/// Ditto
1211template ApplyRight(alias Template, args...)
1212{
1213    alias ApplyRight(left...) = SmartAlias!(Template!(left, args));
1214}
1215
1216///
1217@safe unittest
1218{
1219    // enum bool isImplicitlyConvertible(From, To)
1220    import std.traits : isImplicitlyConvertible;
1221
1222    static assert(allSatisfy!(
1223        ApplyLeft!(isImplicitlyConvertible, ubyte),
1224        short, ushort, int, uint, long, ulong));
1225
1226    static assert(is(Filter!(ApplyRight!(isImplicitlyConvertible, short),
1227        ubyte, string, short, float, int) == AliasSeq!(ubyte, short)));
1228}
1229
1230///
1231@safe unittest
1232{
1233    import std.traits : hasMember, ifTestable;
1234
1235    struct T1
1236    {
1237        bool foo;
1238    }
1239
1240    struct T2
1241    {
1242        struct Test
1243        {
1244            bool opCast(T : bool)() { return true; }
1245        }
1246
1247        Test foo;
1248    }
1249
1250    static assert(allSatisfy!(ApplyRight!(hasMember, "foo"), T1, T2));
1251    static assert(allSatisfy!(ApplyRight!(ifTestable, a => a.foo), T1, T2));
1252}
1253
1254///
1255@safe unittest
1256{
1257    import std.traits : Largest;
1258
1259    alias Types = AliasSeq!(byte, short, int, long);
1260
1261    static assert(is(staticMap!(ApplyLeft!(Largest, short), Types) ==
1262                AliasSeq!(short, short, int, long)));
1263    static assert(is(staticMap!(ApplyLeft!(Largest, int), Types) ==
1264                AliasSeq!(int, int, int, long)));
1265}
1266
1267///
1268@safe unittest
1269{
1270    import std.traits : FunctionAttribute, SetFunctionAttributes;
1271
1272    static void foo() @system;
1273    static int bar(int) @system;
1274
1275    alias SafeFunctions = AliasSeq!(
1276        void function() @safe,
1277        int function(int) @safe);
1278
1279    static assert(is(staticMap!(ApplyRight!(
1280        SetFunctionAttributes, "D", FunctionAttribute.safe),
1281        typeof(&foo), typeof(&bar)) == SafeFunctions));
1282}
1283
1284private template SmartAlias(T...)
1285{
1286    static if (T.length == 1)
1287    {
1288        alias SmartAlias = Alias!T;
1289    }
1290    else
1291    {
1292        alias SmartAlias = AliasSeq!T;
1293    }
1294}
1295
1296@safe unittest
1297{
1298    static assert(is(typeof({
1299        alias T(T0, int a, double b, alias T1, string c) = AliasSeq!(T0, a, b, T1, c);
1300        alias T0 = ApplyRight!(ApplyLeft, ApplyRight);
1301        alias T1 = T0!ApplyLeft;
1302        alias T2 = T1!T;
1303        alias T3 = T2!(3, "foo");
1304        alias T4 = T3!(short, 3, 3.3);
1305        static assert(Pack!T4.equals!(short, 3, 3.3, 3, "foo"));
1306
1307        import std.traits : isImplicitlyConvertible;
1308        alias U1 = ApplyLeft!(ApplyRight, isImplicitlyConvertible);
1309        alias U2 = U1!int;
1310        enum U3 = U2!short;
1311        static assert(U3);
1312    })));
1313}
1314
1315/**
1316 * Creates an `AliasSeq` which repeats a type or an `AliasSeq` exactly `n` times.
1317 */
1318template Repeat(size_t n, TList...)
1319if (n > 0)
1320{
1321    static if (n == 1)
1322    {
1323        alias Repeat = AliasSeq!TList;
1324    }
1325    else static if (n == 2)
1326    {
1327        alias Repeat = AliasSeq!(TList, TList);
1328    }
1329    else
1330    {
1331        alias R = Repeat!((n - 1) / 2, TList);
1332        static if ((n - 1) % 2 == 0)
1333        {
1334            alias Repeat = AliasSeq!(TList, R, R);
1335        }
1336        else
1337        {
1338            alias Repeat = AliasSeq!(TList, TList, R, R);
1339        }
1340    }
1341}
1342
1343///
1344@safe unittest
1345{
1346    alias ImInt1 = Repeat!(1, immutable(int));
1347    static assert(is(ImInt1 == AliasSeq!(immutable(int))));
1348
1349    alias Real3 = Repeat!(3, real);
1350    static assert(is(Real3 == AliasSeq!(real, real, real)));
1351
1352    alias Real12 = Repeat!(4, Real3);
1353    static assert(is(Real12 == AliasSeq!(real, real, real, real, real, real,
1354        real, real, real, real, real, real)));
1355
1356    alias Composite = AliasSeq!(uint, int);
1357    alias Composite2 = Repeat!(2, Composite);
1358    static assert(is(Composite2 == AliasSeq!(uint, int, uint, int)));
1359}
1360
1361
1362///
1363@safe unittest
1364{
1365    auto staticArray(T, size_t n)(Repeat!(n, T) elems)
1366    {
1367        T[n] a = [elems];
1368        return a;
1369    }
1370
1371    auto a = staticArray!(long, 3)(3, 1, 4);
1372    assert(is(typeof(a) == long[3]));
1373    assert(a == [3, 1, 4]);
1374}
1375
1376/**
1377 * Sorts a $(LREF AliasSeq) using $(D cmp).
1378 *
1379 * Parameters:
1380 *     cmp = A template that returns a $(D bool) (if its first argument is less than the second one)
1381 *         or an $(D int) (-1 means less than, 0 means equal, 1 means greater than)
1382 *
1383 *     Seq = The  $(LREF AliasSeq) to sort
1384 *
1385 * Returns: The sorted alias sequence
1386 */
1387template staticSort(alias cmp, Seq...)
1388{
1389    static if (Seq.length < 2)
1390    {
1391        alias staticSort = Seq;
1392    }
1393    else
1394    {
1395        private alias btm = staticSort!(cmp, Seq[0 .. $ / 2]);
1396        private alias top = staticSort!(cmp, Seq[$ / 2 .. $]);
1397
1398        static if (isLessEq!(cmp, btm[$ - 1], top[0]))
1399            alias staticSort = AliasSeq!(btm, top); // already ascending
1400        else static if (isLessEq!(cmp, top[$ - 1], btm[0]))
1401            alias staticSort = AliasSeq!(top, btm); // already descending
1402        else
1403            alias staticSort = staticMerge!(cmp, Seq.length / 2, btm, top);
1404    }
1405}
1406
1407///
1408@safe unittest
1409{
1410    alias Nums = AliasSeq!(7, 2, 3, 23);
1411    enum Comp(int N1, int N2) = N1 < N2;
1412    static assert(AliasSeq!(2, 3, 7, 23) == staticSort!(Comp, Nums));
1413}
1414
1415///
1416@safe unittest
1417{
1418    alias Types = AliasSeq!(uint, short, ubyte, long, ulong);
1419    enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
1420    static assert(is(AliasSeq!(uint, ubyte, ulong, short, long) == staticSort!(Comp,
1421        Types)));
1422}
1423
1424private template staticMerge(alias cmp, int half, Seq...)
1425{
1426    static if (half == 0 || half == Seq.length)
1427    {
1428        alias staticMerge = Seq;
1429    }
1430    else
1431    {
1432        static if (isLessEq!(cmp, Seq[0], Seq[half]))
1433        {
1434            alias staticMerge = AliasSeq!(Seq[0],
1435                staticMerge!(cmp, half - 1, Seq[1 .. $]));
1436        }
1437        else
1438        {
1439            alias staticMerge = AliasSeq!(Seq[half],
1440                staticMerge!(cmp, half, Seq[0 .. half], Seq[half + 1 .. $]));
1441        }
1442    }
1443}
1444
1445private template isLessEq(alias cmp, Seq...)
1446if (Seq.length == 2)
1447{
1448    private enum Result = cmp!(Seq[1], Seq[0]);
1449    static if (is(typeof(Result) == bool))
1450        enum isLessEq = !Result;
1451    else static if (is(typeof(Result) : int))
1452        enum isLessEq = Result >= 0;
1453    else
1454        static assert(0, typeof(Result).stringof ~ " is not a value comparison type");
1455}
1456
1457/**
1458 * Checks if an $(LREF AliasSeq) is sorted according to $(D cmp).
1459 *
1460 * Parameters:
1461 *     cmp = A template that returns a $(D bool) (if its first argument is less than the second one)
1462 *         or an $(D int) (-1 means less than, 0 means equal, 1 means greater than)
1463 *
1464 *     Seq = The  $(LREF AliasSeq) to check
1465 *
1466 * Returns: `true` if `Seq` is sorted; otherwise `false`
1467 */
1468template staticIsSorted(alias cmp, Seq...)
1469{
1470    static if (Seq.length <= 1)
1471        enum staticIsSorted = true;
1472    else static if (Seq.length == 2)
1473        enum staticIsSorted = isLessEq!(cmp, Seq[0], Seq[1]);
1474    else
1475    {
1476        enum staticIsSorted =
1477            isLessEq!(cmp, Seq[($ / 2) - 1], Seq[$ / 2]) &&
1478            staticIsSorted!(cmp, Seq[0 .. $ / 2]) &&
1479            staticIsSorted!(cmp, Seq[$ / 2 .. $]);
1480    }
1481}
1482
1483///
1484@safe unittest
1485{
1486    enum Comp(int N1, int N2) = N1 < N2;
1487    static assert( staticIsSorted!(Comp, 2, 2));
1488    static assert( staticIsSorted!(Comp, 2, 3, 7, 23));
1489    static assert(!staticIsSorted!(Comp, 7, 2, 3, 23));
1490}
1491
1492///
1493@safe unittest
1494{
1495    enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
1496    static assert( staticIsSorted!(Comp, uint, ubyte, ulong, short, long));
1497    static assert(!staticIsSorted!(Comp, uint, short, ubyte, long, ulong));
1498}
1499
1500/**
1501Selects a subset of the argument list by stepping with fixed `stepSize` over the list.
1502A negative `stepSize` starts iteration with the last list element.
1503
1504Params:
1505    stepSize = Number of elements to increment on each iteration. Can't be `0`.
1506    Args = Template arguments
1507
1508Returns: A template argument list filtered by the selected stride.
1509*/
1510template Stride(int stepSize, Args...)
1511if (stepSize != 0)
1512{
1513    static if (Args.length == 0)
1514    {
1515        alias Stride = AliasSeq!();
1516    }
1517    else static if (stepSize > 0)
1518    {
1519        static if (stepSize >= Args.length)
1520            alias Stride = AliasSeq!(Args[0]);
1521        else
1522            alias Stride = AliasSeq!(Args[0], Stride!(stepSize, Args[stepSize .. $]));
1523    }
1524    else
1525    {
1526        static if (-stepSize >= Args.length)
1527            alias Stride = AliasSeq!(Args[$ - 1]);
1528        else
1529            alias Stride = AliasSeq!(Args[$ - 1], Stride!(stepSize, Args[0 .. $ + stepSize]));
1530    }
1531}
1532
1533///
1534@safe unittest
1535{
1536    static assert(is(Stride!(1, short, int, long) == AliasSeq!(short, int, long)));
1537    static assert(is(Stride!(2, short, int, long) == AliasSeq!(short, long)));
1538    static assert(is(Stride!(-1, short, int, long) == AliasSeq!(long, int, short)));
1539    static assert(is(Stride!(-2, short, int, long) == AliasSeq!(long, short)));
1540
1541    alias attribs = AliasSeq!(short, int, long, ushort, uint, ulong);
1542    static assert(is(Stride!(3, attribs) == AliasSeq!(short, ushort)));
1543    static assert(is(Stride!(3, attribs[1 .. $]) == AliasSeq!(int, uint)));
1544    static assert(is(Stride!(-3, attribs) == AliasSeq!(ulong, long)));
1545}
1546
1547@safe unittest
1548{
1549    static assert(Pack!(Stride!(5, int)).equals!(int));
1550    static assert(Pack!(Stride!(-5, int)).equals!(int));
1551    static assert(!__traits(compiles, Stride!(0, int)));
1552}
1553
1554// : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : //
1555private:
1556
1557/*
1558 * [internal] Returns true if a and b are the same thing, or false if
1559 * not. Both a and b can be types, literals, or symbols.
1560 *
1561 * How:                     When:
1562 *      is(a == b)        - both are types
1563 *        a == b          - both are literals (true literals, enums)
1564 * __traits(isSame, a, b) - other cases (variables, functions,
1565 *                          templates, etc.)
1566 */
1567private template isSame(ab...)
1568if (ab.length == 2)
1569{
1570    static if (__traits(compiles, expectType!(ab[0]),
1571                                  expectType!(ab[1])))
1572    {
1573        enum isSame = is(ab[0] == ab[1]);
1574    }
1575    else static if (!__traits(compiles, expectType!(ab[0])) &&
1576                    !__traits(compiles, expectType!(ab[1])) &&
1577                     __traits(compiles, expectBool!(ab[0] == ab[1])))
1578    {
1579        static if (!__traits(compiles, &ab[0]) ||
1580                   !__traits(compiles, &ab[1]))
1581            enum isSame = (ab[0] == ab[1]);
1582        else
1583            enum isSame = __traits(isSame, ab[0], ab[1]);
1584    }
1585    else
1586    {
1587        enum isSame = __traits(isSame, ab[0], ab[1]);
1588    }
1589}
1590private template expectType(T) {}
1591private template expectBool(bool b) {}
1592
1593@safe unittest
1594{
1595    static assert( isSame!(int, int));
1596    static assert(!isSame!(int, short));
1597
1598    enum a = 1, b = 1, c = 2, s = "a", t = "a";
1599    static assert( isSame!(1, 1));
1600    static assert( isSame!(a, 1));
1601    static assert( isSame!(a, b));
1602    static assert(!isSame!(b, c));
1603    static assert( isSame!("a", "a"));
1604    static assert( isSame!(s, "a"));
1605    static assert( isSame!(s, t));
1606    static assert(!isSame!(1, "1"));
1607    static assert(!isSame!(a, "a"));
1608    static assert( isSame!(isSame, isSame));
1609    static assert(!isSame!(isSame, a));
1610
1611    static assert(!isSame!(byte, a));
1612    static assert(!isSame!(short, isSame));
1613    static assert(!isSame!(a, int));
1614    static assert(!isSame!(long, isSame));
1615
1616    static immutable X = 1, Y = 1, Z = 2;
1617    static assert( isSame!(X, X));
1618    static assert(!isSame!(X, Y));
1619    static assert(!isSame!(Y, Z));
1620
1621    int  foo();
1622    int  bar();
1623    real baz(int);
1624    static assert( isSame!(foo, foo));
1625    static assert(!isSame!(foo, bar));
1626    static assert(!isSame!(bar, baz));
1627    static assert( isSame!(baz, baz));
1628    static assert(!isSame!(foo, 0));
1629
1630    int  x, y;
1631    real z;
1632    static assert( isSame!(x, x));
1633    static assert(!isSame!(x, y));
1634    static assert(!isSame!(y, z));
1635    static assert( isSame!(z, z));
1636    static assert(!isSame!(x, 0));
1637}
1638
1639/*
1640 * [internal] Confines a tuple within a template.
1641 */
1642private template Pack(T...)
1643{
1644    alias tuple = T;
1645
1646    // For convenience
1647    template equals(U...)
1648    {
1649        static if (T.length == U.length)
1650        {
1651            static if (T.length == 0)
1652                enum equals = true;
1653            else
1654                enum equals = isSame!(T[0], U[0]) &&
1655                    Pack!(T[1 .. $]).equals!(U[1 .. $]);
1656        }
1657        else
1658        {
1659            enum equals = false;
1660        }
1661    }
1662}
1663
1664@safe unittest
1665{
1666    static assert( Pack!(1, int, "abc").equals!(1, int, "abc"));
1667    static assert(!Pack!(1, int, "abc").equals!(1, int, "cba"));
1668}
1669
1670/*
1671 * Instantiates the given template with the given list of parameters.
1672 *
1673 * Used to work around syntactic limitations of D with regard to instantiating
1674 * a template from an alias sequence (e.g. T[0]!(...) is not valid) or a template
1675 * returning another template (e.g. Foo!(Bar)!(Baz) is not allowed).
1676 */
1677// TODO: Consider publicly exposing this, maybe even if only for better
1678// understandability of error messages.
1679alias Instantiate(alias Template, Params...) = Template!Params;
1680