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