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