1 // Written in the D programming language
2 /++
3     Templates to manipulate
4     $(DDSUBLINK spec/template, variadic-templates, template parameter sequences)
5     (also known as $(I alias sequences)).
6 
7     Some operations on alias sequences are built into the language,
8     such as `S[i]`, which accesses the element at index `i` in the
9     sequence. `S[low .. high]` returns a new alias
10     sequence that is a slice of the old one.
11 
12     For more information, see
13     $(DDLINK ctarguments, Compile-time Sequences, Compile-time Sequences).
14 
15     One thing that should be noted is that while the templates provided in this
16     module can be extremely useful, they generally should not be used with lists
17     of values. The language uses alias sequences for a variety of things
18     (including both parameter lists and argument lists), so they can contain
19     types, symbols, values, or a mixture of them all. The ability to manipulate
20     types and symbols within alias sequences is vital, because that's really
21     the only way to do it. However, because D has CTFE (Compile-Time Function
22     Evaluation), making it possible to call many functions at compile time, if
23     code needs to be able to manipulate values at compile-time, CTFE is
24     typically much more efficient and easier to do. Instantiating a bunch of
25     templates to manipulate values is incredibly inefficient in comparison.
26 
27     So, while many of the templates in this module will work with values simply
28     because alias sequences can contain values, most code should restrict
29     itself to using them for operating on types or symbols - i.e. the stuff
30     where CTFE can't be used. That being said, there will be times when one can
31     be used to feed into the other. E.G.
32     ---
33     alias Types = AliasSeq!(int, byte, ulong, int[10]);
34 
35     enum Sizeof(T) = T.sizeof;
36 
37     alias sizesAsAliasSeq = Map!(Sizeof, Types);
38     static assert(sizesAsAliasSeq == AliasSeq!(4, 1, 8, 40));
39 
40     enum size_t[] sizes = [sizesAsAliasSeq];
41     static assert(sizes == [4, 1, 8, 40]);
42     ---
43 
44     Just be aware that if CTFE can be used for a particular task, it's better to
45     use CTFE than to manipulate alias sequences with the kind of templates
46     provided by this module.
47 
48     $(SCRIPT inhibitQuickIndex = 1;)
49     $(DIVC quickindex,
50     $(BOOKTABLE ,
51     $(TR $(TH Category) $(TH Templates))
52     $(TR $(TD Building blocks) $(TD
53               $(LREF Alias)
54               $(LREF AliasSeq)
55     ))
56     $(TR $(TD Alias sequence filtering) $(TD
57               $(LREF Filter)
58               $(LREF Stride)
59               $(LREF Unique)
60     ))
61     $(TR $(TD Alias sequence transformation) $(TD
62               $(LREF Map)
63               $(LREF Reverse)
64     ))
65     $(TR $(TD Alias sequence searching) $(TD
66               $(LREF all)
67               $(LREF any)
68               $(LREF indexOf)
69     ))
70     $(TR $(TD Template predicates) $(TD
71               $(LREF And)
72               $(LREF Not)
73               $(LREF Or)
74     ))
75     $(TR $(TD Template instantiation) $(TD
76               $(LREF ApplyLeft)
77               $(LREF ApplyRight)
78               $(LREF Instantiate)
79     ))
80     )
81 
82    References:
83        Based on ideas in Table 3.1 from
84        $(LINK2 http://amazon.com/exec/obidos/ASIN/0201704315/ref=ase_classicempire/102-2957199-2585768,
85          Modern C++ Design),
86        Andrei Alexandrescu (Addison-Wesley Professional, 2001)
87 
88     Copyright: Copyright The D Language Foundation 2005 - 2024.
89     License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
90     Authors: $(HTTP digitalmars.com, Walter Bright),
91              $(HTTP klickverbot.at, David Nadlinger)
92              $(HTTP jmdavisprog.com, Jonathan M Davis)
93     Source:    $(PHOBOSSRC phobos/sys/meta)
94 +/
95 module phobos.sys.meta;
96 
97 // Example for converting types to values from module documentation.
98 @safe unittest
99 {
100     alias Types = AliasSeq!(int, byte, ulong, int[10]);
101 
102     enum Sizeof(T) = T.sizeof;
103 
104     alias sizesAsAliasSeq = Map!(Sizeof, Types);
105     static assert(sizesAsAliasSeq == AliasSeq!(4, 1, 8, 40));
106 
107     enum size_t[] sizes = [sizesAsAliasSeq];
108     static assert(sizes == [4, 1, 8, 40]);
109 }
110 
111 /++
112    Creates a sequence of zero or more aliases. This is most commonly
113    used as template parameters or arguments.
114  +/
115 alias AliasSeq(TList...) = TList;
116 
117 ///
118 @safe unittest
119 {
120     alias TL = AliasSeq!(int, double);
121 
122     int foo(TL td)  // same as int foo(int, double);
123     {
124         return td[0] + cast(int) td[1];
125     }
126 }
127 
128 ///
129 @safe unittest
130 {
131     alias TL = AliasSeq!(int, double);
132 
133     alias Types = AliasSeq!(TL, char);
134     static assert(is(Types == AliasSeq!(int, double, char)));
135 }
136 
137 ///
138 @safe unittest
139 {
140     static char foo(size_t i, string str)
141     {
142         return str[i];
143     }
144 
145     alias vars = AliasSeq!(2, "dlang");
146 
147     assert(foo(vars) == 'a');
148 }
149 
150 /++
151     Allows aliasing of any single symbol, type or compile-time expression.
152 
153     Not everything can be directly aliased. An alias cannot be declared
154     of - for example - a literal:
155     ---
156     alias a = 4; //Error
157     ---
158     With this template any single entity can be aliased:
159     ---
160     alias b = Alias!4; //OK
161     ---
162     See_Also:
163         To alias more than one thing at once, use $(LREF AliasSeq).
164   +/
165 alias Alias(alias a) = a;
166 
167 /// Ditto
168 alias Alias(T) = T;
169 
170 ///
171 @safe unittest
172 {
173     // Without Alias this would fail if Args[0] were e.g. a value and
174     // some logic would be needed to detect when to use enum instead.
175     alias Head(Args...) = Alias!(Args[0]);
176     alias Tail(Args...) = Args[1 .. $];
177 
178     alias Blah = AliasSeq!(3, int, "hello");
179     static assert(Head!Blah == 3);
180     static assert(is(Head!(Tail!Blah) == int));
181     static assert((Tail!Blah)[1] == "hello");
182 }
183 
184 ///
185 @safe unittest
186 {
187     {
188         alias a = Alias!123;
189         static assert(a == 123);
190     }
191     {
192         enum e = 1;
193         alias a = Alias!e;
194         static assert(a == 1);
195     }
196     {
197         alias a = Alias!(3 + 4);
198         static assert(a == 7);
199     }
200     {
201         alias concat = (s0, s1) => s0 ~ s1;
202         alias a = Alias!(concat("Hello", " World!"));
203         static assert(a == "Hello World!");
204     }
205     {
206         alias A = Alias!int;
207         static assert(is(A == int));
208     }
209     {
210         alias A = Alias!(AliasSeq!int);
211         static assert(!is(typeof(A[0]))); // An Alias is not an AliasSeq.
212         static assert(is(A == int));
213     }
214     {
215         auto i = 6;
216         alias a = Alias!i;
217         ++a;
218         assert(i == 7);
219     }
220 }
221 
222 /++
223     Filters an $(D AliasSeq) using the given template predicate.
224 
225     The result is an $(D AliasSeq) that contains only the elements which satisfy
226     the predicate.
227   +/
228 template Filter(alias Pred, Args...)
229 {
230     alias Filter = AliasSeq!();
231     static foreach (Arg; Args)
232     {
233         static if (Pred!Arg)
234             Filter = AliasSeq!(Filter, Arg);
235     }
236 }
237 
238 ///
239 @safe unittest
240 {
241     import phobos.sys.traits : isDynamicArray, isPointer, isUnsignedInteger;
242 
243     alias Types = AliasSeq!(string, int, int[], bool[], ulong, double, ubyte);
244 
245     static assert(is(Filter!(isDynamicArray, Types) ==
246                      AliasSeq!(string, int[], bool[])));
247 
248     static assert(is(Filter!(isUnsignedInteger, Types) ==
249                      AliasSeq!(ulong, ubyte)));
250 
251     static assert(is(Filter!(isPointer, Types) == AliasSeq!()));
252 }
253 
254 /++
255     Evaluates to an $(LREF AliasSeq) which only contains every nth element from
256     the $(LREF AliasSeq) that was passed in, where $(D n) is stepSize.
257 
258     So, if stepSize is $(D 2), then the result contains every other element from
259     the original. If stepSize is $(D 3), then the result contains every third
260     element from the original. Etc.
261 
262     If stepSize is negative, then the result is equivalent to using
263     $(LREF Reverse) on the given $(LREF AliasSeq) and then using Stride on it
264     with the absolute value of that stepSize.
265 
266     If stepSize is positive, then the first element in the original
267     $(LREF AliasSeq) is the first element in the result, whereas if stepSize is
268     negative, then the last element in the original is the first element in the
269     result. Each subsequent element is then the element at the index of the
270     previous element plus stepSize.
271   +/
272 template Stride(int stepSize, Args...)
273 if (stepSize != 0)
274 {
275     alias Stride = AliasSeq!();
276     static if (stepSize > 0)
277     {
278         static foreach (i; 0 .. (Args.length + stepSize - 1) / stepSize)
279             Stride = AliasSeq!(Stride, Args[i * stepSize]);
280     }
281     else
282     {
283         static foreach (i; 0 .. (Args.length - stepSize - 1) / -stepSize)
284             Stride = AliasSeq!(Stride, Args[$ - 1 + i * stepSize]);
285     }
286 }
287 
288 ///
289 @safe unittest
290 {
291     static assert(is(Stride!(1, short, int, long) == AliasSeq!(short, int, long)));
292     static assert(is(Stride!(2, short, int, long) == AliasSeq!(short, long)));
293     static assert(is(Stride!(3, short, int, long) == AliasSeq!short));
294     static assert(is(Stride!(100, short, int, long) == AliasSeq!short));
295 
296     static assert(is(Stride!(-1, short, int, long) == AliasSeq!(long, int, short)));
297     static assert(is(Stride!(-2, short, int, long) == AliasSeq!(long, short)));
298     static assert(is(Stride!(-3, short, int, long) == AliasSeq!long));
299     static assert(is(Stride!(-100, short, int, long) == AliasSeq!long));
300 
301     alias Types = AliasSeq!(short, int, long, ushort, uint, ulong);
302     static assert(is(Stride!(3, Types) == AliasSeq!(short, ushort)));
303     static assert(is(Stride!(3, Types[1 .. $]) == AliasSeq!(int, uint)));
304     static assert(is(Stride!(-3, Types) == AliasSeq!(ulong, long)));
305 
306     static assert(is(Stride!(-2, Types) == Stride!(2, Reverse!Types)));
307 
308     static assert(is(Stride!1 == AliasSeq!()));
309     static assert(is(Stride!100 == AliasSeq!()));
310 }
311 
312 @safe unittest
313 {
314     static assert(!__traits(compiles, Stride!(0, int)));
315 
316     alias Types = AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
317                             char, wchar, dchar, float, double, real, Object);
318     alias Types2 = AliasSeq!(bool, ubyte, ushort, uint, ulong, wchar, float, real);
319     alias Types3 = AliasSeq!(bool, short, uint, char, float, Object);
320     alias Types4 = AliasSeq!(bool, ushort, ulong, float);
321     alias Types5 = AliasSeq!(bool, int, wchar, Object);
322     alias Types6 = AliasSeq!(bool, uint, float);
323     alias Types7 = AliasSeq!(bool, long, real);
324     alias Types8 = AliasSeq!(bool, ulong);
325     alias Types9 = AliasSeq!(bool, char);
326     alias Types10 = AliasSeq!(bool, wchar);
327 
328     static assert(is(Stride!(1, Types) == Types));
329     static assert(is(Stride!(2, Types) == Types2));
330     static assert(is(Stride!(3, Types) == Types3));
331     static assert(is(Stride!(4, Types) == Types4));
332     static assert(is(Stride!(5, Types) == Types5));
333     static assert(is(Stride!(6, Types) == Types6));
334     static assert(is(Stride!(7, Types) == Types7));
335     static assert(is(Stride!(8, Types) == Types8));
336     static assert(is(Stride!(9, Types) == Types9));
337     static assert(is(Stride!(10, Types) == Types10));
338 
339     static assert(is(Stride!(-1, Types) == Reverse!Types));
340     static assert(is(Stride!(-2, Types) == Stride!(2, Reverse!Types)));
341     static assert(is(Stride!(-3, Types) == Stride!(3, Reverse!Types)));
342     static assert(is(Stride!(-4, Types) == Stride!(4, Reverse!Types)));
343     static assert(is(Stride!(-5, Types) == Stride!(5, Reverse!Types)));
344     static assert(is(Stride!(-6, Types) == Stride!(6, Reverse!Types)));
345     static assert(is(Stride!(-7, Types) == Stride!(7, Reverse!Types)));
346     static assert(is(Stride!(-8, Types) == Stride!(8, Reverse!Types)));
347     static assert(is(Stride!(-9, Types) == Stride!(9, Reverse!Types)));
348     static assert(is(Stride!(-10, Types) == Stride!(10, Reverse!Types)));
349 }
350 
351 /++
352     Evaluates to an $(LREF AliasSeq) which contains no duplicate elements.
353 
354     Unique takes a binary template predicate that it uses to compare elements
355     for equality. If the predicate is $(D true) when an element in the given
356     $(LREF AliasSeq) is compared with an element with a lower index, then that
357     element is not included in the result (so if any elements in the
358     $(LREF AliasSeq) are considered equal per the predicate, then only the
359     first one is included in the result).
360 
361     Note that the binary predicate must be partially instantiable, e.g.
362     ---
363     alias PartialCmp = Cmp!(Args[0]);
364     enum same = PartialCmp!(Args[1]);
365     ---
366     Otherwise, it won't work.
367 
368     See_Also:
369         $(REF isSameSymbol, phobos, sys, traits)
370         $(REF isSameType, phobos, sys, traits)
371   +/
372 template Unique(alias Cmp, Args...)
373 {
374     alias Unique = AliasSeq!();
375     static foreach (i, Arg; Args)
376     {
377         static if (i == 0)
378             Unique = AliasSeq!Arg;
379         else
380             Unique = AppendIfUnique!(Cmp, Unique, Arg);
381     }
382 }
383 
384 // Unfortunately, this can't be done in-place in Unique, because then we get
385 // errors about reassigning Unique after reading it.
386 private template AppendIfUnique(alias Cmp, Args...)
387 {
388     static if (indexOf!(Cmp!(Args[$ - 1]), Args[0 .. $ - 1]) == -1)
389         alias AppendIfUnique = Args;
390     else
391         alias AppendIfUnique = Args[0 .. $ - 1];
392 }
393 
394 ///
395 @safe unittest
396 {
397     import phobos.sys.traits : isSameType;
398 
399     alias Types1 = AliasSeq!(int, long, long, int, int, float, int);
400 
401     static assert(is(Unique!(isSameType, Types1) ==
402                      AliasSeq!(int, long, float)));
403 
404     alias Types2 = AliasSeq!(byte, ubyte, short, ushort, int, uint);
405     static assert(is(Unique!(isSameType, Types2) == Types2));
406 
407     // Empty AliasSeq.
408     static assert(Unique!isSameType.length == 0);
409 
410     // An AliasSeq with a single element works as well.
411     static assert(Unique!(isSameType, int).length == 1);
412 }
413 
414 ///
415 @safe unittest
416 {
417     import phobos.sys.traits : isSameSymbol;
418 
419     int i;
420     string s;
421     real r;
422     alias Symbols = AliasSeq!(i, s, i, i, s, r, r, i);
423 
424     alias Result = Unique!(isSameSymbol, Symbols);
425     static assert(Result.length == 3);
426     static assert(__traits(isSame, Result[0], i));
427     static assert(__traits(isSame, Result[1], s));
428     static assert(__traits(isSame, Result[2], r));
429 
430     // Comparing AliasSeqs for equality with is expressions only works
431     // if they only contain types.
432     static assert(!is(Symbols == Result));
433 }
434 
435 ///
436 @safe unittest
437 {
438     alias Types = AliasSeq!(int, uint, long, string, short, int*, ushort);
439 
440     template sameSize(T)
441     {
442         enum sameSize(U) = T.sizeof == U.sizeof;
443     }
444     static assert(is(Unique!(sameSize, Types) ==
445                      AliasSeq!(int, long, string, short)));
446 
447     // The predicate must be partially instantiable.
448     enum sameSize_fails(T, U) = T.sizeof == U.sizeof;
449     static assert(!__traits(compiles, Unique!(sameSize_fails, Types)));
450 }
451 
452 /++
453     Map takes a template and applies it to every element in the given
454     $(D AliasSeq), resulting in an $(D AliasSeq) with the transformed elements.
455 
456     So, it's equivalent to
457     `AliasSeq!(Fun!(Args[0]), Fun!(Args[1]), ..., Fun!(Args[$ - 1]))`.
458  +/
459 template Map(alias Fun, Args...)
460 {
461     alias Map = AliasSeq!();
462     static foreach (Arg; Args)
463         Map = AliasSeq!(Map, Fun!Arg);
464 }
465 
466 ///
467 @safe unittest
468 {
469     import phobos.sys.traits : Unqualified;
470 
471     // empty
472     alias Empty = Map!Unqualified;
473     static assert(Empty.length == 0);
474 
475     // single
476     alias Single = Map!(Unqualified, const int);
477     static assert(is(Single == AliasSeq!int));
478 
479     // several
480     alias Several = Map!(Unqualified, int, const int, immutable int, uint,
481                          ubyte, byte, short, ushort, const long);
482     static assert(is(Several == AliasSeq!(int, int, int, uint,
483                                           ubyte, byte, short, ushort, long)));
484 
485     alias ToDynamicArray(T) = T[];
486 
487     alias Arrays = Map!(ToDynamicArray, int, const ubyte, string);
488     static assert(is(Arrays == AliasSeq!(int[], const(ubyte)[], string[])));
489 }
490 
491 // @@@ BUG @@@ The test below exposes failure of the straightforward use.
492 // See @adamdruppe's comment to https://github.com/dlang/phobos/pull/8039
493 @safe unittest
494 {
495     template id(alias what)
496     {
497         enum id = __traits(identifier, what);
498     }
499 
500     enum A { a }
501     static assert(Map!(id, A.a) == AliasSeq!"a");
502 }
503 
504 // regression test for https://issues.dlang.org/show_bug.cgi?id=21088
505 @system unittest // typeid opEquals is @system
506 {
507     enum getTypeId(T) = typeid(T);
508     alias A = Map!(getTypeId, int);
509 
510     assert(A == typeid(int));
511 }
512 
513 /++
514     Takes an $(D AliasSeq) and result in an $(D AliasSeq) where the order of
515     the elements has been reversed.
516   +/
517 template Reverse(Args...)
518 {
519     alias Reverse = AliasSeq!();
520     static foreach_reverse (Arg; Args)
521         Reverse = AliasSeq!(Reverse, Arg);
522 }
523 
524 ///
525 @safe unittest
526 {
527     static assert(is(Reverse!(int, byte, long, string) ==
528                      AliasSeq!(string, long, byte, int)));
529 
530     alias Types = AliasSeq!(int, long, long, int, float,
531                             ubyte, short, ushort, uint);
532     static assert(is(Reverse!Types == AliasSeq!(uint, ushort, short, ubyte,
533                                                 float, int, long, long, int)));
534 
535     static assert(is(Reverse!() == AliasSeq!()));
536 }
537 
538 /++
539     Whether the given template predicate is $(D true) for all of the elements in
540     the given $(D AliasSeq).
541 
542     Evaluation is $(I not) short-circuited if a $(D false) result is
543     encountered; the template predicate must be instantiable with all the
544     elements.
545   +/
546 version (StdDdoc) template all(alias Pred, Args...)
547 {
548     import core.internal.traits : allSatisfy;
549     alias all = allSatisfy!(Pred, Args);
550 }
551 else
552 {
553     import core.internal.traits : allSatisfy;
554     alias all = allSatisfy;
555 }
556 
557 ///
558 @safe unittest
559 {
560     import phobos.sys.traits : isDynamicArray, isInteger;
561 
562     static assert(!all!(isInteger, int, double));
563     static assert( all!(isInteger, int, long));
564 
565     alias Types = AliasSeq!(string, int[], bool[]);
566 
567     static assert( all!(isDynamicArray, Types));
568     static assert(!all!(isInteger, Types));
569 
570     static assert( all!isInteger);
571 }
572 
573 /++
574     Whether the given template predicate is $(D true) for any of the elements in
575     the given $(D AliasSeq).
576 
577     Evaluation is $(I not) short-circuited if a $(D true) result is
578     encountered; the template predicate must be instantiable with all the
579     elements.
580   +/
581 version (StdDdoc) template any(alias Pred, Args...)
582 {
583     import core.internal.traits : anySatisfy;
584     alias any = anySatisfy!(Pred, Args);
585 }
586 else
587 {
588     import core.internal.traits : anySatisfy;
589     alias any = anySatisfy;
590 }
591 
592 ///
593 @safe unittest
594 {
595     import phobos.sys.traits : isDynamicArray, isInteger;
596 
597     static assert(!any!(isInteger, string, double));
598     static assert( any!(isInteger, int, double));
599 
600     alias Types = AliasSeq!(string, int[], bool[], real, bool);
601 
602     static assert( any!(isDynamicArray, Types));
603     static assert(!any!(isInteger, Types));
604 
605     static assert(!any!isInteger);
606 }
607 
608 /++
609     Evaluates to the index of the first element where $(D Pred!(Args[i])) is
610     $(D true).
611 
612     If $(D Pred!(Args[i])) is not $(D true) for any elements, then the result
613     is $(D -1).
614 
615     Evaluation is $(I not) short-circuited if a $(D true) result is
616     encountered; the template predicate must be instantiable with all the
617     elements.
618   +/
619 template indexOf(alias Pred, Args...)
620 {
621     enum ptrdiff_t indexOf =
622     {
623         static foreach (i; 0 .. Args.length)
624         {
625             static if (Pred!(Args[i]))
626                 return i;
627         }
628         return -1;
629     }();
630 }
631 
632 ///
633 @safe unittest
634 {
635     import phobos.sys.traits : isInteger, isSameSymbol, isSameType;
636 
637     alias Types1 = AliasSeq!(string, int, long, char[], ubyte, int);
638     alias Types2 = AliasSeq!(float, double, int[], char[], void);
639 
640     static assert(indexOf!(isInteger, Types1) == 1);
641     static assert(indexOf!(isInteger, Types2) == -1);
642 
643     static assert(indexOf!(isSameType!ubyte, Types1) == 4);
644     static assert(indexOf!(isSameType!ubyte, Types2) == -1);
645 
646     int i;
647     int j;
648     string s;
649     int foo() { return 0; }
650     alias Symbols = AliasSeq!(i, j, foo);
651     static assert(indexOf!(isSameSymbol!j, Symbols) == 1);
652     static assert(indexOf!(isSameSymbol!s, Symbols) == -1);
653 
654     // Empty AliasSeq.
655     static assert(indexOf!isInteger == -1);
656 
657     // The predicate does not compile with all of the arguments,
658     // so indexOf does not compile.
659     static assert(!__traits(compiles, indexOf!(isSameType!int, long, int, 42)));
660 }
661 
662 unittest
663 {
664     import phobos.sys.traits : isSameType;
665 
666     static assert(indexOf!(isSameType!int, short, int, long) >= 0);
667     static assert(indexOf!(isSameType!string, short, int, long) < 0);
668 
669     // This is to verify that we don't accidentally end up with the type of
670     // the result differing based on whether it's -1 or not. Not specifying the
671     // type at all in indexOf results in -1 being int on all systems and the
672     // other results being whatever size_t is (ulong on most systems at this
673     // point), which does generally work, but being explicit with the type
674     // avoids any subtle issues that might come from the type of the result
675     // varying based on whether the item is found or not.
676     static assert(is(typeof(indexOf!(isSameType!int, short, int, long)) ==
677                      typeof(indexOf!(isSameType!string, short, int, long))));
678 
679     static assert(indexOf!(isSameType!string, string, string, string, string) == 0);
680     static assert(indexOf!(isSameType!string,    int, string, string, string) == 1);
681     static assert(indexOf!(isSameType!string,    int,    int, string, string) == 2);
682     static assert(indexOf!(isSameType!string,    int,    int,    int, string) == 3);
683     static assert(indexOf!(isSameType!string,    int,    int,    int,    int) == -1);
684 }
685 
686 /++
687     Combines multiple template predicates into a single template predicate using
688     logical AND - i.e. for the resulting predicate to be $(D true) with a
689     particular argument, all of the predicates must be $(D true) with that
690     argument.
691 
692     Evaluation is $(I not) short-circuited if a $(D false) result is
693     encountered; the template predicate must be instantiable with all the
694     elements.
695 
696     See_Also:
697         $(LREF Not)
698         $(LREF Or)
699   +/
700 template And(Preds...)
701 {
702     enum And(Args...) =
703     {
704         static foreach (Pred; Preds)
705         {
706             static if (!Pred!Args)
707                 return false;
708         }
709         return true;
710     }();
711 }
712 
713 ///
714 @safe unittest
715 {
716     import phobos.sys.traits : isNumeric;
717 
718     template isSameSize(size_t size)
719     {
720         enum isSameSize(T) = T.sizeof == size;
721     }
722 
723     alias is32BitNumeric = And!(isNumeric, isSameSize!4);
724 
725     static assert(!is32BitNumeric!short);
726     static assert( is32BitNumeric!int);
727     static assert(!is32BitNumeric!long);
728     static assert( is32BitNumeric!float);
729     static assert(!is32BitNumeric!double);
730     static assert(!is32BitNumeric!(int*));
731 
732     // An empty sequence of predicates always yields true.
733     alias alwaysTrue = And!();
734     static assert(alwaysTrue!int);
735 }
736 
737 /++
738     Predicates with multiple parameters are also supported. However, the number
739     of parameters must match.
740   +/
741 @safe unittest
742 {
743     import phobos.sys.traits : isImplicitlyConvertible, isInteger, isSameType;
744 
745     alias isOnlyImplicitlyConvertible
746         = And!(Not!isSameType, isImplicitlyConvertible);
747 
748     static assert( isOnlyImplicitlyConvertible!(int, long));
749     static assert(!isOnlyImplicitlyConvertible!(int, int));
750     static assert(!isOnlyImplicitlyConvertible!(long, int));
751 
752     static assert( isOnlyImplicitlyConvertible!(string, const(char)[]));
753     static assert(!isOnlyImplicitlyConvertible!(string, string));
754     static assert(!isOnlyImplicitlyConvertible!(const(char)[], string));
755 
756     // Mismatched numbers of parameters.
757     alias doesNotWork = And!(isInteger, isImplicitlyConvertible);
758     static assert(!__traits(compiles, doesNotWork!int));
759     static assert(!__traits(compiles, doesNotWork!(int, long)));
760 }
761 
762 @safe unittest
763 {
764     enum testAlways(Args...) = true;
765     enum testNever(Args...) = false;
766 
767     static assert( Instantiate!(And!(testAlways, testAlways, testAlways), int));
768     static assert(!Instantiate!(And!(testAlways, testAlways, testNever), int));
769     static assert(!Instantiate!(And!(testAlways, testNever, testNever), int));
770     static assert(!Instantiate!(And!(testNever, testNever, testNever), int));
771     static assert(!Instantiate!(And!(testNever, testNever, testAlways), int));
772     static assert(!Instantiate!(And!(testNever, testAlways, testAlways), int));
773 
774     static assert( Instantiate!(And!(testAlways, testAlways), int));
775     static assert(!Instantiate!(And!(testAlways, testNever), int));
776     static assert(!Instantiate!(And!(testNever, testAlways), int));
777     static assert(!Instantiate!(And!(testNever, testNever), int));
778 
779     static assert( Instantiate!(And!testAlways, int));
780     static assert(!Instantiate!(And!testNever, int));
781 
782     // No short-circuiting.
783     import phobos.sys.traits : isEqual, isFloatingPoint;
784     static assert(!Instantiate!(And!isFloatingPoint, int));
785     static assert(!__traits(compiles, Instantiate!(And!(isFloatingPoint, isEqual), int)));
786 }
787 
788 /++
789     Evaluates to a template predicate which negates the given predicate.
790 
791     See_Also:
792         $(LREF And)
793         $(LREF Or)
794   +/
795 template Not(alias Pred)
796 {
797     enum Not(Args...) = !Pred!Args;
798 }
799 
800 ///
801 @safe unittest
802 {
803     import phobos.sys.traits : isDynamicArray, isPointer;
804 
805     alias isNotPointer = Not!isPointer;
806     static assert( isNotPointer!int);
807     static assert(!isNotPointer!(int*));
808     static assert( all!(isNotPointer, string, char, float));
809 
810     static assert(!all!(Not!isDynamicArray, string, char[], int[], long));
811     static assert( any!(Not!isDynamicArray, string, char[], int[], long));
812 }
813 
814 /++
815     Predicates with multiple parameters are also supported.
816   +/
817 @safe unittest
818 {
819     import phobos.sys.traits : isImplicitlyConvertible, isInteger;
820 
821     alias notImplicitlyConvertible = Not!isImplicitlyConvertible;
822 
823     static assert( notImplicitlyConvertible!(long, int));
824     static assert(!notImplicitlyConvertible!(int, long));
825 
826     static assert( notImplicitlyConvertible!(const(char)[], string));
827     static assert(!notImplicitlyConvertible!(string, const(char)[]));
828 }
829 
830 /++
831     Combines multiple template predicates into a single template predicate using
832     logical OR - i.e. for the resulting predicate to be $(D true) with a
833     particular argument, at least one of the predicates must be $(D true) with
834     that argument.
835 
836     Evaluation is $(I not) short-circuited if a $(D true) result is
837     encountered; the template predicate must be instantiable with all the
838     elements.
839 
840     See_Also:
841         $(LREF And)
842         $(LREF Not)
843   +/
844 template Or(Preds...)
845 {
846     enum Or(Args...) =
847     {
848         static foreach (Pred; Preds)
849         {
850             static if (Pred!Args)
851                 return true;
852         }
853         return false;
854     }();
855 }
856 
857 ///
858 @safe unittest
859 {
860     import phobos.sys.traits : isFloatingPoint, isSignedInteger;
861 
862     alias isSignedNumeric = Or!(isFloatingPoint, isSignedInteger);
863 
864     static assert( isSignedNumeric!short);
865     static assert( isSignedNumeric!long);
866     static assert( isSignedNumeric!double);
867     static assert(!isSignedNumeric!uint);
868     static assert(!isSignedNumeric!ulong);
869     static assert(!isSignedNumeric!string);
870     static assert(!isSignedNumeric!(int*));
871 
872     // An empty sequence of predicates always yields false.
873     alias alwaysFalse = Or!();
874     static assert(!alwaysFalse!int);
875 }
876 
877 /++
878     Predicates with multiple parameters are also supported. However, the number
879     of parameters must match.
880   +/
881 @safe unittest
882 {
883     import phobos.sys.traits : isImplicitlyConvertible, isInteger;
884 
885     enum isSameSize(T, U) = T.sizeof == U.sizeof;
886     alias convertibleOrSameSize = Or!(isImplicitlyConvertible, isSameSize);
887 
888     static assert( convertibleOrSameSize!(int, int));
889     static assert( convertibleOrSameSize!(int, long));
890     static assert(!convertibleOrSameSize!(long, int));
891 
892     static assert( convertibleOrSameSize!(int, float));
893     static assert( convertibleOrSameSize!(float, int));
894     static assert(!convertibleOrSameSize!(double, int));
895     static assert(!convertibleOrSameSize!(float, long));
896 
897     static assert( convertibleOrSameSize!(int*, string*));
898 
899     // Mismatched numbers of parameters.
900     alias doesNotWork = Or!(isInteger, isImplicitlyConvertible);
901     static assert(!__traits(compiles, doesNotWork!int));
902     static assert(!__traits(compiles, doesNotWork!(int, long)));
903 }
904 
905 @safe unittest
906 {
907     enum testAlways(Args...) = true;
908     enum testNever(Args...) = false;
909 
910     static assert( Instantiate!(Or!(testAlways, testAlways, testAlways), int));
911     static assert( Instantiate!(Or!(testAlways, testAlways, testNever), int));
912     static assert( Instantiate!(Or!(testAlways, testNever, testNever), int));
913     static assert(!Instantiate!(Or!(testNever, testNever, testNever), int));
914 
915     static assert( Instantiate!(Or!(testAlways, testAlways), int));
916     static assert( Instantiate!(Or!(testAlways, testNever), int));
917     static assert( Instantiate!(Or!(testNever, testAlways), int));
918     static assert(!Instantiate!(Or!(testNever, testNever), int));
919 
920     static assert( Instantiate!(Or!testAlways, int));
921     static assert(!Instantiate!(Or!testNever, int));
922 
923     static assert(Instantiate!(Or!testAlways, int));
924     static assert(Instantiate!(Or!testAlways, Map));
925     static assert(Instantiate!(Or!testAlways, int, Map));
926 
927     // No short-circuiting.
928     import phobos.sys.traits : isEqual, isInteger;
929     static assert( Instantiate!(Or!isInteger, int));
930     static assert(!__traits(compiles, Instantiate!(Or!(isInteger, isEqual), int)));
931 }
932 
933 /++
934     Instantiates the given template with the given arguments and evaluates to
935     the result of that template.
936 
937     This is used to work around some syntactic limitations that D has with
938     regards to instantiating templates. Essentially, D requires a name for a
939     template when instantiating it (be it the name of the template itself or an
940     alias to the template), which causes problems when you don't have that.
941 
942     Specifically, if the template is within an $(LREF AliasSeq) - e.g.
943     $(D Templates[0]!Args) - or it's the result of another template - e.g
944     $(D Foo!Bar!Baz) - the instantiation is illegal. This leaves two ways to
945     solve the problem. The first is to create an alias, e.g.
946     ---
947     alias Template = Templates[0];
948     enum result = Template!Args;
949 
950     alias Partial = Foo!Bar;
951     alias T = Partial!Baz;
952     ---
953     The second is to use Instantiate, e.g.
954     ---
955     enum result = Instantiate!(Templates[0], Args);
956 
957     alias T = Instiantiate!(Foo!Bar, Baz);
958     ---
959 
960     Of course, the downside to this is that it adds an additional template
961     instantiation, but it avoids creating an alias just to be able to
962     instantiate a template. So, whether it makes sense to use Instantiate
963     instead of an alias naturally depends on the situation, but without it,
964     we'd be forced to create aliases even in situations where that's
965     problematic.
966 
967     See_Also:
968         $(LREF ApplyLeft)
969         $(LREF ApplyRight)
970   +/
971 alias Instantiate(alias Template, Args...) = Template!Args;
972 
973 ///
974 @safe unittest
975 {
976     import phobos.sys.traits : ConstOf, isImplicitlyConvertible, isSameType, isInteger;
977 
978     alias Templates = AliasSeq!(isImplicitlyConvertible!int,
979                                 isSameType!string,
980                                 isInteger,
981                                 ConstOf);
982 
983     // Templates[0]!long does not compile, because the compiler can't parse it.
984 
985     static assert( Instantiate!(Templates[0], long));
986     static assert(!Instantiate!(Templates[0], string));
987 
988     static assert(!Instantiate!(Templates[1], long));
989     static assert( Instantiate!(Templates[1], string));
990 
991     static assert( Instantiate!(Templates[2], long));
992     static assert(!Instantiate!(Templates[2], string));
993 
994     static assert(is(Instantiate!(Templates[3], int) == const int));
995     static assert(is(Instantiate!(Templates[3], double) == const double));
996 }
997 
998 ///
999 @safe unittest
1000 {
1001     template hasMember(string member)
1002     {
1003         enum hasMember(T) = __traits(hasMember, T, member);
1004     }
1005 
1006     struct S
1007     {
1008         int foo;
1009     }
1010 
1011     // hasMember!"foo"!S does not compile,
1012     // because having multiple ! arguments is not allowed.
1013 
1014     static assert( Instantiate!(hasMember!"foo", S));
1015     static assert(!Instantiate!(hasMember!"bar", S));
1016 }
1017 
1018 /++
1019     Instantiate also allows us to do template instantations via templates that
1020     take other templates as arguments.
1021   +/
1022 @safe unittest
1023 {
1024     import phobos.sys.traits : isInteger, isNumeric, isUnsignedInteger;
1025 
1026     alias Results = Map!(ApplyRight!(Instantiate, int),
1027                          isInteger, isNumeric, isUnsignedInteger);
1028 
1029     static assert([Results] == [true, true, false]);
1030 }
1031 
1032 /++
1033     ApplyLeft does a
1034     $(LINK2 http://en.wikipedia.org/wiki/Partial_application, partial application)
1035     of its arguments, providing a way to bind a set of arguments to the given
1036     template while delaying actually instantiating that template until the full
1037     set of arguments is provided. The "Left" in the name indicates that the
1038     initial arguments are one the left-hand side of the argument list
1039     when the given template is instantiated.
1040 
1041     Essentially, ApplyLeft results in a template that stores Template and Args,
1042     and when that intermediate template is instantiated in turn, it instantiates
1043     Template with Args on the left-hand side of the arguments to Template and
1044     with the arguments to the intermediate template on the right-hand side -
1045     i.e. Args is applied to the left when instantiating Template.
1046 
1047     So, if you have
1048     ---
1049     alias Intermediate = ApplyLeft!(MyTemplate, Arg1, Arg2);
1050     alias Result = Intermediate!(ArgA, ArgB);
1051     ---
1052     then that is equivalent to
1053     ---
1054     alias Result = MyTemplate!(Arg1, Arg2, ArgA, ArgB);
1055     ---
1056     with the difference being that you have an intermediate template which can
1057     be stored or passed to other templates (e.g. as a template predicate).
1058 
1059     The only difference between ApplyLeft and $(LREF ApplyRight) is whether
1060     Args is on the left-hand or the right-hand side of the arguments given to
1061     Template when it's instantiated.
1062 
1063     Note that in many cases, the need for ApplyLeft can be eliminated by making
1064     it so that Template can be partially instantiated. E.G.
1065     ---
1066     enum isSameType(T, U) = is(T == U);
1067 
1068     template isSameType(T)
1069     {
1070         enum isSameType(U) = is(T == U);
1071     }
1072     ---
1073     makes it so that both of these work
1074     ---
1075     enum result1 = isSameType!(int, long);
1076 
1077     alias Intermediate = isSameType!int;
1078     enum result2 = Intermediate!long;
1079     ---
1080     whereas if only the two argument version is provided, then ApplyLeft would
1081     be required for the second use case.
1082     ---
1083     enum result1 = isSameType!(int, long);
1084 
1085     alias Intermediate = ApplyLeft!(isSameType, int);
1086     enum result2 = Intermediate!long;
1087     ---
1088 
1089     See_Also:
1090         $(LREF ApplyRight)
1091         $(LREF Instantiate)
1092    +/
1093 template ApplyLeft(alias Template, Args...)
1094 {
1095     alias ApplyLeft(Right...) = Template!(Args, Right);
1096 }
1097 
1098 ///
1099 @safe unittest
1100 {
1101     {
1102         alias Intermediate = ApplyLeft!(AliasSeq, ubyte, ushort, uint);
1103         alias Result = Intermediate!(char, wchar, dchar);
1104         static assert(is(Result == AliasSeq!(ubyte, ushort, uint, char, wchar, dchar)));
1105     }
1106     {
1107         enum isImplicitlyConvertible(T, U) = is(T : U);
1108 
1109         // i.e. isImplicitlyConvertible!(ubyte, T) is what all is checking for
1110         // with each element in the AliasSeq.
1111         static assert(all!(ApplyLeft!(isImplicitlyConvertible, ubyte),
1112                            short, ushort, int, uint, long, ulong));
1113     }
1114     {
1115         enum hasMember(T, string member) = __traits(hasMember, T, member);
1116 
1117         struct S
1118         {
1119             bool foo;
1120             int bar;
1121             string baz;
1122         }
1123 
1124         static assert(all!(ApplyLeft!(hasMember, S), "foo", "bar", "baz"));
1125     }
1126     {
1127         // Either set of arguments can be empty, since the first set is just
1128         // stored to be applied later, and then when the intermediate template
1129         // is instantiated, they're all applied to the given template in the
1130         // requested order. However, whether the code compiles when
1131         // instantiating the intermediate template depends on what kinds of
1132         // arguments the given template requires.
1133 
1134         alias Intermediate1 = ApplyLeft!AliasSeq;
1135         static assert(Intermediate1!().length == 0);
1136 
1137         enum isSameSize(T, U) = T.sizeof == U.sizeof;
1138 
1139         alias Intermediate2 = ApplyLeft!(isSameSize, int);
1140         static assert(Intermediate2!uint);
1141 
1142         alias Intermediate3 = ApplyLeft!(isSameSize, int, uint);
1143         static assert(Intermediate3!());
1144 
1145         alias Intermediate4 = ApplyLeft!(isSameSize);
1146         static assert(Intermediate4!(int, uint));
1147 
1148         // isSameSize requires two arguments
1149         alias Intermediate5 = ApplyLeft!isSameSize;
1150         static assert(!__traits(compiles, Intermediate5!()));
1151         static assert(!__traits(compiles, Intermediate5!int));
1152         static assert(!__traits(compiles, Intermediate5!(int, long, string)));
1153     }
1154 }
1155 
1156 /++
1157     ApplyRight does a
1158     $(LINK2 http://en.wikipedia.org/wiki/Partial_application, partial application)
1159     of its arguments, providing a way to bind a set of arguments to the given
1160     template while delaying actually instantiating that template until the full
1161     set of arguments is provided. The "Right" in the name indicates that the
1162     initial arguments are one the right-hand side of the argument list
1163     when the given template is instantiated.
1164 
1165     Essentially, ApplyRight results in a template that stores Template and
1166     Args, and when that intermediate template is instantiated in turn, it
1167     instantiates Template with the arguments to the intermediate template on
1168     the left-hand side and with Args on the right-hand side - i.e. Args is
1169     applied to the right when instantiating Template.
1170 
1171     So, if you have
1172     ---
1173     alias Intermediate = ApplyRight!(MyTemplate, Arg1, Arg2);
1174     alias Result = Intermediate!(ArgA, ArgB);
1175     ---
1176     then that is equivalent to
1177     ---
1178     alias Result = MyTemplate!(ArgA, ArgB, Arg1, Arg2);
1179     ---
1180     with the difference being that you have an intermediate template which can
1181     be stored or passed to other templates (e.g. as a template predicate).
1182 
1183     The only difference between $(LREF ApplyLeft) and ApplyRight is whether
1184     Args is on the left-hand or the right-hand side of the arguments given to
1185     Template when it's instantiated.
1186 
1187     See_Also:
1188         $(LREF ApplyLeft)
1189         $(LREF Instantiate)
1190    +/
1191 template ApplyRight(alias Template, Args...)
1192 {
1193     alias ApplyRight(Left...) = Template!(Left, Args);
1194 }
1195 
1196 ///
1197 @safe unittest
1198 {
1199     {
1200         alias Intermediate = ApplyRight!(AliasSeq, ubyte, ushort, uint);
1201         alias Result = Intermediate!(char, wchar, dchar);
1202         static assert(is(Result == AliasSeq!(char, wchar, dchar, ubyte, ushort, uint)));
1203     }
1204     {
1205         enum isImplicitlyConvertible(T, U) = is(T : U);
1206 
1207         // i.e. isImplicitlyConvertible!(T, short) is what Filter is checking
1208         // for with each element in the AliasSeq.
1209         static assert(is(Filter!(ApplyRight!(isImplicitlyConvertible, short),
1210                                  ubyte, string, short, float, int) ==
1211                          AliasSeq!(ubyte, short)));
1212     }
1213     {
1214         enum hasMember(T, string member) = __traits(hasMember, T, member);
1215 
1216         struct S1
1217         {
1218             bool foo;
1219         }
1220 
1221         struct S2
1222         {
1223             int foo() { return 42; }
1224         }
1225 
1226         static assert(all!(ApplyRight!(hasMember, "foo"), S1, S2));
1227     }
1228     {
1229         // Either set of arguments can be empty, since the first set is just
1230         // stored to be applied later, and then when the intermediate template
1231         // is instantiated, they're all applied to the given template in the
1232         // requested order. However, whether the code compiles when
1233         // instantiating the intermediate template depends on what kinds of
1234         // arguments the given template requires.
1235 
1236         alias Intermediate1 = ApplyRight!AliasSeq;
1237         static assert(Intermediate1!().length == 0);
1238 
1239         enum isSameSize(T, U) = T.sizeof == U.sizeof;
1240 
1241         alias Intermediate2 = ApplyRight!(isSameSize, int);
1242         static assert(Intermediate2!uint);
1243 
1244         alias Intermediate3 = ApplyRight!(isSameSize, int, uint);
1245         static assert(Intermediate3!());
1246 
1247         alias Intermediate4 = ApplyRight!(isSameSize);
1248         static assert(Intermediate4!(int, uint));
1249 
1250         // isSameSize requires two arguments
1251         alias Intermediate5 = ApplyRight!isSameSize;
1252         static assert(!__traits(compiles, Intermediate5!()));
1253         static assert(!__traits(compiles, Intermediate5!int));
1254     }
1255 }