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