1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /**
6  * This module is suited for computations on template arguments, both types and
7  * values at compile time.
8  *
9  * It contains different algorithms for iterating, searching and modifying
10  * template arguments.
11  *
12  * Copyright: Eugene Wissner 2017-2020.
13  * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
14  *                  Mozilla Public License, v. 2.0).
15  * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
16  * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/metafunction.d,
17  *                 tanya/meta/metafunction.d)
18  */
19 module tanya.meta.metafunction;
20 
21 import tanya.meta.trait;
22 import tanya.meta.transform;
23 
24 /**
25  * Finds the minimum value in $(D_PARAM Args) according to $(D_PARAM pred).
26  *
27  * $(D_PARAM Args) should contain at least one element.
28  *
29  * $(D_PARAM pred) can evaluate to:
30  * $(UL
31  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
32  *       $(D_INLINECODE Args[0] < Args[1]).)
33  *  $(LI $(D_KEYWORD int): a negative number means that
34  *       $(D_INLINECODE Args[0] < Args[1]), a positive number that
35  *       $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
36  * )
37  * 
38  * Params:
39  *  pred = Template predicate.
40  *  Args = Elements for which you want to find the minimum value.
41  *
42  * Returns: The minimum.
43  *
44  * See_Also: $(D_PSYMBOL isLess).
45  */
46 template Min(alias pred, Args...)
47 if (Args.length > 0 && __traits(isTemplate, pred))
48 {
49     static if (Args.length == 1)
50     {
51         alias Min = Alias!(Args[0]);
52     }
53     else static if (isLess!(pred, Args[1], Args[0]))
54     {
55         alias Min = Min!(pred, Args[1], Args[2 .. $]);
56     }
57     else
58     {
59         alias Min = Min!(pred, Args[0], Args[2 .. $]);
60     }
61 }
62 
63 ///
64 @nogc nothrow pure @safe unittest
65 {
66     enum bool cmp(alias T, alias U) = T < U;
67     static assert(Min!(cmp, 8, 4, 5, 3, 13) == 3);
68     static assert(Min!(cmp, 8) == 8);
69 }
70 
71 /**
72  * Finds the maximum value in $(D_PARAM Args) according to $(D_PARAM pred).
73  *
74  * $(D_PARAM Args) should contain at least one element.
75  *
76  * $(D_PARAM pred) can evaluate to:
77  * $(UL
78  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
79  *       $(D_INLINECODE Args[0] < Args[1]).)
80  *  $(LI $(D_KEYWORD int): a negative number means that
81  *       $(D_INLINECODE Args[0] < Args[1]), a positive number that
82  *       $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
83  * )
84  * 
85  * Params:
86  *  pred = Template predicate.
87  *  Args = Elements for which you want to find the maximum value.
88  *
89  * Returns: The maximum.
90  *
91  * See_Also: $(D_PSYMBOL isLess).
92  */
93 template Max(alias pred, Args...)
94 if (Args.length > 0 && __traits(isTemplate, pred))
95 {
96     static if (Args.length == 1)
97     {
98         alias Max = Alias!(Args[0]);
99     }
100     else static if (isGreater!(pred, Args[1], Args[0]))
101     {
102         alias Max = Max!(pred, Args[1], Args[2 .. $]);
103     }
104     else
105     {
106         alias Max = Max!(pred, Args[0], Args[2 .. $]);
107     }
108 }
109 
110 ///
111 @nogc nothrow pure @safe unittest
112 {
113     enum bool cmp(alias T, alias U) = T < U;
114     static assert(Max!(cmp, 8, 4, 5, 3, 13) == 13);
115     static assert(Max!(cmp, 8) == 8);
116 }
117 
118 /**
119  * Zips one or more $(D_PSYMBOL Pack)s with $(D_PARAM f).
120  *
121  * Given $(D_PARAM f) and tuples t1, t2, ..., tk, where tk[i] denotes the
122  * $(I i)-th element of the tuple $(I k)-th tuple, $(D_PSYMBOL ZipWith)
123  * produces a sequence:
124  *
125  * ---
126  * f(t1[0], t2[0], ... tk[0]),
127  * f(t1[1], t2[1], ... tk[1]),
128  * ...
129  * f(tk[0], tk[1], ... tk[i]),
130  * ---
131  *
132  * $(D_PSYMBOL ZipWith) begins with the first elements from $(D_PARAM Packs)
133  * and applies $(D_PARAM f) to them, then it takes the second
134  * ones and does the same, and so on.
135  *
136  * If not all argument tuples have the same length, $(D_PSYMBOL ZipWith) will
137  * zip only `n` elements from each tuple, where `n` is the length of the
138  * shortest tuple in the argument list. Remaining elements in the longer tuples
139  * are just ignored.
140  *
141  * Params:
142  *  f      = Some template that can be applied to the elements of
143  *           $(D_PARAM Packs).
144  *  Packs  = $(D_PSYMBOL Pack) instances.
145  *
146  * Returns: A sequence, whose $(I i)-th element contains the $(I i)-th element
147  *          from each of the $(D_PARAM Packs).
148  */
149 template ZipWith(alias f, Packs...)
150 if (Packs.length > 0
151  && __traits(isTemplate, f)
152  && (allSatisfy!(ApplyLeft!(isInstanceOf, Pack), Packs)
153  || allSatisfy!(ApplyLeft!(isInstanceOf, Tuple), Packs)))
154 {
155     private template GetIth(size_t i, Args...)
156     {
157         static if ((Args.length == 0) || (Args[0].Seq.length <= i))
158         {
159             alias GetIth = AliasSeq!();
160         }
161         else
162         {
163             alias GetIth = AliasSeq!(Args[0].Seq[i], GetIth!(i, Args[1 .. $]));
164         }
165     }
166     private template Iterate(size_t i, Args...)
167     {
168         alias Pack = GetIth!(i, Args);
169 
170         static if (Pack.length < Packs.length)
171         {
172             alias Iterate = AliasSeq!();
173         }
174         else
175         {
176             alias Iterate = AliasSeq!(f!Pack, Iterate!(i + 1, Args));
177         }
178     }
179     alias ZipWith = Iterate!(0, Packs);
180 }
181 
182 ///
183 @nogc nothrow pure @safe unittest
184 {
185     alias Result1 = ZipWith!(AliasSeq, Pack!(1, 2), Pack!(5, 6), Pack!(9, 10));
186     static assert(Result1 == AliasSeq!(1, 5, 9, 2, 6, 10));
187 
188     alias Result2 = ZipWith!(AliasSeq, Pack!(1, 2, 3), Pack!(4, 5));
189     static assert(Result2 == AliasSeq!(1, 4, 2, 5));
190 
191     alias Result3 = ZipWith!(AliasSeq, Pack!(), Pack!(4, 5));
192     static assert(Result3.length == 0);
193 }
194 
195 /**
196  * Holds a typed sequence of template parameters.
197  *
198  * Different than $(D_PSYMBOL AliasSeq), $(D_PSYMBOL Pack) doesn't unpack
199  * its template parameters automatically. Consider:
200  *
201  * ---
202  * template A(Args...)
203  * {
204  *  static assert(Args.length == 4);
205  * }
206  *
207  * alias AInstance = A!(AliasSeq!(int, uint), AliasSeq!(float, double));
208  * ---
209  *
210  * Using $(D_PSYMBOL AliasSeq) template `A` gets 4 parameters instead of 2,
211  * because $(D_PSYMBOL AliasSeq) is just an alias for its template parameters.
212  *
213  * With $(D_PSYMBOL Pack) it is possible to pass distinguishable
214  * sequences of parameters to a template. So:
215  *
216  * ---
217  * template B(Args...)
218  * {
219  *  static assert(Args.length == 2);
220  * }
221  *
222  * alias BInstance = B!(Pack!(int, uint), Pack!(float, double));
223  * ---
224  *
225  * Params:
226  *  Args = Elements of this $(D_PSYMBOL Pack).
227  *
228  * See_Also: $(D_PSYMBOL AliasSeq).
229  */
230 struct Pack(Args...)
231 {
232     /// Elements in this tuple as $(D_PSYMBOL AliasSeq).
233     alias Seq = Args;
234 
235     /// The length of the tuple.
236     enum size_t length = Args.length;
237 
238     alias Seq this;
239 }
240 
241 ///
242 @nogc nothrow pure @safe unittest
243 {
244     alias A = Pack!short;
245     alias B = Pack!(3, 8, 9);
246     alias C = Pack!(A, B);
247 
248     static assert(C.length == 2);
249 
250     static assert(A.length == 1);
251     static assert(is(A.Seq == AliasSeq!short));
252     static assert(B.length == 3);
253     static assert(B.Seq == AliasSeq!(3, 8, 9));
254 
255     alias D = Pack!();
256     static assert(D.length == 0);
257     static assert(is(D.Seq == AliasSeq!()));
258 }
259 
260 /**
261  * Unordered sequence of unique aliases.
262  *
263  * $(D_PARAM Args) can contain duplicates, but they will be filtered out, so
264  * $(D_PSYMBOL Set) contains only unique items. $(D_PSYMBOL isEqual) is used
265  * for determining if two items are equal.
266  *
267  * Params:
268  *  Args = Elements of this $(D_PSYMBOL Set).
269  */
270 struct Set(Args...)
271 {
272     /// Elements in this set as $(D_PSYMBOL AliasSeq).
273     alias Seq = NoDuplicates!Args;
274 
275     /// The length of the set.
276     enum size_t length = Seq.length;
277 
278     alias Seq this;
279 }
280 
281 ///
282 @nogc nothrow pure @safe unittest
283 {
284     alias S1 = Set!(int, 5, 5, int, 4);
285     static assert(S1.length == 3);
286 }
287 
288 /**
289  * Produces a $(D_PSYMBOL Set) containing all elements of the given
290  * $(D_PARAM Sets).
291  *
292  * Params:
293  *  Sets = List of $(D_PSYMBOL Set) instances.
294  *
295  * Returns: Set-theoretic union of all $(D_PARAM Sets).
296  *
297  * See_Also: $(D_PSYMBOL Set).
298  */
299 template Union(Sets...)
300 if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
301 {
302     private template Impl(Sets...)
303     {
304         static if (Sets.length == 0)
305         {
306             alias Impl = AliasSeq!();
307         }
308         else
309         {
310             alias Impl = AliasSeq!(Sets[0].Seq, Impl!(Sets[1 .. $]));
311         }
312     }
313     alias Union = Set!(Impl!Sets);
314 }
315 
316 ///
317 @nogc nothrow pure @safe unittest
318 {
319     alias S1 = Set!(2, 5, 8, 4);
320     alias S2 = Set!(3, 8, 4, 1);
321     static assert(Union!(S1, S2).Seq == AliasSeq!(2, 5, 8, 4, 3, 1));
322 }
323 
324 /**
325  * Produces a $(D_PSYMBOL Set) that containing elements of
326  * $(D_INLINECODE Sets[0]) that are also elements of all other sets in
327  * $(D_PARAM Sets).
328  *
329  * Params:
330  *  Sets = List of $(D_PSYMBOL Set) instances.
331  *
332  * Returns: Set-theoretic intersection of all $(D_PARAM Sets).
333  *
334  * See_Also: $(D_PSYMBOL Set).
335  */
336 template Intersection(Sets...)
337 if (allSatisfy!(ApplyLeft!(isInstanceOf, Set), Sets))
338 {
339     private template Impl(Args...)
340     if (Args.length > 0)
341     {
342         alias Equal = ApplyLeft!(isEqual, Args[0]);
343         static if (Args.length == 1)
344         {
345             enum bool Impl = true;
346         }
347         else static if (!anySatisfy!(Equal, Args[1].Seq))
348         {
349             enum bool Impl = false;
350         }
351         else
352         {
353             enum bool Impl = Impl!(Args[0], Args[2 .. $]);
354         }
355     }
356 
357     private enum bool FilterImpl(Args...) = Impl!(Args[0], Sets[1 .. $]);
358 
359     static if (Sets.length == 0)
360     {
361         alias Intersection = Set!();
362     }
363     else
364     {
365         alias Intersection = Set!(Filter!(FilterImpl, Sets[0].Seq));
366     }
367 }
368 
369 ///
370 @nogc nothrow pure @safe unittest
371 {
372     alias S1 = Set!(2, 5, 8, 4);
373     alias S2 = Set!(3, 8, 4, 1);
374     static assert(Intersection!(S1, S2).Seq == AliasSeq!(8, 4));
375 
376     static assert(Intersection!(S1).Seq == AliasSeq!(2, 5, 8, 4));
377     static assert(Intersection!().length == 0);
378 }
379 
380 /**
381  * Produces a $(D_PSYMBOL Set) that contains all elements of
382  * $(D_PARAM S1) that are not members of $(D_PARAM S2).
383  *
384  * Params:
385  *  S1 = A $(D_PSYMBOL Set).
386  *  S2 = A $(D_PSYMBOL Set).
387  *
388  * Returns: Set-theoretic difference of two sets $(D_PARAM S1) and
389  *          $(D_PARAM S2).
390  *
391  * See_Also: $(D_PSYMBOL Set).
392  */
393 template Difference(alias S1, alias S2)
394 if (isInstanceOf!(Set, S1) && isInstanceOf!(Set, S2))
395 {
396     private template Impl(Args...)
397     {
398         alias Equal = ApplyLeft!(isEqual, Args[0]);
399         enum bool Impl = !anySatisfy!(Equal, S2.Seq);
400     }
401 
402     static if (S1.length == 0)
403     {
404         alias Difference = Set!();
405     }
406     else static if (S2.length == 1)
407     {
408         alias Difference = S1;
409     }
410     else
411     {
412         alias Difference = Set!(Filter!(Impl, S1.Seq));
413     }
414 }
415 
416 ///
417 @nogc nothrow pure @safe unittest
418 {
419     alias S1 = Set!(2, 5, 8, 4);
420     alias S2 = Set!(3, 8, 4, 1);
421     static assert(Difference!(S1, S2).Seq == AliasSeq!(2, 5));
422     static assert(Difference!(S2, S1).Seq == AliasSeq!(3, 1));
423     static assert(Difference!(S1, Set!()).Seq == AliasSeq!(2, 5, 8, 4));
424 }
425 
426 /**
427  * Tests whether $(D_INLINECODE Args[0]) is less than or equal to
428  * $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
429  *
430  * $(D_PARAM cmp) can evaluate to:
431  * $(UL
432  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
433  *       $(D_INLINECODE Args[0] < Args[1]).)
434  *  $(LI $(D_KEYWORD int): a negative number means that
435  *       $(D_INLINECODE Args[0] < Args[1]), a positive number that
436  *       $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
437  * )
438  *
439  * Params:
440  *  Args = Two aliases to compare for equality.
441  *
442  * Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is less than or equal
443  *          to $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
444  */
445 template isLessEqual(alias cmp, Args...)
446 if (Args.length == 2 && __traits(isTemplate, cmp))
447 {
448     private enum result = cmp!(Args[1], Args[0]);
449     static if (is(typeof(result) == bool))
450     {
451         enum bool isLessEqual = !result;
452     }
453     else
454     {
455         enum bool isLessEqual = result >= 0;
456     }
457 }
458 
459 ///
460 @nogc nothrow pure @safe unittest
461 {
462     enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
463     static assert(isLessEqual!(boolCmp, byte, int));
464     static assert(isLessEqual!(boolCmp, uint, int));
465     static assert(!isLessEqual!(boolCmp, long, int));
466 
467     enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
468     static assert(isLessEqual!(intCmp, byte, int));
469     static assert(isLessEqual!(intCmp, uint, int));
470     static assert(!isLessEqual!(intCmp, long, int));
471 }
472 
473 /**
474  * Tests whether $(D_INLINECODE Args[0]) is greater than or equal to
475  * $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
476  *
477  * $(D_PARAM cmp) can evaluate to:
478  * $(UL
479  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
480  *       $(D_INLINECODE Args[0] < Args[1]).)
481  *  $(LI $(D_KEYWORD int): a negative number means that
482  *       $(D_INLINECODE Args[0] < Args[1]), a positive number that
483  *       $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
484  * )
485  *
486  * Params:
487  *  Args = Two aliases to compare for equality.
488  *
489  * Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is greater than or
490  *          equal to $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
491  */
492 template isGreaterEqual(alias cmp, Args...)
493 if (Args.length == 2 && __traits(isTemplate, cmp))
494 {
495     private enum result = cmp!Args;
496     static if (is(typeof(result) == bool))
497     {
498         enum bool isGreaterEqual = !result;
499     }
500     else
501     {
502         enum bool isGreaterEqual = result >= 0;
503     }
504 }
505 
506 ///
507 @nogc nothrow pure @safe unittest
508 {
509     enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
510     static assert(!isGreaterEqual!(boolCmp, byte, int));
511     static assert(isGreaterEqual!(boolCmp, uint, int));
512     static assert(isGreaterEqual!(boolCmp, long, int));
513 
514     enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
515     static assert(!isGreaterEqual!(intCmp, byte, int));
516     static assert(isGreaterEqual!(intCmp, uint, int));
517     static assert(isGreaterEqual!(intCmp, long, int));
518 }
519 
520 /**
521  * Tests whether $(D_INLINECODE Args[0]) is less than
522  * $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
523  *
524  * $(D_PARAM cmp) can evaluate to:
525  * $(UL
526  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
527  *       $(D_INLINECODE Args[0] < Args[1]).)
528  *  $(LI $(D_KEYWORD int): a negative number means that
529  *       $(D_INLINECODE Args[0] < Args[1]), a positive number that
530  *       $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
531  * )
532  *
533  * Params:
534  *  Args = Two aliases to compare for equality.
535  *
536  * Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is less than
537  *          $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
538  */
539 template isLess(alias cmp, Args...)
540 if (Args.length == 2 && __traits(isTemplate, cmp))
541 {
542     private enum result = cmp!Args;
543     static if (is(typeof(result) == bool))
544     {
545         enum bool isLess = result;
546     }
547     else
548     {
549         enum bool isLess = result < 0;
550     }
551 }
552 
553 ///
554 @nogc nothrow pure @safe unittest
555 {
556     enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
557     static assert(isLess!(boolCmp, byte, int));
558     static assert(!isLess!(boolCmp, uint, int));
559     static assert(!isLess!(boolCmp, long, int));
560 
561     enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
562     static assert(isLess!(intCmp, byte, int));
563     static assert(!isLess!(intCmp, uint, int));
564     static assert(!isLess!(intCmp, long, int));
565 }
566 
567 /**
568  * Tests whether $(D_INLINECODE Args[0]) is greater than
569  * $(D_INLINECODE Args[1]) according to $(D_PARAM cmp).
570  *
571  * $(D_PARAM cmp) can evaluate to:
572  * $(UL
573  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
574  *       $(D_INLINECODE Args[0] < Args[1]).)
575  *  $(LI $(D_KEYWORD int): a negative number means that
576  *       $(D_INLINECODE Args[0] < Args[1]), a positive number that
577  *       $(D_INLINECODE Args[0] > Args[1]), `0` if they equal.)
578  * )
579  *
580  * Params:
581  *  Args = Two aliases to compare for equality.
582  *
583  * Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is greater than
584  *          $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
585  */
586 template isGreater(alias cmp, Args...)
587 if (Args.length == 2 && __traits(isTemplate, cmp))
588 {
589     private enum result = cmp!Args;
590     static if (is(typeof(result) == bool))
591     {
592         enum bool isGreater = !result && cmp!(Args[1], Args[0]);
593     }
594     else
595     {
596         enum bool isGreater = result > 0;
597     }
598 }
599 
600 ///
601 @nogc nothrow pure @safe unittest
602 {
603     enum bool boolCmp(T, U) = T.sizeof < U.sizeof;
604     static assert(!isGreater!(boolCmp, byte, int));
605     static assert(!isGreater!(boolCmp, uint, int));
606     static assert(isGreater!(boolCmp, long, int));
607 
608     enum ptrdiff_t intCmp(T, U) = T.sizeof - U.sizeof;
609     static assert(!isGreater!(intCmp, byte, int));
610     static assert(!isGreater!(intCmp, uint, int));
611     static assert(isGreater!(intCmp, long, int));
612 }
613 
614 /**
615  * Tests whether $(D_INLINECODE Args[0]) is equal to $(D_INLINECODE Args[1]).
616  *
617  * $(D_PSYMBOL isEqual) checks first if $(D_PARAM Args) can be compared directly. If not, they are compared as types:
618  * $(D_INLINECODE is(Args[0] == Args[1])). It it fails, the arguments are
619  * considered to be not equal.
620  *
621  * If two items cannot be compared (for example comparing a type with a
622  * number), they are considered not equal.
623  *
624  * Params:
625  *  Args = Two aliases to compare for equality.
626  *
627  * Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) is equal to
628  *          $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
629  */
630 template isEqual(Args...)
631 if (Args.length == 2)
632 {
633     static if ((is(typeof(Args[0] == Args[1])) && (Args[0] == Args[1]))
634             || (isTypeTuple!Args && is(Args[0] == Args[1]))
635             || __traits(isSame, Args[0], Args[1]))
636     {
637         enum bool isEqual = true;
638     }
639     else
640     {
641         enum bool isEqual = false;
642     }
643 }
644 
645 ///
646 @nogc nothrow pure @safe unittest
647 {
648     static assert(isEqual!(int, int));
649     static assert(isEqual!(8, 8));
650     static assert(!isEqual!(int, const(int)));
651     static assert(!isEqual!(5, int));
652     static assert(!isEqual!(5, 8));
653 }
654 
655 /**
656  * Tests whether $(D_INLINECODE Args[0]) isn't equal to
657  * $(D_INLINECODE Args[1]).
658  *
659  * $(D_PSYMBOL isNotEqual) checks first if $(D_PARAM Args) can be compared directly. If not, they are compared as types:
660  * $(D_INLINECODE is(Args[0] == Args[1])). It it fails, the arguments are
661  * considered to be not equal.
662  *
663  * Params:
664  *  Args = Two aliases to compare for equality.
665  *
666  * Returns: $(D_KEYWORD true) if $(D_INLINECODE Args[0]) isn't equal to
667  *          $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
668  */
669 template isNotEqual(Args...)
670 if (Args.length == 2)
671 {
672     enum bool isNotEqual = !isEqual!Args;
673 }
674 
675 ///
676 @nogc nothrow pure @safe unittest
677 {
678     static assert(!isNotEqual!(int, int));
679     static assert(isNotEqual!(5, int));
680     static assert(isNotEqual!(5, 8));
681 }
682 
683 /**
684  * Instantiates the template $(D_PARAM T) with $(D_PARAM Args).
685  *
686  * Params:
687  *  T    = Template.
688  *  Args = Template parameters.
689  *
690  * Returns: Instantiated template.
691  */
692 alias Instantiate(alias T, Args...) = T!Args;
693 
694 ///
695 @nogc nothrow pure @safe unittest
696 {
697     template Template(T)
698     {
699         alias Template = T;
700     }
701     alias Seq = AliasSeq!(Template, Template);
702 
703     alias Instance1 = Instantiate!(Seq[0], int);
704     static assert(is(Instance1 == int));
705 
706     alias Instance2 = Instantiate!(Seq[1], float);
707     static assert(is(Instance2 == float));
708 }
709 
710 /**
711  * Creates an alias for $(D_PARAM T).
712  *
713  * In contrast to the $(D_KEYWORD alias)-keyword $(D_PSYMBOL Alias) can alias
714  * any kind of D symbol that can be used as argument to template alias
715  * parameters.
716  *
717  * $(UL
718  *  $(LI Types)
719  *  $(LI Local and global names)
720  *  $(LI Module names)
721  *  $(LI Template names)
722  *  $(LI Template instance names)
723  *  $(LI Literals)
724  * )
725  *
726  * Params:
727  *  T = A symbol.
728  *
729  * Returns: An alias for $(D_PARAM T).
730  *
731  * See_Also: $(LINK2 https://dlang.org/spec/template.html#aliasparameters,
732  *                   Template Alias Parameters).
733  */
734 alias Alias(alias T) = T;
735 
736 /// ditto
737 alias Alias(T) = T;
738 
739 ///
740 @nogc nothrow pure @safe unittest
741 {
742     static assert(is(Alias!int));
743 
744     static assert(is(typeof(Alias!5)));
745     static assert(is(typeof(Alias!(() {}))));
746 
747     int i;
748     static assert(is(typeof(Alias!i)));
749 }
750 
751 /**
752  * Holds a sequence of aliases.
753  *
754  * $(D_PSYMBOL AliasSeq) can be used to pass multiple parameters to a template
755  * at once. $(D_PSYMBOL AliasSeq) behaves as it were just $(D_PARAM Args). Note
756  * that because of this property, if multiple instances of
757  * $(D_PSYMBOL AliasSeq) are passed to a template, they are not distinguishable
758  * from each other and act as a single sequence. There is also no way to make
759  * $(D_PSYMBOL AliasSeq) nested, it always unpacks its elements.
760  *
761  * Params:
762  *  Args = Symbol sequence.
763  *
764  * Returns: An alias for sequence $(D_PARAM Args).
765  *
766  * See_Also: $(D_PSYMBOL Alias).
767  */
768 alias AliasSeq(Args...) = Args;
769 
770 ///
771 @nogc nothrow pure @safe unittest
772 {
773     static assert(is(typeof({ alias T = AliasSeq!(short, 5); })));
774     static assert(is(typeof({ alias T = AliasSeq!(int, short, 5); })));
775     static assert(is(typeof({ alias T = AliasSeq!(() {}, short, 5); })));
776     static assert(is(typeof({ alias T = AliasSeq!(); })));
777 
778     static assert(AliasSeq!().length == 0);
779     static assert(AliasSeq!(int, short, 5).length == 3);
780 
781     alias A = AliasSeq!(short, float);
782     alias B = AliasSeq!(ushort, double);
783     alias C = AliasSeq!(A, B);
784     static assert(C.length == 4);
785 }
786 
787 /**
788  * Tests whether all the items of $(D_PARAM L) satisfy the condition
789  * $(D_PARAM F).
790  *
791  * $(D_PARAM F) is a template that accepts one parameter and returns a boolean,
792  * so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called.
793  *
794  * Params:
795  *  F = Template predicate. 
796  *  L = List of items to test.
797  *
798  * Returns: $(D_KEYWORD true) if all the items of $(D_PARAM L) satisfy
799  *          $(D_PARAM F), $(D_KEYWORD false) otherwise.
800  */
801 enum bool allSatisfy(alias F, L...) = Filter!(templateNot!F, L).length == 0;
802 
803 ///
804 @nogc nothrow pure @safe unittest
805 {
806     static assert(allSatisfy!(isSigned, int, short, byte, long));
807     static assert(!allSatisfy!(isUnsigned, uint, ushort, float, ulong));
808 }
809 
810 /**
811  * Tests whether any of the items of $(D_PARAM L) satisfy the condition
812  * $(D_PARAM F).
813  *
814  * $(D_PARAM F) is a template that accepts one parameter and returns a boolean,
815  * so $(D_INLINECODE F!([0]) && F!([1])) and so on, can be called.
816  *
817  * Params:
818  *  F = Template predicate. 
819  *  L = List of items to test.
820  *
821  * Returns: $(D_KEYWORD true) if any of the items of $(D_PARAM L) satisfy
822  *          $(D_PARAM F), $(D_KEYWORD false) otherwise.
823  */
824 enum bool anySatisfy(alias F, L...) = Filter!(F, L).length != 0;
825 
826 ///
827 @nogc nothrow pure @safe unittest
828 {
829     static assert(anySatisfy!(isSigned, int, short, byte, long));
830     static assert(anySatisfy!(isUnsigned, uint, ushort, float, ulong));
831     static assert(!anySatisfy!(isSigned, uint, ushort, ulong));
832 }
833 
834 private template indexOf(Args...)
835 {
836     static foreach (i, Arg; Args[1 .. $])
837     {
838         static if (!is(typeof(indexOf) == ptrdiff_t) && isEqual!(Args[0], Arg))
839         {
840             enum ptrdiff_t indexOf = i;
841         }
842     }
843     static if (!is(typeof(indexOf) == ptrdiff_t))
844     {
845         enum ptrdiff_t indexOf = -1;
846     }
847 }
848 
849 /**
850  * Returns the index of the first occurrence of $(D_PARAM T) in $(D_PARAM L).
851  * `-1` is returned if $(D_PARAM T) is not found.
852  *
853  * Params:
854  *  T = The item to search for.
855  *  L = Symbol sequence.
856  *
857  * Returns: The index of the first occurrence of $(D_PARAM T) in $(D_PARAM L).
858  */
859 template staticIndexOf(T, L...)
860 {
861     enum ptrdiff_t staticIndexOf = indexOf!(T, L);
862 }
863 
864 /// ditto
865 template staticIndexOf(alias T, L...)
866 {
867     enum ptrdiff_t staticIndexOf = indexOf!(T, L);
868 }
869 
870 ///
871 @nogc nothrow pure @safe unittest
872 {
873     static assert(staticIndexOf!(int) == -1);
874     static assert(staticIndexOf!(int, int) == 0);
875     static assert(staticIndexOf!(int, float, double, int, real) == 2);
876     static assert(staticIndexOf!(3, () {}, uint, 5, 3) == 3);
877 }
878 
879 /**
880  * Looks for $(D_PARAM T) in $(D_PARAM L) and returns $(D_KEYWORD true) if it
881  * could be found and $(D_KEYWORD false) otherwise.
882  *
883  * Params:
884  *  T = The item to search for.
885  *  L = Symbol sequence.
886  *
887  * Returns: $(D_KEYWORD true) if $(D_PARAM T) can be found in $(D_PARAM L),
888  *          $(D_KEYWORD false) otherwise.
889  */
890 enum bool canFind(T, L...) = staticIndexOf!(T, L) != -1;
891 
892 /// ditto
893 enum bool canFind(alias T, L...) = staticIndexOf!(T, L) != -1;
894 
895 ///
896 @nogc nothrow pure @safe unittest
897 {
898     static assert(!canFind!(int));
899     static assert(canFind!(int, int));
900     static assert(canFind!(int, float, double, int, real));
901     static assert(canFind!(3, () {}, uint, 5, 3));
902 }
903 
904 /*
905  * Tests whether $(D_PARAM T) is a template.
906  *
907  * $(D_PSYMBOL isTemplate) isn't $(D_KEYWORD true) for template instances,
908  * since the latter already represent some type. Only not instantiated
909  * templates, i.e. that accept some template parameters, are considered
910  * templates.
911  *
912  * Params:
913  *  T = A symbol.
914  *
915  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a template,
916  *          $(D_KEYWORD false) otherwise.
917  */
918 private enum bool isTemplate(alias T) = __traits(isTemplate, T);
919 
920 ///
921 @nogc nothrow pure @safe unittest
922 {
923     static struct S(T)
924     {
925     }
926     static assert(isTemplate!S);
927     static assert(!isTemplate!(S!int));
928 }
929 
930 /**
931  * Combines multiple templates with logical AND. So $(D_PSYMBOL templateAnd)
932  * evaluates to $(D_INLINECODE Preds[0] && Preds[1] && Preds[2]) and so on.
933  *
934  * Empty $(D_PARAM Preds) evaluates to $(D_KEYWORD true).
935  *
936  * Params:
937  *  Preds = Template predicates.
938  *
939  * Returns: The constructed template.
940  */
941 template templateAnd(Preds...)
942 if (allSatisfy!(isTemplate, Preds))
943 {
944     template templateAnd(T...)
945     {
946         static if (Preds.length == 0)
947         {
948             enum bool templateAnd = true;
949         }
950         else static if (Instantiate!(Preds[0], T))
951         {
952             alias templateAnd = Instantiate!(.templateAnd!(Preds[1 .. $]), T);
953         }
954         else
955         {
956             enum bool templateAnd = false;
957         }
958     }
959 }
960 
961 ///
962 @nogc nothrow pure @safe unittest
963 {
964     alias isMutableInt = templateAnd!(isIntegral, isMutable);
965     static assert(isMutableInt!int);
966     static assert(!isMutableInt!(const int));
967     static assert(!isMutableInt!float);
968 
969     alias alwaysTrue = templateAnd!();
970     static assert(alwaysTrue!int);
971 
972     alias isIntegral = templateAnd!(.isIntegral);
973     static assert(isIntegral!int);
974     static assert(isIntegral!(const int));
975     static assert(!isIntegral!float);
976 }
977 
978 /**
979  * Combines multiple templates with logical OR. So $(D_PSYMBOL templateOr)
980  * evaluates to $(D_INLINECODE Preds[0] || Preds[1] || Preds[2]) and so on.
981  *
982  * Empty $(D_PARAM Preds) evaluates to $(D_KEYWORD false).
983  *
984  * Params:
985  *  Preds = Template predicates.
986  *
987  * Returns: The constructed template.
988  */
989 template templateOr(Preds...)
990 if (allSatisfy!(isTemplate, Preds))
991 {
992     template templateOr(T...)
993     {
994         static if (Preds.length == 0)
995         {
996             enum bool templateOr = false;
997         }
998         else static if (Instantiate!(Preds[0], T))
999         {
1000             enum bool templateOr = true;
1001         }
1002         else
1003         {
1004             alias templateOr = Instantiate!(.templateOr!(Preds[1 .. $]), T);
1005         }
1006     }
1007 }
1008 
1009 ///
1010 @nogc nothrow pure @safe unittest
1011 {
1012     alias isMutableOrInt = templateOr!(isIntegral, isMutable);
1013     static assert(isMutableOrInt!int);
1014     static assert(isMutableOrInt!(const int));
1015     static assert(isMutableOrInt!float);
1016     static assert(!isMutableOrInt!(const float));
1017 
1018     alias alwaysFalse = templateOr!();
1019     static assert(!alwaysFalse!int);
1020 
1021     alias isIntegral = templateOr!(.isIntegral);
1022     static assert(isIntegral!int);
1023     static assert(isIntegral!(const int));
1024     static assert(!isIntegral!float);
1025 }
1026 
1027 /**
1028  * Params:
1029  *  pred = Template predicate.
1030  *
1031  * Returns: Negated $(D_PARAM pred).
1032  */
1033 template templateNot(alias pred)
1034 if (__traits(isTemplate, pred))
1035 {
1036     enum bool templateNot(T...) = !pred!T;
1037 }
1038 
1039 ///
1040 @nogc nothrow pure @safe unittest
1041 {
1042     alias isNotIntegral = templateNot!isIntegral;
1043     static assert(!isNotIntegral!int);
1044     static assert(isNotIntegral!(char[]));
1045 }
1046 
1047 /**
1048  * Tests whether $(D_PARAM L) is sorted in ascending order according to
1049  * $(D_PARAM cmp).
1050  *
1051  * $(D_PARAM cmp) can evaluate to:
1052  * $(UL
1053  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
1054  *       $(D_INLINECODE a[i] < a[i + 1]).)
1055  *  $(LI $(D_KEYWORD int): a negative number means that
1056  *       $(D_INLINECODE a[i] < a[i + 1]), a positive number that
1057  *       $(D_INLINECODE a[i] > a[i + 1]), `0` if they equal.)
1058  * )
1059  *
1060  * Params:
1061  *  cmp = Sorting template predicate.
1062  *  L   = Elements to be tested.
1063  *
1064  * Returns: $(D_KEYWORD true) if $(D_PARAM L) is sorted, $(D_KEYWORD false)
1065  *          if not.
1066  */
1067 template isSorted(alias cmp, L...)
1068 if (__traits(isTemplate, cmp))
1069 {
1070     static if (L.length <= 1)
1071     {
1072         enum bool isSorted = true;
1073     }
1074     else
1075     {
1076         // `L` is sorted if the both halves and the boundary values are sorted.
1077         enum bool isSorted = isLessEqual!(cmp, L[$ / 2 - 1], L[$ / 2])
1078                           && isSorted!(cmp, L[0 .. $ / 2])
1079                           && isSorted!(cmp, L[$ / 2 .. $]);
1080     }
1081 }
1082 
1083 ///
1084 @nogc nothrow pure @safe unittest
1085 {
1086     enum cmp(T, U) = T.sizeof < U.sizeof;
1087     static assert(isSorted!(cmp));
1088     static assert(isSorted!(cmp, byte));
1089     static assert(isSorted!(cmp, byte, ubyte, short, uint));
1090     static assert(!isSorted!(cmp, long, byte, ubyte, short, uint));
1091 }
1092 
1093 /**
1094  * Params:
1095  *  T    = A template.
1096  *  Args = The first arguments for $(D_PARAM T).
1097  *
1098  * Returns: $(D_PARAM T) with $(D_PARAM Args) applied to it as its first
1099  *          arguments.
1100  */
1101 template ApplyLeft(alias T, Args...)
1102 {
1103     alias ApplyLeft(U...) = T!(Args, U);
1104 }
1105 
1106 ///
1107 @nogc nothrow pure @safe unittest
1108 {
1109     alias allAreIntegral = ApplyLeft!(allSatisfy, isIntegral);
1110     static assert(allAreIntegral!(int, uint));
1111     static assert(!allAreIntegral!(int, float, uint));
1112 }
1113 
1114 /**
1115  * Params:
1116  *  T    = A template.
1117  *  Args = The last arguments for $(D_PARAM T).
1118  *
1119  * Returns: $(D_PARAM T) with $(D_PARAM Args) applied to it as itslast
1120  *          arguments.
1121  */
1122 template ApplyRight(alias T, Args...)
1123 {
1124     alias ApplyRight(U...) = T!(U, Args);
1125 }
1126 
1127 ///
1128 @nogc nothrow pure @safe unittest
1129 {
1130     alias intIs = ApplyRight!(allSatisfy, int);
1131     static assert(intIs!(isIntegral));
1132     static assert(!intIs!(isUnsigned));
1133 }
1134 
1135 /**
1136  * Params:
1137  *  n = The number of times to repeat $(D_PARAM L).
1138  *  L = The sequence to be repeated.
1139  *
1140  * Returns: $(D_PARAM L) repeated $(D_PARAM n) times.
1141  */
1142 template Repeat(size_t n, L...)
1143 if (n > 0)
1144 {
1145     static if (n == 1)
1146     {
1147         alias Repeat = L;
1148     }
1149     else
1150     {
1151         alias Repeat = AliasSeq!(L, Repeat!(n - 1, L));
1152     }
1153 }
1154 
1155 ///
1156 @nogc nothrow pure @safe unittest
1157 {
1158     static assert(is(Repeat!(1, uint, int) == AliasSeq!(uint, int)));
1159     static assert(is(Repeat!(2, uint, int) == AliasSeq!(uint, int, uint, int)));
1160     static assert(is(Repeat!(3) == AliasSeq!()));
1161 }
1162 
1163 private template ReplaceOne(L...)
1164 {
1165     static if (L.length == 2)
1166     {
1167         alias ReplaceOne = AliasSeq!();
1168     }
1169     else static if (isEqual!(L[0], L[2]))
1170     {
1171         alias ReplaceOne = AliasSeq!(L[1], L[3 .. $]);
1172     }
1173     else
1174     {
1175         alias ReplaceOne = AliasSeq!(L[2], ReplaceOne!(L[0], L[1], L[3 .. $]));
1176     }
1177 }
1178 
1179 /**
1180  * Replaces the first occurrence of $(D_PARAM T) in $(D_PARAM L) with
1181  * $(D_PARAM U).
1182  *
1183  * Params:
1184  *  T = The symbol to be replaced.
1185  *  U = Replacement.
1186  *  L = List of symbols.
1187  *
1188  * Returns: $(D_PARAM L) with the first occurrence of $(D_PARAM T) replaced.
1189  */
1190 template Replace(T, U, L...)
1191 {
1192     alias Replace = ReplaceOne!(T, U, L);
1193 }
1194 
1195 /// ditto
1196 template Replace(alias T, U, L...)
1197 {
1198     alias Replace = ReplaceOne!(T, U, L);
1199 }
1200 
1201 /// ditto
1202 template Replace(T, alias U, L...)
1203 {
1204     alias Replace = ReplaceOne!(T, U, L);
1205 }
1206 
1207 /// ditto
1208 template Replace(alias T, alias U, L...)
1209 {
1210     alias Replace = ReplaceOne!(T, U, L);
1211 }
1212 
1213 ///
1214 @nogc nothrow pure @safe unittest
1215 {
1216     static assert(is(Replace!(int, uint, int) == AliasSeq!(uint)));
1217     static assert(is(Replace!(int, uint, short, int, int, ushort)
1218                == AliasSeq!(short, uint, int, ushort)));
1219 
1220     static assert(Replace!(5, 8, 1, 2, 5, 5) == AliasSeq!(1, 2, 8, 5));
1221 }
1222 
1223 private template ReplaceAllImpl(L...)
1224 {
1225     static if (L.length == 2)
1226     {
1227         alias ReplaceAllImpl = AliasSeq!();
1228     }
1229     else
1230     {
1231         private alias Rest = ReplaceAllImpl!(L[0], L[1], L[3 .. $]);
1232         static if (isEqual!(L[0], L[2]))
1233         {
1234             alias ReplaceAllImpl = AliasSeq!(L[1], Rest);
1235         }
1236         else
1237         {
1238             alias ReplaceAllImpl = AliasSeq!(L[2], Rest);
1239         }
1240     }
1241 }
1242 
1243 /**
1244  * Replaces all occurrences of $(D_PARAM T) in $(D_PARAM L) with $(D_PARAM U).
1245  *
1246  * Params:
1247  *  T = The symbol to be replaced.
1248  *  U = Replacement.
1249  *  L = List of symbols.
1250  *
1251  * Returns: $(D_PARAM L) with all occurrences of $(D_PARAM T) replaced.
1252  */
1253 template ReplaceAll(T, U, L...)
1254 {
1255     alias ReplaceAll = ReplaceAllImpl!(T, U, L);
1256 }
1257 
1258 /// ditto
1259 template ReplaceAll(alias T, U, L...)
1260 {
1261     alias ReplaceAll = ReplaceAllImpl!(T, U, L);
1262 }
1263 
1264 /// ditto
1265 template ReplaceAll(T, alias U, L...)
1266 {
1267     alias ReplaceAll = ReplaceAllImpl!(T, U, L);
1268 }
1269 
1270 /// ditto
1271 template ReplaceAll(alias T, alias U, L...)
1272 {
1273     alias ReplaceAll = ReplaceAllImpl!(T, U, L);
1274 }
1275 
1276 ///
1277 @nogc nothrow pure @safe unittest
1278 {
1279     static assert(is(ReplaceAll!(int, uint, int) == AliasSeq!(uint)));
1280     static assert(is(ReplaceAll!(int, uint, short, int, int, ushort)
1281                == AliasSeq!(short, uint, uint, ushort)));
1282 
1283     static assert(ReplaceAll!(5, 8, 1, 2, 5, 5) == AliasSeq!(1, 2, 8, 8));
1284 }
1285 
1286 /**
1287  * Params:
1288  *  L = List of symbols.
1289  *
1290  * Returns: $(D_PARAM L) with elements in reversed order.
1291  */
1292 template Reverse(L...)
1293 {
1294     static if (L.length == 0)
1295     {
1296         alias Reverse = AliasSeq!();
1297     }
1298     else
1299     {
1300         alias Reverse = AliasSeq!(L[$ - 1], Reverse!(L[0 .. $ - 1]));
1301     }
1302 }
1303 
1304 ///
1305 @nogc nothrow pure @safe unittest
1306 {
1307     static assert(is(Reverse!(byte, short, int) == AliasSeq!(int, short, byte)));
1308 }
1309 
1310 /**
1311  * Applies $(D_PARAM F) to all elements of $(D_PARAM T).
1312  *
1313  * Params:
1314  *  F = Template predicate.
1315  *  T = List of symbols.
1316  *
1317  * Returns: Elements $(D_PARAM T) after applying $(D_PARAM F) to them.
1318  */
1319 template Map(alias F, T...)
1320 if (__traits(isTemplate, F))
1321 {
1322     static if (T.length == 0)
1323     {
1324         alias Map = AliasSeq!();
1325     }
1326     else
1327     {
1328         alias Map = AliasSeq!(F!(T[0]), Map!(F, T[1 .. $]));
1329     }
1330 }
1331 
1332 ///
1333 @nogc nothrow pure @safe unittest
1334 {
1335     static assert(is(Map!(Unqual, const int, immutable short)
1336                == AliasSeq!(int, short)));
1337 }
1338 
1339 /**
1340  * Sorts $(D_PARAM L) in ascending order according to $(D_PARAM cmp).
1341  *
1342  * $(D_PARAM cmp) can evaluate to:
1343  * $(UL
1344  *  $(LI $(D_KEYWORD bool): $(D_KEYWORD true) means
1345  *       $(D_INLINECODE a[i] < a[i + 1]).)
1346  *  $(LI $(D_KEYWORD int): a negative number means that
1347  *       $(D_INLINECODE a[i] < a[i + 1]), a positive number that
1348  *       $(D_INLINECODE a[i] > a[i + 1]), `0` if they equal.)
1349  * )
1350  *
1351  * Merge sort is used to sort the arguments.
1352  *
1353  * Params:
1354  *  cmp = Sorting template predicate.
1355  *  L   = Elements to be sorted.
1356  *
1357  * Returns: Elements of $(D_PARAM L) in ascending order.
1358  *
1359  * See_Also: $(LINK2 https://en.wikipedia.org/wiki/Merge_sort, Merge sort).
1360  */
1361 template Sort(alias cmp, L...)
1362 if (__traits(isTemplate, cmp))
1363 {
1364     private template merge(size_t A, size_t B)
1365     {
1366         static if (A + B == L.length)
1367         {
1368             alias merge = AliasSeq!();
1369         }
1370         else static if (B >= Right.length
1371                      || (A < Left.length && isLessEqual!(cmp, Left[A], Right[B])))
1372         {
1373             alias merge = AliasSeq!(Left[A], merge!(A + 1, B));
1374         }
1375         else
1376         {
1377             alias merge = AliasSeq!(Right[B], merge!(A, B + 1));
1378         }
1379     }
1380 
1381     static if (L.length <= 1)
1382     {
1383         alias Sort = L;
1384     }
1385     else
1386     {
1387         private alias Left = Sort!(cmp, L[0 .. $ / 2]);
1388         private alias Right = Sort!(cmp, L[$ / 2 .. $]);
1389         alias Sort = merge!(0, 0);
1390     }
1391 }
1392 
1393 ///
1394 @nogc nothrow pure @safe unittest
1395 {
1396     enum cmp(T, U) = T.sizeof < U.sizeof;
1397     static assert(is(Sort!(cmp, long, short, byte, int)
1398                == AliasSeq!(byte, short, int, long)));
1399 }
1400 
1401 @nogc nothrow pure @safe unittest
1402 {
1403     enum cmp(int T, int U) = T - U;
1404     static assert(Sort!(cmp, 5, 17, 9, 12, 2, 10, 14)
1405                == AliasSeq!(2, 5, 9, 10, 12, 14, 17));
1406 }
1407 
1408 private enum bool DerivedToFrontCmp(A, B) = is(A : B);
1409 
1410 /**
1411  * Returns $(D_PARAM L) sorted in such a way that the most derived types come
1412  * first.
1413  *
1414  * Params:
1415  *  L = Type tuple.
1416  *
1417  * Returns: Sorted $(D_PARAM L).
1418  */
1419 template DerivedToFront(L...)
1420 {
1421     alias DerivedToFront = Sort!(DerivedToFrontCmp, L);
1422 }
1423 
1424 ///
1425 @nogc nothrow pure @safe unittest
1426 {
1427     class A
1428     {
1429     }
1430     class B : A
1431     {
1432     }
1433     class C : B
1434     {
1435     }
1436     static assert(is(DerivedToFront!(B, A, C) == AliasSeq!(C, B, A)));
1437 }
1438 
1439 /**
1440  * Returns the type from the type tuple $(D_PARAM L) that is most derived from
1441  * $(D_PARAM T).
1442  *
1443  * Params:
1444  *  T = The type to compare to.
1445  *  L = Type tuple.
1446  *
1447  * Returns: The type most derived from $(D_PARAM T).
1448  */
1449 template MostDerived(T, L...)
1450 {
1451     static if (L.length == 0)
1452     {
1453         alias MostDerived = T;
1454     }
1455     else static if (is(T : L[0]))
1456     {
1457         alias MostDerived = MostDerived!(T, L[1 .. $]);
1458     }
1459     else
1460     {
1461         alias MostDerived = MostDerived!(L[0], L[1 .. $]);
1462     }
1463 }
1464 
1465 ///
1466 @nogc nothrow pure @safe unittest
1467 {
1468     class A
1469     {
1470     }
1471     class B : A
1472     {
1473     }
1474     class C : B
1475     {
1476     }
1477     static assert(is(MostDerived!(A, C, B) == C));
1478 }
1479 
1480 private template EraseOne(L...)
1481 if (L.length > 0)
1482 {
1483     static if (L.length == 1)
1484     {
1485         alias EraseOne = AliasSeq!();
1486     }
1487     else static if (isEqual!(L[0 .. 2]))
1488     {
1489         alias EraseOne = AliasSeq!(L[2 .. $]);
1490     }
1491     else
1492     {
1493         alias EraseOne = AliasSeq!(L[1], EraseOne!(L[0], L[2 .. $]));
1494     }
1495 }
1496 
1497 /**
1498  * Removes the first occurrence of $(D_PARAM T) from the alias sequence
1499  * $(D_PARAL L).
1500  *
1501  * Params:
1502  *  T = The item to be removed.
1503  *  L = Alias sequence.
1504  *
1505  * Returns: $(D_PARAM L) with the first occurrence of $(D_PARAM T) removed.
1506  */
1507 template Erase(T, L...)
1508 {
1509     alias Erase = EraseOne!(T, L);
1510 }
1511 
1512 /// ditto
1513 template Erase(alias T, L...)
1514 {
1515     alias Erase = EraseOne!(T, L);
1516 }
1517 
1518 ///
1519 @nogc nothrow pure @safe unittest
1520 {
1521     static assert(is(Erase!(int, short, int, int, uint) == AliasSeq!(short, int, uint)));
1522     static assert(is(Erase!(int, short, uint) == AliasSeq!(short, uint)));
1523 }
1524 
1525 private template EraseAllImpl(L...)
1526 {
1527     static if (L.length == 1)
1528     {
1529         alias EraseAllImpl = AliasSeq!();
1530     }
1531     else static if (isEqual!(L[0 .. 2]))
1532     {
1533         alias EraseAllImpl = EraseAllImpl!(L[0], L[2 .. $]);
1534     }
1535     else
1536     {
1537         alias EraseAllImpl = AliasSeq!(L[1], EraseAllImpl!(L[0], L[2 .. $]));
1538     }
1539 }
1540 
1541 /**
1542  * Removes all occurrences of $(D_PARAM T) from the alias sequence $(D_PARAL L).
1543  *
1544  * Params:
1545  *  T = The item to be removed.
1546  *  L = Alias sequence.
1547  *
1548  * Returns: $(D_PARAM L) with all occurrences of $(D_PARAM T) removed.
1549  */
1550 template EraseAll(T, L...)
1551 {
1552     alias EraseAll = EraseAllImpl!(T, L);
1553 }
1554 
1555 /// ditto
1556 template EraseAll(alias T, L...)
1557 {
1558     alias EraseAll = EraseAllImpl!(T, L);
1559 }
1560 
1561 ///
1562 @nogc nothrow pure @safe unittest
1563 {
1564     static assert(is(EraseAll!(int, short, int, int, uint) == AliasSeq!(short, uint)));
1565     static assert(is(EraseAll!(int, short, uint) == AliasSeq!(short, uint)));
1566     static assert(is(EraseAll!(int, int, int) == AliasSeq!()));
1567 }
1568 
1569 /**
1570  * Returns an alias sequence which contains only items that satisfy the
1571  * condition $(D_PARAM pred).
1572  *
1573  * Params:
1574  *  pred = Template predicate.
1575  *  L    = Alias sequence.
1576  *
1577  * Returns: $(D_PARAM L) filtered so that it contains only items that satisfy
1578  *          $(D_PARAM pred).
1579  */
1580 template Filter(alias pred, L...)
1581 if (__traits(isTemplate, pred))
1582 {
1583     static if (L.length == 0)
1584     {
1585         alias Filter = AliasSeq!();
1586     }
1587     else static if (pred!(L[0]))
1588     {
1589         alias Filter = AliasSeq!(L[0], Filter!(pred, L[1 .. $]));
1590     }
1591     else
1592     {
1593         alias Filter = Filter!(pred, L[1 .. $]);
1594     }
1595 }
1596 
1597 ///
1598 @nogc nothrow pure @safe unittest
1599 {
1600     alias Given = AliasSeq!(real, int, bool, uint);
1601     static assert(is(Filter!(isIntegral, Given) == AliasSeq!(int, uint)));
1602 }
1603 
1604 /**
1605  * Removes all duplicates from the alias sequence $(D_PARAM L).
1606  *
1607  * Params:
1608  *  L = Alias sequence.
1609  *
1610  * Returns: $(D_PARAM L) containing only unique items.
1611  */
1612 template NoDuplicates(L...)
1613 {
1614     static if (L.length == 0)
1615     {
1616         alias NoDuplicates = AliasSeq!();
1617     }
1618     else
1619     {
1620         private alias Rest = NoDuplicates!(EraseAll!(L[0], L[1 .. $]));
1621         alias NoDuplicates = AliasSeq!(L[0], Rest);
1622     }
1623 }
1624 
1625 ///
1626 @nogc nothrow pure @safe unittest
1627 {
1628     alias Given = AliasSeq!(int, uint, int, short, short, uint);
1629     static assert(is(NoDuplicates!Given == AliasSeq!(int, uint, short)));
1630 }
1631 
1632 /**
1633  * Converts an input range $(D_PARAM range) into an alias sequence.
1634  *
1635  * Params:
1636  *  range = Input range.
1637  *
1638  * Returns: Alias sequence with items from $(D_PARAM range).
1639  */
1640 template aliasSeqOf(alias range)
1641 {
1642     static if (isArray!(typeof(range)))
1643     {
1644         static if (range.length == 0)
1645         {
1646             alias aliasSeqOf = AliasSeq!();
1647         }
1648         else
1649         {
1650             alias aliasSeqOf = AliasSeq!(range[0], aliasSeqOf!(range[1 .. $]));
1651         }
1652     }
1653     else
1654     {
1655         ReturnType!(typeof(&range.front))[] toArray(typeof(range) range)
1656         {
1657             typeof(return) result;
1658             foreach (r; range)
1659             {
1660                 result ~= r;
1661             }
1662             return result;
1663         }
1664         alias aliasSeqOf = aliasSeqOf!(toArray(range));
1665     }
1666 }
1667 
1668 ///
1669 @nogc nothrow pure @safe unittest
1670 {
1671     static assert(aliasSeqOf!([0, 1, 2, 3]) == AliasSeq!(0, 1, 2, 3));
1672 }
1673 
1674 /**
1675  * Produces a alias sequence consisting of every $(D_PARAM n)th element of
1676  * $(D_PARAM Args), starting with the first.
1677  *
1678  * Params:
1679  *  n    = Step.
1680  *  Args = The items to stride.
1681  *
1682  * Returns: Alias sequence of every $(D_PARAM n)th element of $(D_PARAM Args).
1683  */
1684 template Stride(size_t n, Args...)
1685 if (n > 0)
1686 {
1687     static if (Args.length > n)
1688     {
1689         alias Stride = AliasSeq!(Args[0], Stride!(n, Args[n .. $]));
1690     }
1691     else static if (Args.length > 0)
1692     {
1693         alias Stride = AliasSeq!(Args[0]);
1694     }
1695     else
1696     {
1697         alias Stride = AliasSeq!();
1698     }
1699 }
1700 
1701 ///
1702 @nogc nothrow pure @safe unittest
1703 {
1704     static assert(Stride!(3, 1, 2, 3, 4, 5, 6, 7, 8) == AliasSeq!(1, 4, 7));
1705     static assert(Stride!(2, 1, 2, 3) == AliasSeq!(1, 3));
1706     static assert(Stride!(2, 1, 2) == AliasSeq!(1));
1707     static assert(Stride!(2, 1) == AliasSeq!(1));
1708     static assert(Stride!(1, 1, 2, 3) == AliasSeq!(1, 2, 3));
1709     static assert(is(Stride!3 == AliasSeq!()));
1710 }
1711 
1712 /**
1713  * Aliases itself to $(D_INLINECODE T[0]) if $(D_PARAM cond) is $(D_KEYWORD true),
1714  * to $(D_INLINECODE T[1]) if $(D_KEYWORD false).
1715  *
1716  * Params:
1717  *  cond = Template predicate.
1718  *  T    = Two arguments.
1719  *
1720  * Returns: $(D_INLINECODE T[0]) if $(D_PARAM cond) is $(D_KEYWORD true),
1721  * $(D_INLINECODE T[1]) otherwise.
1722  */
1723 template Select(bool cond, T...)
1724 if (T.length == 2)
1725 {
1726     static if (cond)
1727     {
1728         alias Select = T[0];
1729     }
1730     else
1731     {
1732         alias Select = T[1];
1733     }
1734 }
1735 
1736 ///
1737 @nogc nothrow pure @safe unittest
1738 {
1739     static assert(is(Select!(true, int, float) == int));
1740     static assert(is(Select!(false, int, float) == float));
1741 }
1742 
1743 /**
1744  * Attaches a numeric index to each element from $(D_PARAM Args).
1745  *
1746  * $(D_PSYMBOL EnumerateFrom) returns a sequence of tuples ($(D_PSYMBOL Pack)s)
1747  * consisting of the index of each element and the element itself.
1748  *
1749  * Params:
1750  *  start = Enumeration initial value.
1751  *  Args  = Enumerated sequence.
1752  *
1753  * See_Also: $(D_PSYMBOL Enumerate).
1754  */
1755 template EnumerateFrom(size_t start, Args...)
1756 {
1757     static if (Args.length == 0)
1758     {
1759         alias EnumerateFrom = AliasSeq!();
1760     }
1761     else
1762     {
1763         alias EnumerateFrom = AliasSeq!(Pack!(start, Args[0]), EnumerateFrom!(start + 1, Args[1 .. $]));
1764     }
1765 }
1766 
1767 ///
1768 @nogc nothrow pure @safe unittest
1769 {
1770     static assert(EnumerateFrom!(0, int, uint, bool).length == 3);
1771 }
1772 
1773 ///
1774 @nogc nothrow pure @safe unittest
1775 {
1776     alias Expected = AliasSeq!(Pack!(cast(size_t) 0, int),
1777                                Pack!(cast(size_t) 1, uint));
1778     static assert(is(EnumerateFrom!(0, int, uint) == Expected));
1779 }
1780 
1781 /**
1782  * Attaches a numeric index to each element from $(D_PARAM Args).
1783  *
1784  * $(D_PSYMBOL EnumerateFrom) returns a sequence of tuples ($(D_PSYMBOL Pack)s)
1785  * consisting of the index of each element and the element itself.
1786  *
1787  * Params:
1788  *  Args  = Enumerated sequence.
1789  *
1790  * See_Also: $(D_PSYMBOL EnumerateFrom).
1791  */
1792 alias Enumerate(Args...) = EnumerateFrom!(0, Args);
1793 
1794 ///
1795 @nogc nothrow pure @safe unittest
1796 {
1797     alias Expected = AliasSeq!(Pack!(cast(size_t) 0, int),
1798                                Pack!(cast(size_t) 1, uint));
1799     static assert(is(Enumerate!(int, uint) == Expected));
1800 }