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 
73 module 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  */
AliasSeq(TList...)81 template 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 
foo(TL td)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 {
ArgCall(alias Func,alias arg)116     auto ref ArgCall(alias Func, alias arg)()
117     {
118         return Func(arg);
119     }
120 
Map(alias Func,args...)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 
square(int arg)133     static int square(int arg)
134     {
135         return arg * arg;
136     }
137 
refSquare(ref int arg)138     static int refSquare(ref int arg)
139     {
140         arg *= arg;
141         return arg;
142     }
143 
refRetSquare(ref int arg)144     static ref int refRetSquare(ref int arg)
145     {
146         arg *= arg;
147         return arg;
148     }
149 
test(int a,int b)150     static void test(int a, int b)
151     {
152         assert(a == 4);
153         assert(b == 16);
154     }
155 
testRef(ref int a,ref int b)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  */
191 alias Alias(alias a) = a;
192 
193 /// Ditto
194 alias 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 
OldAlias(alias a)240 package 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 
250 import std.traits : isAggregateType, Unqual;
251 
252 package template OldAlias(T)
253 if (!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  */
staticIndexOf(T,TList...)273 template staticIndexOf(T, TList...)
274 {
275     enum staticIndexOf = genericIndexOf!(T, TList).index;
276 }
277 
278 /// Ditto
staticIndexOf(alias T,TList...)279 template staticIndexOf(alias T, TList...)
280 {
281     enum staticIndexOf = genericIndexOf!(T, TList).index;
282 }
283 
284 ///
285 @safe unittest
286 {
287     import std.stdio;
288 
foo()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]
298 private template genericIndexOf(args...)
299 if (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  */
Erase(T,TList...)351 template Erase(T, TList...)
352 {
353     alias Erase = GenericErase!(T, TList).result;
354 }
355 
356 /// Ditto
Erase(alias T,TList...)357 template 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]
371 private template GenericErase(args...)
372 if (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  */
EraseAll(T,TList...)409 template EraseAll(T, TList...)
410 {
411     alias EraseAll = GenericEraseAll!(T, TList).result;
412 }
413 
414 /// Ditto
EraseAll(alias T,TList...)415 template 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]
430 private template GenericEraseAll(args...)
431 if (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  */
NoDuplicates(TList...)472 template 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  */
Replace(T,U,TList...)531 template Replace(T, U, TList...)
532 {
533     alias Replace = GenericReplace!(T, U, TList).result;
534 }
535 
536 /// Ditto
Replace(alias T,U,TList...)537 template Replace(alias T, U, TList...)
538 {
539     alias Replace = GenericReplace!(T, U, TList).result;
540 }
541 
542 /// Ditto
Replace(T,alias U,TList...)543 template Replace(T, alias U, TList...)
544 {
545     alias Replace = GenericReplace!(T, U, TList).result;
546 }
547 
548 /// Ditto
Replace(alias T,alias U,TList...)549 template 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]
564 private template GenericReplace(args...)
565 if (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  */
ReplaceAll(T,U,TList...)611 template ReplaceAll(T, U, TList...)
612 {
613     alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
614 }
615 
616 /// Ditto
ReplaceAll(alias T,U,TList...)617 template ReplaceAll(alias T, U, TList...)
618 {
619     alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
620 }
621 
622 /// Ditto
ReplaceAll(T,alias U,TList...)623 template ReplaceAll(T, alias U, TList...)
624 {
625     alias ReplaceAll = GenericReplaceAll!(T, U, TList).result;
626 }
627 
628 /// Ditto
ReplaceAll(alias T,alias U,TList...)629 template 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]
644 private template GenericReplaceAll(args...)
645 if (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  */
Reverse(TList...)690 template 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  */
MostDerived(T,TList...)718 template 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  */
DerivedToFront(TList...)744 template 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 /**
769 Evaluates to $(D AliasSeq!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))).
770  */
staticMap(alias F,T...)771 template 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 /**
815 Tests whether all given items satisfy a template predicate, i.e. evaluates to
816 $(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])).
817 
818 Evaluation is $(I not) short-circuited if a false result is encountered; the
819 template predicate must be instantiable with all the given items.
820  */
allSatisfy(alias F,T...)821 template 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 /**
849 Tests whether any given items satisfy a template predicate, i.e. evaluates to
850 $(D F!(T[0]) || F!(T[1]) || ... || F!(T[$ - 1])).
851 
852 Evaluation is short-circuited if a true result is encountered; the
853 template predicate must be instantiable with one of the given items.
854  */
anySatisfy(alias F,T...)855 template 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  */
Filter(alias pred,TList...)887 template 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.
version(unittest)933 private 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  */
templateNot(alias pred)955 template 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  */
templateAnd(Preds...)989 template 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  */
templateOr(Preds...)1047 template 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  */
aliasSeqOf(alias range)1102 template 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   */
ApplyLeft(alias Template,args...)1205 template ApplyLeft(alias Template, args...)
1206 {
1207     alias ApplyLeft(right...) = SmartAlias!(Template!(args, right));
1208 }
1209 
1210 /// Ditto
ApplyRight(alias Template,args...)1211 template 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 
SmartAlias(T...)1284 private 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  */
1318 template Repeat(size_t n, TList...)
1319 if (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 {
staticArray(T,size_t n)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  */
staticSort(alias cmp,Seq...)1387 template 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 
staticMerge(alias cmp,int half,Seq...)1424 private 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 
1445 private template isLessEq(alias cmp, Seq...)
1446 if (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  */
staticIsSorted(alias cmp,Seq...)1468 template 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 /**
1501 Selects a subset of the argument list by stepping with fixed `stepSize` over the list.
1502 A negative `stepSize` starts iteration with the last list element.
1503 
1504 Params:
1505     stepSize = Number of elements to increment on each iteration. Can't be `0`.
1506     Args = Template arguments
1507 
1508 Returns: A template argument list filtered by the selected stride.
1509 */
1510 template Stride(int stepSize, Args...)
1511 if (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 // : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : //
1555 private:
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  */
1567 private template isSame(ab...)
1568 if (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 }
expectType(T)1590 private template expectType(T) {}
expectBool(bool b)1591 private 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  */
Pack(T...)1642 private 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.
1679 alias Instantiate(alias Template, Params...) = Template!Params;
1680