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 }