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 T in the 253 * sequence TList. 254 * If not found, -1 is returned. 255 */ 256 template staticIndexOf(T, TList...) 257 { 258 enum staticIndexOf = genericIndexOf!(T, TList); 259 } 260 261 /// Ditto 262 template staticIndexOf(alias T, TList...) 263 { 264 enum staticIndexOf = genericIndexOf!(T, TList); 265 } 266 267 /// 268 @safe unittest 269 { 270 import std.stdio; 271 272 void foo() 273 { 274 writefln("The index of long is %s", 275 staticIndexOf!(long, AliasSeq!(int, long, double))); 276 // prints: The index of long is 1 277 } 278 } 279 280 // [internal] 281 private template genericIndexOf(args...) 282 if (args.length >= 1) 283 { 284 static foreach (idx, arg; args[1 .. $]) 285 { 286 static if (is(typeof(genericIndexOf) == void) && // not yet defined 287 isSame!(args[0], arg)) 288 { 289 enum genericIndexOf = idx; 290 } 291 } 292 static if (is(typeof(genericIndexOf) == void)) // no hit 293 { 294 enum genericIndexOf = -1; 295 } 296 } 297 298 @safe unittest 299 { 300 static assert(staticIndexOf!( byte, byte, short, int, long) == 0); 301 static assert(staticIndexOf!(short, byte, short, int, long) == 1); 302 static assert(staticIndexOf!( int, byte, short, int, long) == 2); 303 static assert(staticIndexOf!( long, byte, short, int, long) == 3); 304 static assert(staticIndexOf!( char, byte, short, int, long) == -1); 305 static assert(staticIndexOf!( -1, byte, short, int, long) == -1); 306 static assert(staticIndexOf!(void) == -1); 307 308 static assert(staticIndexOf!("abc", "abc", "def", "ghi", "jkl") == 0); 309 static assert(staticIndexOf!("def", "abc", "def", "ghi", "jkl") == 1); 310 static assert(staticIndexOf!("ghi", "abc", "def", "ghi", "jkl") == 2); 311 static assert(staticIndexOf!("jkl", "abc", "def", "ghi", "jkl") == 3); 312 static assert(staticIndexOf!("mno", "abc", "def", "ghi", "jkl") == -1); 313 static assert(staticIndexOf!( void, "abc", "def", "ghi", "jkl") == -1); 314 static assert(staticIndexOf!(42) == -1); 315 316 static assert(staticIndexOf!(void, 0, "void", void) == 2); 317 static assert(staticIndexOf!("void", 0, void, "void") == 2); 318 } 319 320 /** 321 * Returns an `AliasSeq` created from TList with the first occurrence, 322 * if any, of T removed. 323 */ 324 template Erase(T, TList...) 325 { 326 alias Erase = GenericErase!(T, TList).result; 327 } 328 329 /// Ditto 330 template Erase(alias T, TList...) 331 { 332 alias Erase = GenericErase!(T, TList).result; 333 } 334 335 /// 336 @safe unittest 337 { 338 alias Types = AliasSeq!(int, long, double, char); 339 alias TL = Erase!(long, Types); 340 static assert(is(TL == AliasSeq!(int, double, char))); 341 } 342 343 // [internal] 344 private template GenericErase(args...) 345 if (args.length >= 1) 346 { 347 alias e = OldAlias!(args[0]); 348 alias tuple = args[1 .. $] ; 349 350 static if (tuple.length) 351 { 352 alias head = OldAlias!(tuple[0]); 353 alias tail = tuple[1 .. $]; 354 355 static if (isSame!(e, head)) 356 alias result = tail; 357 else 358 alias result = AliasSeq!(head, GenericErase!(e, tail).result); 359 } 360 else 361 { 362 alias result = AliasSeq!(); 363 } 364 } 365 366 @safe unittest 367 { 368 static assert(Pack!(Erase!(int, 369 short, int, int, 4)). 370 equals!(short, int, 4)); 371 372 static assert(Pack!(Erase!(1, 373 real, 3, 1, 4, 1, 5, 9)). 374 equals!(real, 3, 4, 1, 5, 9)); 375 } 376 377 378 /** 379 * Returns an `AliasSeq` created from TList with the all occurrences, 380 * if any, of T removed. 381 */ 382 template EraseAll(T, TList...) 383 { 384 alias EraseAll = GenericEraseAll!(T, TList).result; 385 } 386 387 /// Ditto 388 template EraseAll(alias T, TList...) 389 { 390 alias EraseAll = GenericEraseAll!(T, TList).result; 391 } 392 393 /// 394 @safe unittest 395 { 396 alias Types = AliasSeq!(int, long, long, int); 397 398 alias TL = EraseAll!(long, Types); 399 static assert(is(TL == AliasSeq!(int, int))); 400 } 401 402 // [internal] 403 private template GenericEraseAll(args...) 404 if (args.length >= 1) 405 { 406 alias e = OldAlias!(args[0]); 407 alias tuple = args[1 .. $]; 408 409 static if (tuple.length) 410 { 411 alias head = OldAlias!(tuple[0]); 412 alias tail = tuple[1 .. $]; 413 alias next = AliasSeq!( 414 GenericEraseAll!(e, tail[0..$/2]).result, 415 GenericEraseAll!(e, tail[$/2..$]).result 416 ); 417 418 static if (isSame!(e, head)) 419 alias result = next; 420 else 421 alias result = AliasSeq!(head, next); 422 } 423 else 424 { 425 alias result = AliasSeq!(); 426 } 427 } 428 429 @safe unittest 430 { 431 static assert(Pack!(EraseAll!(int, 432 short, int, int, 4)). 433 equals!(short, 4)); 434 435 static assert(Pack!(EraseAll!(1, 436 real, 3, 1, 4, 1, 5, 9)). 437 equals!(real, 3, 4, 5, 9)); 438 } 439 440 /* 441 * Erase any occurrence of the first `TList[0 .. N]` elements from `TList[N .. $]`. 442 * 443 * Params: 444 * N = number of elements to delete from the `TList` 445 * TList = sequence of aliases 446 * 447 * See_Also: $(LREF EraseAll) 448 */ 449 private template EraseAllN(uint N, TList...) 450 { 451 static if (N == 1) 452 { 453 alias EraseAllN = EraseAll!(TList[0], TList[1 .. $]); 454 } 455 else 456 { 457 static if (N & 1) 458 alias EraseAllN = EraseAllN!(N / 2, TList[N / 2 + 1 .. N], 459 EraseAllN!(N / 2 + 1, TList[0 .. N / 2 + 1], TList[N .. $])); 460 else 461 alias EraseAllN = EraseAllN!(N / 2, TList[N / 2 .. N], 462 EraseAllN!(N / 2, TList[0 .. N / 2], TList[N .. $])); 463 } 464 } 465 466 /** 467 * Returns an `AliasSeq` created from TList with the all duplicate 468 * types removed. 469 */ 470 template NoDuplicates(TList...) 471 { 472 static if (TList.length >= 2) 473 { 474 alias fst = NoDuplicates!(TList[0 .. $/2]); 475 alias snd = NoDuplicates!(TList[$/2 .. $]); 476 alias NoDuplicates = AliasSeq!(fst, EraseAllN!(fst.length, fst, snd)); 477 } 478 else 479 { 480 alias NoDuplicates = TList; 481 } 482 } 483 484 /// 485 @safe unittest 486 { 487 alias Types = AliasSeq!(int, long, long, int, float); 488 489 alias TL = NoDuplicates!(Types); 490 static assert(is(TL == AliasSeq!(int, long, float))); 491 } 492 493 @safe unittest 494 { 495 import std.range : iota; 496 497 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums 498 alias LongList = Repeat!(1500, int); 499 static assert(NoDuplicates!LongList.length == 1); 500 // https://issues.dlang.org/show_bug.cgi?id=17995: huge enums, revisited 501 502 alias a = NoDuplicates!(AliasSeq!(1, Repeat!(1000, 3))); 503 alias b = NoDuplicates!(AliasSeq!(1, Repeat!(10, 3))); 504 static assert(a.length == b.length); 505 506 static assert(NoDuplicates!(aliasSeqOf!(iota(7)), aliasSeqOf!(iota(7))) == aliasSeqOf!(iota(7))); 507 static assert(NoDuplicates!(aliasSeqOf!(iota(8)), aliasSeqOf!(iota(8))) == aliasSeqOf!(iota(8))); 508 } 509 510 @safe unittest 511 { 512 static assert( 513 Pack!( 514 NoDuplicates!(1, int, 1, NoDuplicates, int, NoDuplicates, real)) 515 .equals!(1, int, NoDuplicates, real)); 516 } 517 518 519 /** 520 * Returns an `AliasSeq` created from TList with the first occurrence 521 * of T, if found, replaced with U. 522 */ 523 template Replace(T, U, TList...) 524 { 525 alias Replace = GenericReplace!(T, U, TList).result; 526 } 527 528 /// Ditto 529 template Replace(alias T, U, TList...) 530 { 531 alias Replace = GenericReplace!(T, U, TList).result; 532 } 533 534 /// Ditto 535 template Replace(T, alias U, TList...) 536 { 537 alias Replace = GenericReplace!(T, U, TList).result; 538 } 539 540 /// Ditto 541 template Replace(alias T, alias U, TList...) 542 { 543 alias Replace = GenericReplace!(T, U, TList).result; 544 } 545 546 /// 547 @safe unittest 548 { 549 alias Types = AliasSeq!(int, long, long, int, float); 550 551 alias TL = Replace!(long, char, Types); 552 static assert(is(TL == AliasSeq!(int, char, long, int, float))); 553 } 554 555 // [internal] 556 private template GenericReplace(args...) 557 if (args.length >= 2) 558 { 559 alias from = OldAlias!(args[0]); 560 alias to = OldAlias!(args[1]); 561 alias tuple = args[2 .. $]; 562 563 static if (tuple.length) 564 { 565 alias head = OldAlias!(tuple[0]); 566 alias tail = tuple[1 .. $]; 567 568 static if (isSame!(from, head)) 569 alias result = AliasSeq!(to, tail); 570 else 571 alias result = AliasSeq!(head, 572 GenericReplace!(from, to, tail).result); 573 } 574 else 575 { 576 alias result = AliasSeq!(); 577 } 578 } 579 580 @safe unittest 581 { 582 static assert(Pack!(Replace!(byte, ubyte, 583 short, byte, byte, byte)). 584 equals!(short, ubyte, byte, byte)); 585 586 static assert(Pack!(Replace!(1111, byte, 587 2222, 1111, 1111, 1111)). 588 equals!(2222, byte, 1111, 1111)); 589 590 static assert(Pack!(Replace!(byte, 1111, 591 short, byte, byte, byte)). 592 equals!(short, 1111, byte, byte)); 593 594 static assert(Pack!(Replace!(1111, "11", 595 2222, 1111, 1111, 1111)). 596 equals!(2222, "11", 1111, 1111)); 597 } 598 599 /** 600 * Returns an `AliasSeq` created from TList with all occurrences 601 * of T, if found, replaced with U. 602 */ 603 template ReplaceAll(T, U, TList...) 604 { 605 alias ReplaceAll = GenericReplaceAll!(T, U, TList).result; 606 } 607 608 /// Ditto 609 template ReplaceAll(alias T, U, TList...) 610 { 611 alias ReplaceAll = GenericReplaceAll!(T, U, TList).result; 612 } 613 614 /// Ditto 615 template ReplaceAll(T, alias U, TList...) 616 { 617 alias ReplaceAll = GenericReplaceAll!(T, U, TList).result; 618 } 619 620 /// Ditto 621 template ReplaceAll(alias T, alias U, TList...) 622 { 623 alias ReplaceAll = GenericReplaceAll!(T, U, TList).result; 624 } 625 626 /// 627 @safe unittest 628 { 629 alias Types = AliasSeq!(int, long, long, int, float); 630 631 alias TL = ReplaceAll!(long, char, Types); 632 static assert(is(TL == AliasSeq!(int, char, char, int, float))); 633 } 634 635 // [internal] 636 private template GenericReplaceAll(args...) 637 if (args.length >= 2) 638 { 639 alias from = OldAlias!(args[0]); 640 alias to = OldAlias!(args[1]); 641 alias tuple = args[2 .. $]; 642 643 static if (tuple.length) 644 { 645 alias head = OldAlias!(tuple[0]); 646 alias tail = tuple[1 .. $]; 647 alias next = GenericReplaceAll!(from, to, tail).result; 648 649 static if (isSame!(from, head)) 650 alias result = AliasSeq!(to, next); 651 else 652 alias result = AliasSeq!(head, next); 653 } 654 else 655 { 656 alias result = AliasSeq!(); 657 } 658 } 659 660 @safe unittest 661 { 662 static assert(Pack!(ReplaceAll!(byte, ubyte, 663 byte, short, byte, byte)). 664 equals!(ubyte, short, ubyte, ubyte)); 665 666 static assert(Pack!(ReplaceAll!(1111, byte, 667 1111, 2222, 1111, 1111)). 668 equals!(byte, 2222, byte, byte)); 669 670 static assert(Pack!(ReplaceAll!(byte, 1111, 671 byte, short, byte, byte)). 672 equals!(1111, short, 1111, 1111)); 673 674 static assert(Pack!(ReplaceAll!(1111, "11", 675 1111, 2222, 1111, 1111)). 676 equals!("11", 2222, "11", "11")); 677 } 678 679 /** 680 * Returns an `AliasSeq` created from TList with the order reversed. 681 */ 682 template Reverse(TList...) 683 { 684 static if (TList.length <= 1) 685 { 686 alias Reverse = TList; 687 } 688 /* Cases 2 to 8 are to speed up compile times 689 */ 690 else static if (TList.length == 2) 691 { 692 alias Reverse = AliasSeq!(TList[1], TList[0]); 693 } 694 else static if (TList.length == 3) 695 { 696 alias Reverse = AliasSeq!(TList[2], TList[1], TList[0]); 697 } 698 else static if (TList.length == 4) 699 { 700 alias Reverse = AliasSeq!(TList[3], TList[2], TList[1], TList[0]); 701 } 702 else static if (TList.length == 5) 703 { 704 alias Reverse = AliasSeq!(TList[4], TList[3], TList[2], TList[1], TList[0]); 705 } 706 else static if (TList.length == 6) 707 { 708 alias Reverse = AliasSeq!(TList[5], TList[4], TList[3], TList[2], TList[1], TList[0]); 709 } 710 else static if (TList.length == 7) 711 { 712 alias Reverse = AliasSeq!(TList[6], TList[5], TList[4], TList[3], TList[2], TList[1], TList[0]); 713 } 714 else static if (TList.length == 8) 715 { 716 alias Reverse = AliasSeq!(TList[7], TList[6], TList[5], TList[4], TList[3], TList[2], TList[1], TList[0]); 717 } 718 else 719 { 720 alias Reverse = 721 AliasSeq!( 722 Reverse!(TList[$/2 .. $ ]), 723 Reverse!(TList[ 0 .. $/2])); 724 } 725 } 726 727 /// 728 @safe unittest 729 { 730 alias Types = AliasSeq!(int, long, long, int, float, byte, ubyte, short, ushort, uint); 731 732 alias TL = Reverse!(Types); 733 static assert(is(TL == AliasSeq!(uint, ushort, short, ubyte, byte, float, int, long, long, int))); 734 } 735 736 /** 737 * Returns the type from TList that is the most derived from type T. 738 * If none are found, T is returned. 739 */ 740 template MostDerived(T, TList...) 741 { 742 static if (TList.length == 0) 743 alias MostDerived = T; 744 else static if (is(TList[0] : T)) 745 alias MostDerived = MostDerived!(TList[0], TList[1 .. $]); 746 else 747 alias MostDerived = MostDerived!(T, TList[1 .. $]); 748 } 749 750 /// 751 @safe unittest 752 { 753 class A { } 754 class B : A { } 755 class C : B { } 756 alias Types = AliasSeq!(A, C, B); 757 758 MostDerived!(Object, Types) x; // x is declared as type C 759 static assert(is(typeof(x) == C)); 760 } 761 762 /** 763 * Returns an `AliasSeq` with the elements of TList sorted so that the most 764 * derived types come first. 765 */ 766 template DerivedToFront(TList...) 767 { 768 static if (TList.length == 0) 769 alias DerivedToFront = TList; 770 else 771 alias DerivedToFront = 772 AliasSeq!(MostDerived!(TList[0], TList[1 .. $]), 773 DerivedToFront!(ReplaceAll!(MostDerived!(TList[0], TList[1 .. $]), 774 TList[0], 775 TList[1 .. $]))); 776 } 777 778 /// 779 @safe unittest 780 { 781 class A { } 782 class B : A { } 783 class C : B { } 784 alias Types = AliasSeq!(A, C, B); 785 786 alias TL = DerivedToFront!(Types); 787 static assert(is(TL == AliasSeq!(C, B, A))); 788 } 789 790 private enum staticMapExpandFactor = 150; 791 private string generateCases() 792 { 793 string[staticMapExpandFactor] chunks; 794 chunks[0] = q{}; 795 static foreach (enum i; 0 .. staticMapExpandFactor - 1) 796 chunks[i + 1] = chunks[i] ~ `F!(Args[` ~ i.stringof ~ `]),`; 797 string ret = `AliasSeq!(`; 798 foreach (chunk; chunks) 799 ret ~= `q{alias staticMap = AliasSeq!(` ~ chunk ~ `);},`; 800 return ret ~ `)`; 801 } 802 private alias staticMapBasicCases = AliasSeq!(mixin(generateCases())); 803 804 /** 805 Evaluates to $(D AliasSeq!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))). 806 */ 807 template staticMap(alias F, Args ...) 808 { 809 static if (Args.length < staticMapExpandFactor) 810 mixin(staticMapBasicCases[Args.length]); 811 else 812 alias staticMap = AliasSeq!(staticMap!(F, Args[0 .. $/2]), staticMap!(F, Args[$/2 .. $])); 813 } 814 815 /// 816 @safe unittest 817 { 818 import std.traits : Unqual; 819 alias TL = staticMap!(Unqual, int, const int, immutable int, uint, ubyte, byte, short, ushort); 820 static assert(is(TL == AliasSeq!(int, int, int, uint, ubyte, byte, short, ushort))); 821 } 822 823 @safe unittest 824 { 825 import std.traits : Unqual; 826 827 // empty 828 alias Empty = staticMap!(Unqual); 829 static assert(Empty.length == 0); 830 831 // single 832 alias Single = staticMap!(Unqual, const int); 833 static assert(is(Single == AliasSeq!int)); 834 835 alias T = staticMap!(Unqual, int, const int, immutable int, uint, ubyte, byte, short, ushort, long); 836 static assert(is(T == AliasSeq!(int, int, int, uint, ubyte, byte, short, ushort, long))); 837 } 838 839 // regression test for https://issues.dlang.org/show_bug.cgi?id=21088 840 @system unittest // typeid opEquals is @system 841 { 842 enum getTypeId(T) = typeid(T); 843 alias A = staticMap!(getTypeId, int); 844 845 assert(A == typeid(int)); 846 } 847 848 /** 849 Tests whether all given items satisfy a template predicate, i.e. evaluates to 850 $(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])). 851 852 Evaluation is $(I not) short-circuited if a false result is encountered; the 853 template predicate must be instantiable with all the given items. 854 */ 855 template allSatisfy(alias F, T...) 856 { 857 import core.internal.traits : allSat = allSatisfy; 858 alias allSatisfy = allSat!(F, T); 859 } 860 861 /// 862 @safe unittest 863 { 864 import std.traits : isIntegral; 865 866 static assert(!allSatisfy!(isIntegral, int, double)); 867 static assert( allSatisfy!(isIntegral, int, long)); 868 } 869 870 /** 871 Tests whether any given items satisfy a template predicate, i.e. evaluates to 872 $(D F!(T[0]) || F!(T[1]) || ... || F!(T[$ - 1])). 873 874 Evaluation is short-circuited if a true result is encountered; the 875 template predicate must be instantiable with one of the given items. 876 */ 877 template anySatisfy(alias F, T...) 878 { 879 import core.internal.traits : anySat = anySatisfy; 880 alias anySatisfy = anySat!(F, T); 881 } 882 883 /// 884 @safe unittest 885 { 886 import std.traits : isIntegral; 887 888 static assert(!anySatisfy!(isIntegral, string, double)); 889 static assert( anySatisfy!(isIntegral, int, double)); 890 } 891 892 private alias FilterShortCode = AliasSeq!( 893 q{ 894 alias Filter = Nothing; 895 }, 896 q{ 897 static if (pred!(TList[0])) 898 alias Filter = AliasSeq!(TList[0]); 899 else 900 alias Filter = Nothing; 901 }, 902 q{ 903 static if (pred!(TList[0])) 904 { 905 static if (pred!(TList[1])) 906 alias Filter = AliasSeq!(TList[0], TList[1]); 907 else 908 alias Filter = AliasSeq!(TList[0]); 909 } 910 else 911 { 912 static if (pred!(TList[1])) 913 alias Filter = AliasSeq!(TList[1]); 914 else 915 alias Filter = Nothing; 916 } 917 }, 918 q{ 919 static if (pred!(TList[0])) 920 { 921 static if (pred!(TList[1])) 922 { 923 static if (pred!(TList[2])) 924 alias Filter = AliasSeq!(TList[0], TList[1], TList[2]); 925 else 926 alias Filter = AliasSeq!(TList[0], TList[1]); 927 } 928 else 929 { 930 static if (pred!(TList[2])) 931 alias Filter = AliasSeq!(TList[0], TList[2]); 932 else 933 alias Filter = AliasSeq!(TList[0]); 934 } 935 } 936 else 937 { 938 static if (pred!(TList[1])) 939 { 940 static if (pred!(TList[2])) 941 alias Filter = AliasSeq!(TList[1], TList[2]); 942 else 943 alias Filter = AliasSeq!(TList[1]); 944 } 945 else 946 { 947 static if (pred!(TList[2])) 948 alias Filter = AliasSeq!(TList[2]); 949 else 950 alias Filter = Nothing; 951 } 952 } 953 }, 954 q{ 955 static if (pred!(TList[0])) 956 { 957 static if (pred!(TList[1])) 958 { 959 static if (pred!(TList[2])) 960 { 961 static if (pred!(TList[3])) 962 alias Filter = AliasSeq!(TList[0], TList[1], TList[2], TList[3]); 963 else 964 alias Filter = AliasSeq!(TList[0], TList[1], TList[2]); 965 } 966 else 967 { 968 static if (pred!(TList[3])) 969 alias Filter = AliasSeq!(TList[0], TList[1], TList[3]); 970 else 971 alias Filter = AliasSeq!(TList[0], TList[1]); 972 } 973 } 974 else 975 { 976 static if (pred!(TList[2])) 977 { 978 static if (pred!(TList[3])) 979 alias Filter = AliasSeq!(TList[0], TList[2], TList[3]); 980 else 981 alias Filter = AliasSeq!(TList[0], TList[2]); 982 } 983 else 984 { 985 static if (pred!(TList[3])) 986 alias Filter = AliasSeq!(TList[0], TList[3]); 987 else 988 alias Filter = AliasSeq!(TList[0]); 989 } 990 } 991 } 992 else 993 { 994 static if (pred!(TList[1])) 995 { 996 static if (pred!(TList[2])) 997 { 998 static if (pred!(TList[3])) 999 alias Filter = AliasSeq!(TList[1], TList[2], TList[3]); 1000 else 1001 alias Filter = AliasSeq!(TList[1], TList[2]); 1002 } 1003 else 1004 { 1005 static if (pred!(TList[3])) 1006 alias Filter = AliasSeq!(TList[1], TList[3]); 1007 else 1008 alias Filter = AliasSeq!(TList[1]); 1009 } 1010 } 1011 else 1012 { 1013 static if (pred!(TList[2])) 1014 { 1015 static if (pred!(TList[3])) 1016 alias Filter = AliasSeq!(TList[2], TList[3]); 1017 else 1018 alias Filter = AliasSeq!(TList[2]); 1019 } 1020 else 1021 { 1022 static if (pred!(TList[3])) 1023 alias Filter = AliasSeq!(TList[3]); 1024 else 1025 alias Filter = Nothing; 1026 } 1027 } 1028 } 1029 } 1030 ); 1031 1032 private enum filterExpandFactor = FilterShortCode.length; 1033 1034 package alias Nothing = AliasSeq!(); // yes, this really does speed up compilation! 1035 /** 1036 * Filters an `AliasSeq` using a template predicate. Returns an 1037 * `AliasSeq` of the elements which satisfy the predicate. 1038 */ 1039 template Filter(alias pred, TList ...) 1040 { 1041 static if (TList.length < filterExpandFactor) 1042 { 1043 mixin(FilterShortCode[TList.length]); 1044 } 1045 else 1046 { 1047 template MaybeNothing(Q ...) 1048 { 1049 static if (pred!(Q[0])) 1050 alias MaybeNothing = AliasSeq!(Q[0]); 1051 else 1052 alias MaybeNothing = Nothing; 1053 } 1054 alias Filter = staticMap!(MaybeNothing, TList); 1055 } 1056 } 1057 1058 /// 1059 @safe unittest 1060 { 1061 import std.traits : isNarrowString, isUnsigned; 1062 1063 alias Types1 = AliasSeq!(string, wstring, dchar[], char[], dstring, int); 1064 alias TL1 = Filter!(isNarrowString, Types1); 1065 static assert(is(TL1 == AliasSeq!(string, wstring, char[]))); 1066 1067 alias Types2 = AliasSeq!(int, byte, ubyte, dstring, dchar, uint, ulong); 1068 alias TL2 = Filter!(isUnsigned, Types2); 1069 static assert(is(TL2 == AliasSeq!(ubyte, uint, ulong))); 1070 } 1071 1072 @safe unittest 1073 { 1074 import std.traits : isPointer; 1075 1076 static assert(is(Filter!(isPointer, int, void*, char[], int*) == AliasSeq!(void*, int*))); 1077 static assert(is(Filter!isPointer == AliasSeq!())); 1078 } 1079 1080 @safe unittest 1081 { 1082 enum Yes(T) = true; 1083 static struct S {} 1084 static assert(is(Filter!(Yes, const(int), const(S)) == AliasSeq!(const(int), const(S)))); 1085 } 1086 1087 // Used in template predicate unit tests below. 1088 private version (StdUnittest) 1089 { 1090 template testAlways(T...) 1091 { 1092 enum testAlways = true; 1093 } 1094 1095 template testNever(T...) 1096 { 1097 enum testNever = false; 1098 } 1099 1100 template testError(T...) 1101 { 1102 static assert(false, "Should never be instantiated."); 1103 } 1104 } 1105 1106 1107 /** 1108 * Negates the passed template predicate. 1109 */ 1110 template templateNot(alias pred) 1111 { 1112 enum templateNot(T...) = !pred!T; 1113 } 1114 1115 /// 1116 @safe unittest 1117 { 1118 import std.traits : isPointer; 1119 1120 alias isNoPointer = templateNot!isPointer; 1121 static assert(!isNoPointer!(int*)); 1122 static assert(allSatisfy!(isNoPointer, string, char, float)); 1123 } 1124 1125 @safe unittest 1126 { 1127 static foreach (T; AliasSeq!(int, staticMap, 42)) 1128 { 1129 static assert(!Instantiate!(templateNot!testAlways, T)); 1130 static assert(Instantiate!(templateNot!testNever, T)); 1131 } 1132 } 1133 1134 1135 /** 1136 * Combines several template predicates using logical AND, i.e. constructs a new 1137 * predicate which evaluates to true for a given input T if and only if all of 1138 * the passed predicates are true for T. 1139 * 1140 * The predicates are evaluated from left to right, aborting evaluation in a 1141 * short-cut manner if a false result is encountered, in which case the latter 1142 * instantiations do not need to compile. 1143 */ 1144 template templateAnd(Preds...) 1145 { 1146 template templateAnd(T...) 1147 { 1148 static if (Preds.length == 0) 1149 { 1150 enum templateAnd = true; 1151 } 1152 else 1153 { 1154 static if (Instantiate!(Preds[0], T)) 1155 alias templateAnd = Instantiate!(.templateAnd!(Preds[1 .. $]), T); 1156 else 1157 enum templateAnd = false; 1158 } 1159 } 1160 } 1161 1162 /// 1163 @safe unittest 1164 { 1165 import std.traits : isNumeric, isUnsigned; 1166 1167 alias storesNegativeNumbers = templateAnd!(isNumeric, templateNot!isUnsigned); 1168 static assert(storesNegativeNumbers!int); 1169 static assert(!storesNegativeNumbers!string && !storesNegativeNumbers!uint); 1170 1171 // An empty sequence of predicates always yields true. 1172 alias alwaysTrue = templateAnd!(); 1173 static assert(alwaysTrue!int); 1174 } 1175 1176 @safe unittest 1177 { 1178 static foreach (T; AliasSeq!(int, staticMap, 42)) 1179 { 1180 static assert( Instantiate!(templateAnd!(), T)); 1181 static assert( Instantiate!(templateAnd!(testAlways), T)); 1182 static assert( Instantiate!(templateAnd!(testAlways, testAlways), T)); 1183 static assert(!Instantiate!(templateAnd!(testNever), T)); 1184 static assert(!Instantiate!(templateAnd!(testAlways, testNever), T)); 1185 static assert(!Instantiate!(templateAnd!(testNever, testAlways), T)); 1186 1187 static assert(!Instantiate!(templateAnd!(testNever, testError), T)); 1188 static assert(!is(typeof(Instantiate!(templateAnd!(testAlways, testError), T)))); 1189 } 1190 } 1191 1192 1193 /** 1194 * Combines several template predicates using logical OR, i.e. constructs a new 1195 * predicate which evaluates to true for a given input T if and only at least 1196 * one of the passed predicates is true for T. 1197 * 1198 * The predicates are evaluated from left to right, aborting evaluation in a 1199 * short-cut manner if a true result is encountered, in which case the latter 1200 * instantiations do not need to compile. 1201 */ 1202 template templateOr(Preds...) 1203 { 1204 template templateOr(T...) 1205 { 1206 static if (Preds.length == 0) 1207 { 1208 enum templateOr = false; 1209 } 1210 else 1211 { 1212 static if (Instantiate!(Preds[0], T)) 1213 enum templateOr = true; 1214 else 1215 alias templateOr = Instantiate!(.templateOr!(Preds[1 .. $]), T); 1216 } 1217 } 1218 } 1219 1220 /// 1221 @safe unittest 1222 { 1223 import std.traits : isPointer, isUnsigned; 1224 1225 alias isPtrOrUnsigned = templateOr!(isPointer, isUnsigned); 1226 static assert( isPtrOrUnsigned!uint && isPtrOrUnsigned!(short*)); 1227 static assert(!isPtrOrUnsigned!int && !isPtrOrUnsigned!(string)); 1228 1229 // An empty sequence of predicates never yields true. 1230 alias alwaysFalse = templateOr!(); 1231 static assert(!alwaysFalse!int); 1232 } 1233 1234 @safe unittest 1235 { 1236 static foreach (T; AliasSeq!(int, staticMap, 42)) 1237 { 1238 static assert( Instantiate!(templateOr!(testAlways), T)); 1239 static assert( Instantiate!(templateOr!(testAlways, testAlways), T)); 1240 static assert( Instantiate!(templateOr!(testAlways, testNever), T)); 1241 static assert( Instantiate!(templateOr!(testNever, testAlways), T)); 1242 static assert(!Instantiate!(templateOr!(), T)); 1243 static assert(!Instantiate!(templateOr!(testNever), T)); 1244 1245 static assert( Instantiate!(templateOr!(testAlways, testError), T)); 1246 static assert( Instantiate!(templateOr!(testNever, testAlways, testError), T)); 1247 // DMD @@BUG@@: Assertion fails for int, seems like a error gagging 1248 // problem. The bug goes away when removing some of the other template 1249 // instantiations in the module. 1250 // static assert(!is(typeof(Instantiate!(templateOr!(testNever, testError), T)))); 1251 } 1252 } 1253 1254 /** 1255 * Converts any foreach-iterable entity (e.g. an input range) to an alias sequence. 1256 * 1257 * Params: 1258 * iter = the entity to convert into an `AliasSeq`. It must be able to be able to be iterated over using 1259 * a $(LINK2 https://dlang.org/spec/statement.html#foreach-statement, foreach-statement). 1260 * 1261 * Returns: 1262 * An `AliasSeq` containing the values produced by iterating over `iter`. 1263 */ 1264 template aliasSeqOf(alias iter) 1265 if (isIterable!(typeof(iter)) && !isInfinite!(typeof(iter))) 1266 { 1267 import std.array : array; 1268 1269 struct Impl 1270 { 1271 static foreach (size_t i, el; iter.array) 1272 mixin(`auto e` ~ i.stringof ~ ` = el;`); 1273 } 1274 enum aliasSeqOf = Impl.init.tupleof; 1275 } 1276 1277 /// 1278 @safe unittest 1279 { 1280 import std.algorithm.iteration : map; 1281 import std.algorithm.sorting : sort; 1282 import std..string : capitalize; 1283 1284 struct S 1285 { 1286 int a; 1287 int c; 1288 int b; 1289 } 1290 1291 alias capMembers = aliasSeqOf!([__traits(allMembers, S)].sort().map!capitalize()); 1292 static assert(capMembers[0] == "A"); 1293 static assert(capMembers[1] == "B"); 1294 static assert(capMembers[2] == "C"); 1295 } 1296 1297 /// 1298 @safe unittest 1299 { 1300 static immutable REF = [0, 1, 2, 3]; 1301 foreach (I, V; aliasSeqOf!([0, 1, 2, 3])) 1302 { 1303 static assert(V == I); 1304 static assert(V == REF[I]); 1305 } 1306 } 1307 1308 @safe unittest 1309 { 1310 import std.conv : to, octal; 1311 import std.range : iota; 1312 //Testing compile time octal 1313 foreach (I2; aliasSeqOf!(iota(0, 8))) 1314 foreach (I1; aliasSeqOf!(iota(0, 8))) 1315 { 1316 enum oct = I2 * 8 + I1; 1317 enum dec = I2 * 10 + I1; 1318 enum str = to!string(dec); 1319 static assert(octal!dec == oct); 1320 static assert(octal!str == oct); 1321 } 1322 } 1323 1324 @safe unittest 1325 { 1326 enum REF = "日本語"d; 1327 foreach (I, V; aliasSeqOf!"日本語"c) 1328 { 1329 static assert(V == REF[I]); 1330 } 1331 } 1332 1333 @safe unittest 1334 { 1335 struct S 1336 { 1337 int opApply(scope int delegate(ref int) dg) 1338 { 1339 foreach (int i; 3 .. 5) 1340 if (auto r = dg(i)) 1341 return r; 1342 return 0; 1343 } 1344 } 1345 static assert(aliasSeqOf!(S.init) == AliasSeq!(3, 4)); 1346 } 1347 1348 @safe unittest 1349 { 1350 struct Infinite 1351 { 1352 int front(); 1353 void popFront(); 1354 enum empty = false; 1355 } 1356 enum infinite = Infinite(); 1357 static assert(isInfinite!Infinite); 1358 static assert(!__traits(compiles, aliasSeqOf!infinite)); 1359 } 1360 1361 /** 1362 * $(LINK2 http://en.wikipedia.org/wiki/Partial_application, Partially applies) 1363 * $(D_PARAM Template) by binding its first (left) or last (right) arguments 1364 * to $(D_PARAM args). 1365 * 1366 * Behaves like the identity function when $(D_PARAM args) is empty. 1367 * Params: 1368 * Template = template to partially apply 1369 * args = arguments to bind 1370 * Returns: 1371 * _Template with arity smaller than or equal to $(D_PARAM Template) 1372 */ 1373 template ApplyLeft(alias Template, args...) 1374 { 1375 alias ApplyLeft(right...) = SmartAlias!(Template!(args, right)); 1376 } 1377 1378 /// Ditto 1379 template ApplyRight(alias Template, args...) 1380 { 1381 alias ApplyRight(left...) = SmartAlias!(Template!(left, args)); 1382 } 1383 1384 /// 1385 @safe unittest 1386 { 1387 // enum bool isImplicitlyConvertible(From, To) 1388 import std.traits : isImplicitlyConvertible; 1389 1390 static assert(allSatisfy!( 1391 ApplyLeft!(isImplicitlyConvertible, ubyte), 1392 short, ushort, int, uint, long, ulong)); 1393 1394 static assert(is(Filter!(ApplyRight!(isImplicitlyConvertible, short), 1395 ubyte, string, short, float, int) == AliasSeq!(ubyte, short))); 1396 } 1397 1398 /// 1399 @safe unittest 1400 { 1401 import std.traits : hasMember, ifTestable; 1402 1403 struct T1 1404 { 1405 bool foo; 1406 } 1407 1408 struct T2 1409 { 1410 struct Test 1411 { 1412 bool opCast(T : bool)() { return true; } 1413 } 1414 1415 Test foo; 1416 } 1417 1418 static assert(allSatisfy!(ApplyRight!(hasMember, "foo"), T1, T2)); 1419 static assert(allSatisfy!(ApplyRight!(ifTestable, a => a.foo), T1, T2)); 1420 } 1421 1422 /// 1423 @safe unittest 1424 { 1425 import std.traits : Largest; 1426 1427 alias Types = AliasSeq!(byte, short, int, long); 1428 1429 static assert(is(staticMap!(ApplyLeft!(Largest, short), Types) == 1430 AliasSeq!(short, short, int, long))); 1431 static assert(is(staticMap!(ApplyLeft!(Largest, int), Types) == 1432 AliasSeq!(int, int, int, long))); 1433 } 1434 1435 /// 1436 @safe unittest 1437 { 1438 import std.traits : FunctionAttribute, SetFunctionAttributes; 1439 1440 static void foo() @system; 1441 static int bar(int) @system; 1442 1443 alias SafeFunctions = AliasSeq!( 1444 void function() @safe, 1445 int function(int) @safe); 1446 1447 static assert(is(staticMap!(ApplyRight!( 1448 SetFunctionAttributes, "D", FunctionAttribute.safe), 1449 typeof(&foo), typeof(&bar)) == SafeFunctions)); 1450 } 1451 1452 private template SmartAlias(T...) 1453 { 1454 static if (T.length == 1) 1455 { 1456 alias SmartAlias = Alias!T; 1457 } 1458 else 1459 { 1460 alias SmartAlias = T; 1461 } 1462 } 1463 1464 @safe unittest 1465 { 1466 static assert(is(typeof({ 1467 alias T(T0, int a, double b, alias T1, string c) = AliasSeq!(T0, a, b, T1, c); 1468 alias T0 = ApplyRight!(ApplyLeft, ApplyRight); 1469 alias T1 = T0!ApplyLeft; 1470 alias T2 = T1!T; 1471 alias T3 = T2!(3, "foo"); 1472 alias T4 = T3!(short, 3, 3.3); 1473 static assert(Pack!T4.equals!(short, 3, 3.3, 3, "foo")); 1474 1475 import std.traits : isImplicitlyConvertible; 1476 alias U1 = ApplyLeft!(ApplyRight, isImplicitlyConvertible); 1477 alias U2 = U1!int; 1478 enum U3 = U2!short; 1479 static assert(U3); 1480 }))); 1481 } 1482 1483 /** 1484 * Creates an `AliasSeq` which repeats `TList` exactly `n` times. 1485 */ 1486 template Repeat(size_t n, TList...) 1487 { 1488 static if (n == 0) 1489 { 1490 alias Repeat = AliasSeq!(); 1491 } 1492 else static if (n == 1) 1493 { 1494 alias Repeat = AliasSeq!TList; 1495 } 1496 else static if (n == 2) 1497 { 1498 alias Repeat = AliasSeq!(TList, TList); 1499 } 1500 /* Cases 3 to 8 are to speed up compilation 1501 */ 1502 else static if (n == 3) 1503 { 1504 alias Repeat = AliasSeq!(TList, TList, TList); 1505 } 1506 else static if (n == 4) 1507 { 1508 alias Repeat = AliasSeq!(TList, TList, TList, TList); 1509 } 1510 else static if (n == 5) 1511 { 1512 alias Repeat = AliasSeq!(TList, TList, TList, TList, TList); 1513 } 1514 else static if (n == 6) 1515 { 1516 alias Repeat = AliasSeq!(TList, TList, TList, TList, TList, TList); 1517 } 1518 else static if (n == 7) 1519 { 1520 alias Repeat = AliasSeq!(TList, TList, TList, TList, TList, TList, TList); 1521 } 1522 else static if (n == 8) 1523 { 1524 alias Repeat = AliasSeq!(TList, TList, TList, TList, TList, TList, TList, TList); 1525 } 1526 else 1527 { 1528 alias R = Repeat!((n - 1) / 2, TList); 1529 static if ((n - 1) % 2 == 0) 1530 { 1531 alias Repeat = AliasSeq!(TList, R, R); 1532 } 1533 else 1534 { 1535 alias Repeat = AliasSeq!(TList, TList, R, R); 1536 } 1537 } 1538 } 1539 1540 /// 1541 @safe unittest 1542 { 1543 alias ImInt0 = Repeat!(0, int); 1544 static assert(is(ImInt0 == AliasSeq!())); 1545 1546 alias ImInt1 = Repeat!(1, immutable(int)); 1547 static assert(is(ImInt1 == AliasSeq!(immutable(int)))); 1548 1549 alias Real3 = Repeat!(3, real); 1550 static assert(is(Real3 == AliasSeq!(real, real, real))); 1551 1552 alias Real12 = Repeat!(4, Real3); 1553 static assert(is(Real12 == AliasSeq!(real, real, real, real, real, real, 1554 real, real, real, real, real, real))); 1555 1556 alias Composite = AliasSeq!(uint, int); 1557 alias Composite2 = Repeat!(2, Composite); 1558 static assert(is(Composite2 == AliasSeq!(uint, int, uint, int))); 1559 1560 alias ImInt10 = Repeat!(10, int); 1561 static assert(is(ImInt10 == AliasSeq!(int, int, int, int, int, int, int, int, int, int))); 1562 } 1563 1564 1565 /// 1566 @safe unittest 1567 { 1568 auto staticArray(T, size_t n)(Repeat!(n, T) elems) 1569 { 1570 T[n] a = [elems]; 1571 return a; 1572 } 1573 1574 auto a = staticArray!(long, 3)(3, 1, 4); 1575 assert(is(typeof(a) == long[3])); 1576 assert(a == [3, 1, 4]); 1577 } 1578 1579 /** 1580 * Sorts an $(LREF AliasSeq) using `cmp`. 1581 * 1582 * Parameters: 1583 * cmp = A template that returns a `bool` (if its first argument is less than the second one) 1584 * or an `int` (-1 means less than, 0 means equal, 1 means greater than) 1585 * 1586 * Seq = The $(LREF AliasSeq) to sort 1587 * 1588 * Returns: The sorted alias sequence 1589 */ 1590 template staticSort(alias cmp, Seq...) 1591 { 1592 static if (Seq.length < 2) 1593 { 1594 alias staticSort = Seq; 1595 } 1596 else 1597 { 1598 private alias btm = staticSort!(cmp, Seq[0 .. $ / 2]); 1599 private alias top = staticSort!(cmp, Seq[$ / 2 .. $]); 1600 1601 static if (isLessEq!(cmp, btm[$ - 1], top[0])) 1602 alias staticSort = AliasSeq!(btm, top); // already ascending 1603 else static if (isLessEq!(cmp, top[$ - 1], btm[0])) 1604 alias staticSort = AliasSeq!(top, btm); // already descending 1605 else 1606 alias staticSort = staticMerge!(cmp, Seq.length / 2, btm, top); 1607 } 1608 } 1609 1610 /// 1611 @safe unittest 1612 { 1613 alias Nums = AliasSeq!(7, 2, 3, 23); 1614 enum Comp(int N1, int N2) = N1 < N2; 1615 static assert(AliasSeq!(2, 3, 7, 23) == staticSort!(Comp, Nums)); 1616 } 1617 1618 /// 1619 @safe unittest 1620 { 1621 alias Types = AliasSeq!(uint, short, ubyte, long, ulong); 1622 enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1); 1623 static assert(is(AliasSeq!(uint, ubyte, ulong, short, long) == staticSort!(Comp, 1624 Types))); 1625 } 1626 1627 private template staticMerge(alias cmp, int half, Seq...) 1628 { 1629 static if (half == 0 || half == Seq.length) 1630 { 1631 alias staticMerge = Seq; 1632 } 1633 else 1634 { 1635 static if (isLessEq!(cmp, Seq[0], Seq[half])) 1636 { 1637 alias staticMerge = AliasSeq!(Seq[0], 1638 staticMerge!(cmp, half - 1, Seq[1 .. $])); 1639 } 1640 else 1641 { 1642 alias staticMerge = AliasSeq!(Seq[half], 1643 staticMerge!(cmp, half, Seq[0 .. half], Seq[half + 1 .. $])); 1644 } 1645 } 1646 } 1647 1648 private template isLessEq(alias cmp, Seq...) 1649 if (Seq.length == 2) 1650 { 1651 private enum Result = cmp!(Seq[1], Seq[0]); 1652 static if (is(typeof(Result) == bool)) 1653 enum isLessEq = !Result; 1654 else static if (is(typeof(Result) : int)) 1655 enum isLessEq = Result >= 0; 1656 else 1657 static assert(0, typeof(Result).stringof ~ " is not a value comparison type"); 1658 } 1659 1660 /** 1661 * Checks if an $(LREF AliasSeq) is sorted according to `cmp`. 1662 * 1663 * Parameters: 1664 * cmp = A template that returns a `bool` (if its first argument is less than the second one) 1665 * or an `int` (-1 means less than, 0 means equal, 1 means greater than) 1666 * 1667 * Seq = The $(LREF AliasSeq) to check 1668 * 1669 * Returns: `true` if `Seq` is sorted; otherwise `false` 1670 */ 1671 template staticIsSorted(alias cmp, Seq...) 1672 { 1673 static if (Seq.length <= 1) 1674 enum staticIsSorted = true; 1675 else static if (Seq.length == 2) 1676 enum staticIsSorted = isLessEq!(cmp, Seq[0], Seq[1]); 1677 else 1678 { 1679 enum staticIsSorted = 1680 isLessEq!(cmp, Seq[($ / 2) - 1], Seq[$ / 2]) && 1681 staticIsSorted!(cmp, Seq[0 .. $ / 2]) && 1682 staticIsSorted!(cmp, Seq[$ / 2 .. $]); 1683 } 1684 } 1685 1686 /// 1687 @safe unittest 1688 { 1689 enum Comp(int N1, int N2) = N1 < N2; 1690 static assert( staticIsSorted!(Comp, 2, 2)); 1691 static assert( staticIsSorted!(Comp, 2, 3, 7, 23)); 1692 static assert(!staticIsSorted!(Comp, 7, 2, 3, 23)); 1693 } 1694 1695 /// 1696 @safe unittest 1697 { 1698 enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1); 1699 static assert( staticIsSorted!(Comp, uint, ubyte, ulong, short, long)); 1700 static assert(!staticIsSorted!(Comp, uint, short, ubyte, long, ulong)); 1701 } 1702 1703 /** 1704 Selects a subset of `Args` by stepping with fixed `stepSize` over the sequence. 1705 A negative `stepSize` starts iteration with the last element. 1706 1707 Params: 1708 stepSize = Number of elements to increment on each iteration. Can't be `0`. 1709 Args = Template arguments. 1710 1711 Returns: An `AliasSeq` filtered by the selected stride. 1712 */ 1713 template Stride(int stepSize, Args...) 1714 if (stepSize != 0) 1715 { 1716 static if (Args.length == 0) 1717 { 1718 alias Stride = AliasSeq!(); 1719 } 1720 else static if (stepSize > 0) 1721 { 1722 static if (stepSize >= Args.length) 1723 alias Stride = AliasSeq!(Args[0]); 1724 else 1725 alias Stride = AliasSeq!(Args[0], Stride!(stepSize, Args[stepSize .. $])); 1726 } 1727 else 1728 { 1729 static if (-stepSize >= Args.length) 1730 alias Stride = AliasSeq!(Args[$ - 1]); 1731 else 1732 alias Stride = AliasSeq!(Args[$ - 1], Stride!(stepSize, Args[0 .. $ + stepSize])); 1733 } 1734 } 1735 1736 /// 1737 @safe unittest 1738 { 1739 static assert(is(Stride!(1, short, int, long) == AliasSeq!(short, int, long))); 1740 static assert(is(Stride!(2, short, int, long) == AliasSeq!(short, long))); 1741 static assert(is(Stride!(-1, short, int, long) == AliasSeq!(long, int, short))); 1742 static assert(is(Stride!(-2, short, int, long) == AliasSeq!(long, short))); 1743 1744 alias attribs = AliasSeq!(short, int, long, ushort, uint, ulong); 1745 static assert(is(Stride!(3, attribs) == AliasSeq!(short, ushort))); 1746 static assert(is(Stride!(3, attribs[1 .. $]) == AliasSeq!(int, uint))); 1747 static assert(is(Stride!(-3, attribs) == AliasSeq!(ulong, long))); 1748 } 1749 1750 @safe unittest 1751 { 1752 static assert(Pack!(Stride!(5, int)).equals!(int)); 1753 static assert(Pack!(Stride!(-5, int)).equals!(int)); 1754 static assert(!__traits(compiles, Stride!(0, int))); 1755 } 1756 1757 /** 1758 * Instantiates the given template with the given parameters. 1759 * 1760 * Used to work around syntactic limitations of D with regard to instantiating 1761 * a template from an alias sequence (e.g. `T[0]!(...)` is not valid) or a 1762 * template returning another template (e.g. `Foo!(Bar)!(Baz)` is not allowed). 1763 * 1764 * Params: 1765 * Template = The template to instantiate. 1766 * Params = The parameters with which to instantiate the template. 1767 * Returns: 1768 * The instantiated template. 1769 */ 1770 alias Instantiate(alias Template, Params...) = Template!Params; 1771 1772 /// 1773 @safe unittest 1774 { 1775 // ApplyRight combined with Instantiate can be used to apply various 1776 // templates to the same parameters. 1777 import std..string : leftJustify, center, rightJustify; 1778 alias functions = staticMap!(ApplyRight!(Instantiate, string), 1779 leftJustify, center, rightJustify); 1780 string result = ""; 1781 static foreach (f; functions) 1782 { 1783 { 1784 auto x = &f; // not a template, but a function instantiation 1785 result ~= x("hello", 7); 1786 result ~= ";"; 1787 } 1788 } 1789 1790 assert(result == "hello ; hello ; hello;"); 1791 } 1792 1793 // : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : // 1794 private: 1795 1796 /* 1797 * [internal] Returns true if a and b are the same thing, or false if 1798 * not. Both a and b can be types, literals, or symbols. 1799 * 1800 * How: When: 1801 * is(a == b) - both are types 1802 * a == b - both are literals (true literals, enums) 1803 * __traits(isSame, a, b) - other cases (variables, functions, 1804 * templates, etc.) 1805 */ 1806 private template isSame(ab...) 1807 if (ab.length == 2) 1808 { 1809 static if (is(ab[0]) && is(ab[1])) 1810 { 1811 enum isSame = is(ab[0] == ab[1]); 1812 } 1813 else static if (!is(ab[0]) && !is(ab[1]) && 1814 !(is(typeof(&ab[0])) && is(typeof(&ab[1]))) && 1815 __traits(compiles, { enum isSame = ab[0] == ab[1]; })) 1816 { 1817 enum isSame = (ab[0] == ab[1]); 1818 } 1819 else 1820 { 1821 enum isSame = __traits(isSame, ab[0], ab[1]); 1822 } 1823 } 1824 1825 @safe unittest 1826 { 1827 static assert( isSame!(int, int)); 1828 static assert(!isSame!(int, short)); 1829 1830 enum a = 1, b = 1, c = 2, s = "a", t = "a"; 1831 static assert( isSame!(1, 1)); 1832 static assert( isSame!(a, 1)); 1833 static assert( isSame!(a, b)); 1834 static assert(!isSame!(b, c)); 1835 static assert( isSame!("a", "a")); 1836 static assert( isSame!(s, "a")); 1837 static assert( isSame!(s, t)); 1838 static assert(!isSame!(1, "1")); 1839 static assert(!isSame!(a, "a")); 1840 static assert( isSame!(isSame, isSame)); 1841 static assert(!isSame!(isSame, a)); 1842 1843 static assert(!isSame!(byte, a)); 1844 static assert(!isSame!(short, isSame)); 1845 static assert(!isSame!(a, int)); 1846 static assert(!isSame!(long, isSame)); 1847 1848 static immutable X = 1, Y = 1, Z = 2; 1849 static assert( isSame!(X, X)); 1850 static assert(!isSame!(X, Y)); 1851 static assert(!isSame!(Y, Z)); 1852 1853 int foo(); 1854 int bar(); 1855 real baz(int); 1856 static assert( isSame!(foo, foo)); 1857 static assert(!isSame!(foo, bar)); 1858 static assert(!isSame!(bar, baz)); 1859 static assert( isSame!(baz, baz)); 1860 static assert(!isSame!(foo, 0)); 1861 1862 int x, y; 1863 real z; 1864 static assert( isSame!(x, x)); 1865 static assert(!isSame!(x, y)); 1866 static assert(!isSame!(y, z)); 1867 static assert( isSame!(z, z)); 1868 static assert(!isSame!(x, 0)); 1869 } 1870 1871 /* 1872 * [internal] Wraps a sequence in a template. Used only in unittests. 1873 */ 1874 private template Pack(T...) 1875 { 1876 alias Expand = T; 1877 enum equals(U...) = isSame!(Pack!T, Pack!U); 1878 } 1879 1880 @safe unittest 1881 { 1882 static assert( Pack!(1, int, "abc").equals!(1, int, "abc")); 1883 static assert(!Pack!(1, int, "abc").equals!(1, int, "cba")); 1884 }