1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /** 6 * Type traits. 7 * 8 * Templates in this module are used to obtain type information at compile 9 * time. 10 * 11 * Copyright: Eugene Wissner 2017-2020. 12 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, 13 * Mozilla Public License, v. 2.0). 14 * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) 15 * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/trait.d, 16 * tanya/meta/trait.d) 17 */ 18 module tanya.meta.trait; 19 20 import tanya.meta.metafunction; 21 import tanya.meta.transform; 22 23 /** 24 * Determines whether $(D_PARAM T) is a wide string, i.e. consists of 25 * $(D_KEYWORD dchar). 26 * 27 * The character type of the string can be qualified with $(D_KEYWORD const), 28 * $(D_KEYWORD immutable) or $(D_KEYWORD inout), but an occurrence of 29 * $(D_KEYWORD shared) in the character type results in returning 30 * $(D_KEYWORD false). 31 * The string itself (in contrast to its character type) can have any type 32 * qualifiers. 33 * 34 * Static $(D_KEYWORD char) and $(D_KEYWORD wchar) arrays are not considered 35 * strings. 36 * 37 * Params: 38 * T = A Type. 39 * 40 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a wide string, 41 * $(D_KEYWORD false) otherwise. 42 * 43 * See_Also: $(D_PSYMBOL isNarrowString). 44 */ 45 enum bool isWideString(T) = is(T : const dchar[]) && !isStaticArray!T; 46 47 /// 48 @nogc nothrow pure @safe unittest 49 { 50 static assert(isWideString!(dchar[])); 51 static assert(!isWideString!(char[])); 52 static assert(!isWideString!(wchar[])); 53 54 static assert(isWideString!dstring); 55 static assert(!isWideString!string); 56 static assert(!isWideString!wstring); 57 58 static assert(isWideString!(const dstring)); 59 static assert(!isWideString!(const string)); 60 static assert(!isWideString!(const wstring)); 61 62 static assert(isWideString!(shared dstring)); 63 static assert(!isWideString!(shared string)); 64 static assert(!isWideString!(shared wstring)); 65 66 static assert(isWideString!(const(dchar)[])); 67 static assert(isWideString!(inout(dchar)[])); 68 static assert(!isWideString!(shared(const(dchar))[])); 69 static assert(!isWideString!(shared(dchar)[])); 70 static assert(!isWideString!(dchar[10])); 71 } 72 73 /** 74 * Determines whether $(D_PARAM T) is a complex type. 75 * 76 * Complex types are: 77 * $(UL 78 * $(LI cfloat) 79 * $(LI ifloat) 80 * $(LI cdouble) 81 * $(LI idouble) 82 * $(LI creal) 83 * $(LI ireal) 84 * ) 85 * 86 * Params: 87 * T = A type. 88 * 89 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a complex type, 90 * $(D_KEYWORD false) otherwise. 91 */ 92 enum bool isComplex(T) = is(Unqual!(OriginalType!T) == cfloat) 93 || is(Unqual!(OriginalType!T) == ifloat) 94 || is(Unqual!(OriginalType!T) == cdouble) 95 || is(Unqual!(OriginalType!T) == idouble) 96 || is(Unqual!(OriginalType!T) == creal) 97 || is(Unqual!(OriginalType!T) == ireal); 98 99 /// 100 @nogc nothrow pure @safe unittest 101 { 102 static assert(isComplex!cfloat); 103 static assert(isComplex!ifloat); 104 static assert(isComplex!cdouble); 105 static assert(isComplex!idouble); 106 static assert(isComplex!creal); 107 static assert(isComplex!ireal); 108 109 static assert(!isComplex!float); 110 static assert(!isComplex!double); 111 static assert(!isComplex!real); 112 } 113 114 /* 115 * Tests whether $(D_PARAM T) is an interface. 116 * 117 * Params: 118 * T = A type. 119 * 120 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface, 121 * $(D_KEYWORD false) otherwise. 122 */ 123 private enum bool isInterface(T) = is(T == interface); 124 125 /** 126 * Determines whether $(D_PARAM T) is a polymorphic type, i.e. a 127 * $(D_KEYWORD class) or an $(D_KEYWORD interface). 128 * 129 * Params: 130 * T = A type. 131 * 132 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a $(D_KEYWORD class) or an 133 * $(D_KEYWORD interface), $(D_KEYWORD false) otherwise. 134 */ 135 enum bool isPolymorphicType(T) = is(T == class) || is(T == interface); 136 137 /// 138 @nogc nothrow pure @safe unittest 139 { 140 interface I 141 { 142 } 143 static assert(isPolymorphicType!Object); 144 static assert(isPolymorphicType!I); 145 static assert(!isPolymorphicType!short); 146 } 147 148 /** 149 * Determines whether the type $(D_PARAM T) has a static method 150 * named $(D_PARAM member). 151 * 152 * Params: 153 * T = Aggregate type. 154 * member = Symbol name. 155 * 156 * Returns: $(D_KEYWORD true) if $(D_PARAM member) is a static method of 157 * $(D_PARAM T), $(D_KEYWORD false) otherwise. 158 */ 159 template hasStaticMember(T, string member) 160 { 161 static if (hasMember!(T, member)) 162 { 163 alias Member = Alias!(__traits(getMember, T, member)); 164 165 static if (__traits(isStaticFunction, Member) 166 || (!isFunction!Member && is(typeof(&Member)))) 167 { 168 enum bool hasStaticMember = true; 169 } 170 else 171 { 172 enum bool hasStaticMember = false; 173 } 174 } 175 else 176 { 177 enum bool hasStaticMember = false; 178 } 179 } 180 181 /// 182 @nogc nothrow pure @safe unittest 183 { 184 static struct S 185 { 186 int member1; 187 void member2() 188 { 189 } 190 static int member3; 191 static void member4() 192 { 193 } 194 static void function() member5; 195 } 196 static assert(!hasStaticMember!(S, "member1")); 197 static assert(!hasStaticMember!(S, "member2")); 198 static assert(hasStaticMember!(S, "member3")); 199 static assert(hasStaticMember!(S, "member4")); 200 static assert(hasStaticMember!(S, "member5")); 201 } 202 203 /** 204 * Determines whether $(D_PARAM T) is a floating point type. 205 * 206 * Floating point types are: 207 * $(UL 208 * $(LI float) 209 * $(LI double) 210 * $(LI real) 211 * ) 212 * 213 * Params: 214 * T = A type. 215 * 216 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a floating point type, 217 * $(D_KEYWORD false) otherwise. 218 */ 219 enum bool isFloatingPoint(T) = is(Unqual!(OriginalType!T) == double) 220 || is(Unqual!(OriginalType!T) == float) 221 || is(Unqual!(OriginalType!T) == real); 222 223 /// 224 @nogc nothrow pure @safe unittest 225 { 226 static assert(isFloatingPoint!float); 227 static assert(isFloatingPoint!double); 228 static assert(isFloatingPoint!real); 229 static assert(isFloatingPoint!(const float)); 230 static assert(isFloatingPoint!(shared float)); 231 static assert(isFloatingPoint!(shared const float)); 232 static assert(!isFloatingPoint!int); 233 } 234 235 /** 236 * Determines whether $(D_PARAM T) is a signed numeric type. 237 * 238 * Signed numeric types are: 239 * $(UL 240 * $(LI byte) 241 * $(LI short) 242 * $(LI int) 243 * $(LI long) 244 * $(LI float) 245 * $(LI double) 246 * $(LI real) 247 * ) 248 * 249 * Params: 250 * T = A type. 251 * 252 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a signed numeric type, 253 * $(D_KEYWORD false) otherwise. 254 * 255 * See_Also: $(D_PSYMBOL isUnsigned). 256 */ 257 enum bool isSigned(T) = is(Unqual!(OriginalType!T) == byte) 258 || is(Unqual!(OriginalType!T) == short) 259 || is(Unqual!(OriginalType!T) == int) 260 || is(Unqual!(OriginalType!T) == long) 261 || isFloatingPoint!T; 262 263 /// 264 @nogc nothrow pure @safe unittest 265 { 266 static assert(isSigned!byte); 267 static assert(isSigned!short); 268 static assert(isSigned!int); 269 static assert(isSigned!long); 270 static assert(isSigned!float); 271 static assert(isSigned!double); 272 static assert(isSigned!real); 273 274 static assert(!isSigned!ubyte); 275 static assert(!isSigned!ushort); 276 static assert(!isSigned!uint); 277 static assert(!isSigned!ulong); 278 } 279 280 /** 281 * Determines whether $(D_PARAM T) is an unsigned numeric type. 282 * 283 * Unsigned numeric types are: 284 * $(UL 285 * $(LI ubyte) 286 * $(LI ushort) 287 * $(LI uint) 288 * $(LI ulong) 289 * ) 290 * 291 * Params: 292 * T = A type. 293 * 294 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an unsigned numeric type, 295 * $(D_KEYWORD false) otherwise. 296 * 297 * See_Also: $(D_PSYMBOL isSigned). 298 */ 299 enum bool isUnsigned(T) = is(Unqual!(OriginalType!T) == ubyte) 300 || is(Unqual!(OriginalType!T) == ushort) 301 || is(Unqual!(OriginalType!T) == uint) 302 || is(Unqual!(OriginalType!T) == ulong); 303 304 /// 305 @nogc nothrow pure @safe unittest 306 { 307 static assert(isUnsigned!ubyte); 308 static assert(isUnsigned!ushort); 309 static assert(isUnsigned!uint); 310 static assert(isUnsigned!ulong); 311 312 static assert(!isUnsigned!byte); 313 static assert(!isUnsigned!short); 314 static assert(!isUnsigned!int); 315 static assert(!isUnsigned!long); 316 static assert(!isUnsigned!float); 317 static assert(!isUnsigned!double); 318 static assert(!isUnsigned!real); 319 } 320 321 /** 322 * Determines whether $(D_PARAM T) is an integral type. 323 * 324 * Integral types are: 325 * $(UL 326 * $(LI ubyte) 327 * $(LI ushort) 328 * $(LI uint) 329 * $(LI ulong) 330 * $(LI byte) 331 * $(LI short) 332 * $(LI int) 333 * $(LI long) 334 * ) 335 * 336 * Params: 337 * T = A type. 338 * 339 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an integral type, 340 * $(D_KEYWORD false) otherwise. 341 */ 342 enum bool isIntegral(T) = isUnsigned!T 343 || is(Unqual!(OriginalType!T) == byte) 344 || is(Unqual!(OriginalType!T) == short) 345 || is(Unqual!(OriginalType!T) == int) 346 || is(Unqual!(OriginalType!T) == long); 347 348 /// 349 @nogc nothrow pure @safe unittest 350 { 351 static assert(isIntegral!ubyte); 352 static assert(isIntegral!byte); 353 static assert(!isIntegral!float); 354 } 355 356 /** 357 * Determines whether $(D_PARAM T) is a numeric (floating point, integral or 358 * complex) type. 359 * 360 * Params: 361 * T = A type. 362 * 363 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a numeric type, 364 * $(D_KEYWORD false) otherwise. 365 * 366 * See_Also: $(D_PSYMBOL isIntegral!T), 367 * $(D_PSYMBOL isFloatingPoint), 368 * $(D_PSYMBOL isComplex). 369 */ 370 enum bool isNumeric(T) = isIntegral!T || isFloatingPoint!T || isComplex!T; 371 372 /// 373 @nogc nothrow pure @safe unittest 374 { 375 alias F = float; 376 static assert(isNumeric!F); 377 static assert(!isNumeric!bool); 378 static assert(!isNumeric!char); 379 static assert(!isNumeric!wchar); 380 } 381 382 /** 383 * Determines whether $(D_PARAM T) is a boolean type, i.e. $(D_KEYWORD bool). 384 * 385 * Params: 386 * T = A type. 387 * 388 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a boolean type, 389 * $(D_KEYWORD false) otherwise. 390 */ 391 enum bool isBoolean(T) = is(Unqual!(OriginalType!T) == bool); 392 393 /// 394 @nogc nothrow pure @safe unittest 395 { 396 static assert(isBoolean!bool); 397 static assert(isBoolean!(shared const bool)); 398 static assert(!isBoolean!(ubyte)); 399 static assert(!isBoolean!(byte)); 400 401 enum E : bool 402 { 403 t = true, 404 f = false, 405 } 406 static assert(isBoolean!E); 407 408 static struct S1 409 { 410 bool b; 411 alias b this; 412 } 413 static assert(!isBoolean!S1); 414 415 static struct S2 416 { 417 bool opCast(T : bool)() 418 { 419 return true; 420 } 421 } 422 static assert(!isBoolean!S2); 423 } 424 425 /** 426 * Determines whether $(D_PARAM T) is a character type. 427 * 428 * Character types are: 429 * 430 * $(UL 431 * $(LI char) 432 * $(LI wchar) 433 * $(LI dchar) 434 * ) 435 * 436 * Params: 437 * T = A type. 438 * 439 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a character type, 440 * $(D_KEYWORD false) otherwise. 441 */ 442 enum bool isSomeChar(T) = is(Unqual!(OriginalType!T) == char) 443 || is(Unqual!(OriginalType!T) == wchar) 444 || is(Unqual!(OriginalType!T) == dchar); 445 446 /// 447 @nogc nothrow pure @safe unittest 448 { 449 static assert(isSomeChar!char); 450 static assert(isSomeChar!wchar); 451 static assert(isSomeChar!dchar); 452 453 static assert(!isSomeChar!byte); 454 static assert(!isSomeChar!ubyte); 455 static assert(!isSomeChar!short); 456 static assert(!isSomeChar!ushort); 457 static assert(!isSomeChar!int); 458 static assert(!isSomeChar!uint); 459 } 460 461 /** 462 * Determines whether $(D_PARAM T) is a scalar type. 463 * 464 * Scalar types are numbers, booleans and characters. 465 * 466 * Params: 467 * T = A type. 468 * 469 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a scalar type, 470 * $(D_KEYWORD false) otherwise. 471 * 472 * See_Also: $(D_PSYMBOL isNumeric), 473 * $(D_PSYMBOL isBoolean), 474 * $(D_PSYMBOL isSomeChar). 475 */ 476 enum bool isScalarType(T) = isNumeric!T || isBoolean!T || isSomeChar!T; 477 478 /// 479 @nogc nothrow pure @safe unittest 480 { 481 static assert(isScalarType!int); 482 static assert(!isScalarType!(int[])); 483 } 484 485 /** 486 * Determines whether $(D_PARAM T) is a basic type. 487 * 488 * Basic types are scalar types and $(D_KEYWORD void). 489 * 490 * Params: 491 * T = A type. 492 * 493 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a basic type, 494 * $(D_KEYWORD false) otherwise. 495 * 496 * See_Also: $(D_PSYMBOL isScalarType). 497 */ 498 enum bool isBasicType(T) = isScalarType!T || is(T : void); 499 500 /// 501 @nogc nothrow pure @safe unittest 502 { 503 static struct S 504 { 505 } 506 class C 507 { 508 } 509 enum E : int 510 { 511 i = 0, 512 } 513 514 static assert(isBasicType!void); 515 static assert(isBasicType!(shared void)); 516 static assert(isBasicType!E); 517 static assert(!isBasicType!(int*)); 518 static assert(!isBasicType!(void function())); 519 static assert(!isBasicType!C); 520 } 521 522 /** 523 * Determines whether $(D_PARAM T) is a pointer type. 524 * 525 * Params: 526 * T = A type. 527 * 528 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a pointer type, 529 * $(D_KEYWORD false) otherwise. 530 */ 531 template isPointer(T) 532 { 533 static if (is(T U : U*)) 534 { 535 enum bool isPointer = !is(Unqual!(OriginalType!T) == typeof(null)); 536 } 537 else 538 { 539 enum bool isPointer = false; 540 } 541 } 542 543 /// 544 @nogc nothrow pure @safe unittest 545 { 546 static assert(isPointer!(bool*)); 547 static assert(isPointer!(const bool*)); 548 static assert(isPointer!(const shared bool*)); 549 static assert(!isPointer!bool); 550 } 551 552 /** 553 * Determines whether $(D_PARAM T) is an array type (dynamic or static, but 554 * not an associative one). 555 * 556 * Params: 557 * T = A type. 558 * 559 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an array type, 560 * $(D_KEYWORD false) otherwise. 561 * 562 * See_Also: $(D_PSYMBOL isAssociativeArray). 563 */ 564 template isArray(T) 565 { 566 static if (is(T U : U[])) 567 { 568 enum bool isArray = true; 569 } 570 else 571 { 572 enum bool isArray = false; 573 } 574 } 575 576 /// 577 @nogc nothrow pure @safe unittest 578 { 579 static assert(isArray!(bool[])); 580 static assert(isArray!(const bool[])); 581 static assert(isArray!(shared bool[])); 582 static assert(isArray!(bool[8])); 583 static assert(!isArray!bool); 584 static assert(!isArray!(bool[string])); 585 } 586 587 /** 588 * Determines whether $(D_PARAM T) is a static array type. 589 * 590 * Params: 591 * T = A type. 592 * 593 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a static array type, 594 * $(D_KEYWORD false) otherwise. 595 * 596 * See_Also: $(D_PSYMBOL isArray). 597 */ 598 template isStaticArray(T) 599 { 600 static if (is(T U : U[L], size_t L)) 601 { 602 enum bool isStaticArray = true; 603 } 604 else 605 { 606 enum bool isStaticArray = false; 607 } 608 } 609 610 /// 611 @nogc nothrow pure @safe unittest 612 { 613 static assert(isStaticArray!(bool[8])); 614 static assert(isStaticArray!(const bool[8])); 615 static assert(isStaticArray!(shared bool[8])); 616 static assert(!isStaticArray!(bool[])); 617 static assert(!isStaticArray!bool); 618 static assert(!isStaticArray!(bool[string])); 619 } 620 621 /** 622 * Determines whether $(D_PARAM T) is a dynamic array type. 623 * 624 * Params: 625 * T = A type. 626 * 627 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a dynamic array type, 628 * $(D_KEYWORD false) otherwise. 629 * 630 * See_Also: $(D_PSYMBOL isArray). 631 */ 632 enum bool isDynamicArray(T) = isArray!T && !isStaticArray!T; 633 634 /// 635 @nogc nothrow pure @safe unittest 636 { 637 static assert(isDynamicArray!(bool[])); 638 static assert(isDynamicArray!(const bool[])); 639 static assert(isDynamicArray!(shared bool[])); 640 static assert(!isDynamicArray!(bool[8])); 641 static assert(!isDynamicArray!bool); 642 static assert(!isDynamicArray!(bool[string])); 643 } 644 645 /** 646 * Determines whether $(D_PARAM T) is an associative array type. 647 * 648 * Params: 649 * T = A type. 650 * 651 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an associative array type, 652 * $(D_KEYWORD false) otherwise. 653 * 654 * See_Also: $(D_PSYMBOL isArray). 655 */ 656 template isAssociativeArray(T) 657 { 658 static if (is(T U : U[L], L)) 659 { 660 enum bool isAssociativeArray = true; 661 } 662 else 663 { 664 enum bool isAssociativeArray = false; 665 } 666 } 667 668 /// 669 @nogc nothrow pure @safe unittest 670 { 671 static assert(isAssociativeArray!(bool[string])); 672 static assert(isAssociativeArray!(const bool[string])); 673 static assert(isAssociativeArray!(shared const bool[string])); 674 static assert(!isAssociativeArray!(bool[])); 675 static assert(!isAssociativeArray!(bool[8])); 676 static assert(!isAssociativeArray!bool); 677 } 678 679 /** 680 * Determines whether $(D_PARAM T) is a built-in type. 681 * 682 * Built-in types are all basic types and arrays. 683 * 684 * Params: 685 * T = A type. 686 * 687 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a built-in type, 688 * $(D_KEYWORD false) otherwise. 689 * 690 * See_Also: $(D_PSYMBOL isBasicType!T), 691 * $(D_PSYMBOL isArray), 692 * $(D_PSYMBOL isAssociativeArray). 693 */ 694 enum bool isBuiltinType(T) = isBasicType!T 695 || isArray!T 696 || isAssociativeArray!T; 697 698 /// 699 @nogc nothrow pure @safe unittest 700 { 701 static assert(isBuiltinType!int); 702 static assert(isBuiltinType!(int[])); 703 static assert(isBuiltinType!(int[int])); 704 static assert(!isBuiltinType!(int*)); 705 } 706 707 /** 708 * Determines whether $(D_PARAM T) is an aggregate type. 709 * 710 * Aggregate types are: 711 * 712 * $(UL 713 * $(LI $(D_KEYWORD struct)s) 714 * $(LI $(D_KEYWORD class)es) 715 * $(LI $(D_KEYWORD interface)s) 716 * $(LI $(D_KEYWORD union)s) 717 * ) 718 * 719 * Params: 720 * T = A type. 721 * 722 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an aggregate type, 723 * $(D_KEYWORD false) otherwise. 724 */ 725 enum bool isAggregateType(T) = is(T == struct) 726 || is(T == class) 727 || is(T == interface) 728 || is(T == union); 729 730 /// 731 @nogc nothrow pure @safe unittest 732 { 733 static struct S; 734 class C; 735 interface I; 736 union U; 737 enum E; 738 739 static assert(isAggregateType!S); 740 static assert(isAggregateType!C); 741 static assert(isAggregateType!I); 742 static assert(isAggregateType!U); 743 static assert(!isAggregateType!E); 744 static assert(!isAggregateType!void); 745 } 746 747 /** 748 * Determines whether $(D_PARAM T) is a narrow string, i.e. consists of 749 * $(D_KEYWORD char) or $(D_KEYWORD wchar). 750 * 751 * The character type of the string can be qualified with $(D_KEYWORD const), 752 * $(D_KEYWORD immutable) or $(D_KEYWORD inout), but an occurrence of 753 * $(D_KEYWORD shared) in the character type results in returning 754 * $(D_KEYWORD false). 755 * The string itself (in contrast to its character type) can have any type 756 * qualifiers. 757 * 758 * Static $(D_KEYWORD char) and $(D_KEYWORD wchar) arrays are not considered 759 * strings. 760 * 761 * Params: 762 * T = A Type. 763 * 764 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a narrow string, 765 * $(D_KEYWORD false) otherwise. 766 * 767 * See_Also: $(D_PSYMBOL isWideString). 768 */ 769 enum bool isNarrowString(T) = (is(T : const char[]) || is (T : const wchar[])) 770 && !isStaticArray!T; 771 772 /// 773 @nogc nothrow pure @safe unittest 774 { 775 static assert(isNarrowString!(char[])); 776 static assert(isNarrowString!(wchar[])); 777 static assert(!isNarrowString!(dchar[])); 778 779 static assert(isNarrowString!string); 780 static assert(isNarrowString!wstring); 781 static assert(!isNarrowString!dstring); 782 783 static assert(isNarrowString!(const string)); 784 static assert(isNarrowString!(const wstring)); 785 static assert(!isNarrowString!(const dstring)); 786 787 static assert(isNarrowString!(shared string)); 788 static assert(isNarrowString!(shared wstring)); 789 static assert(!isNarrowString!(shared dstring)); 790 791 static assert(isNarrowString!(const(char)[])); 792 static assert(isNarrowString!(inout(char)[])); 793 static assert(!isNarrowString!(shared(const(char))[])); 794 static assert(!isNarrowString!(shared(char)[])); 795 static assert(!isNarrowString!(char[10])); 796 } 797 798 /** 799 * Determines whether $(D_PARAM T) is a string, i.e. consists of 800 * $(D_KEYWORD char), $(D_KEYWORD wchar) or $(D_KEYWORD dchar). 801 * 802 * The character type of the string can be qualified with $(D_KEYWORD const), 803 * $(D_KEYWORD immutable) or $(D_KEYWORD inout), but an occurrence of 804 * $(D_KEYWORD shared) in the character type results in returning 805 * $(D_KEYWORD false). 806 * The string itself (in contrast to its character type) can have any type 807 * qualifiers. 808 * 809 * Static character arrays are not considered strings. 810 * 811 * Params: 812 * T = A Type. 813 * 814 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a string, 815 * $(D_KEYWORD false) otherwise. 816 * 817 * See_Also: $(D_PSYMBOL isNarrowString), $(D_PSYMBOL isWideString). 818 */ 819 enum bool isSomeString(T) = isNarrowString!T || isWideString!T; 820 821 /// 822 @nogc nothrow pure @safe unittest 823 { 824 static assert(isSomeString!(dchar[])); 825 static assert(isSomeString!(char[])); 826 static assert(isSomeString!(wchar[])); 827 828 static assert(isSomeString!dstring); 829 static assert(isSomeString!string); 830 static assert(isSomeString!wstring); 831 832 static assert(isSomeString!(const dstring)); 833 static assert(isSomeString!(const string)); 834 static assert(isSomeString!(const wstring)); 835 836 static assert(isSomeString!(shared dstring)); 837 static assert(isSomeString!(shared string)); 838 static assert(isSomeString!(shared wstring)); 839 840 static assert(isSomeString!(const(char)[])); 841 static assert(isSomeString!(inout(char)[])); 842 static assert(!isSomeString!(shared(const(char))[])); 843 static assert(!isSomeString!(shared(char)[])); 844 static assert(!isSomeString!(char[10])); 845 } 846 847 /** 848 * Returns the minimum value of type $(D_PARAM T). In contrast to 849 * $(D_INLINECODE T.min) this template works with floating point and complex 850 * types as well. 851 * 852 * Params: 853 * T = Integral, boolean, floating point, complex or character type. 854 * 855 * Returns: The minimum value of $(D_PARAM T). 856 * 857 * See_Also: $(D_PSYMBOL isIntegral), 858 * $(D_PSYMBOL isBoolean), 859 * $(D_PSYMBOL isSomeChar), 860 * $(D_PSYMBOL isFloatingPoint), 861 * $(D_PSYMBOL isComplex). 862 */ 863 template mostNegative(T) 864 { 865 static if (isIntegral!T || isBoolean!T || isSomeChar!T) 866 { 867 enum T mostNegative = T.min; 868 } 869 else static if (isFloatingPoint!T || isComplex!T) 870 { 871 enum T mostNegative = -T.max; 872 } 873 else 874 { 875 static assert(false, T.stringof ~ " doesn't have the minimum value"); 876 } 877 } 878 879 /// 880 @nogc nothrow pure @safe unittest 881 { 882 static assert(mostNegative!char == char.min); 883 static assert(mostNegative!wchar == wchar.min); 884 static assert(mostNegative!dchar == dchar.min); 885 886 static assert(mostNegative!byte == byte.min); 887 static assert(mostNegative!ubyte == ubyte.min); 888 static assert(mostNegative!bool == bool.min); 889 890 static assert(mostNegative!float == -float.max); 891 static assert(mostNegative!double == -double.max); 892 static assert(mostNegative!real == -real.max); 893 894 static assert(mostNegative!ifloat == -ifloat.max); 895 static assert(mostNegative!cfloat == -cfloat.max); 896 } 897 898 /** 899 * Determines whether the type $(D_PARAM T) is copyable. 900 * 901 * Only structs can be not copyable if their postblit constructor or the 902 * postblit constructor of one of its fields is disabled, i.e. annotated with 903 * $(D_KEYWORD @disable). 904 * 905 * Params: 906 * T = A type. 907 * 908 * Returns: $(D_PARAM true) if $(D_PARAM T) can be copied, 909 * $(D_PARAM false) otherwise. 910 */ 911 enum bool isCopyable(T) = is(typeof({ T s1 = T.init; T s2 = s1; })); 912 913 /// 914 @nogc nothrow pure @safe unittest 915 { 916 static struct S1 917 { 918 } 919 static struct S2 920 { 921 this(this) 922 { 923 } 924 } 925 static struct S3 926 { 927 @disable this(this); 928 } 929 static struct S4 930 { 931 S3 s; 932 } 933 class C 934 { 935 } 936 937 static assert(isCopyable!S1); 938 static assert(isCopyable!S2); 939 static assert(!isCopyable!S3); 940 static assert(!isCopyable!S4); 941 942 static assert(isCopyable!C); 943 static assert(isCopyable!bool); 944 } 945 946 /** 947 * Determines whether $(D_PARAM T) is an abstract class. 948 * 949 * Abstract class is a class marked as such or a class that has any abstract 950 * methods or doesn't implement all methods of abstract base classes. 951 * 952 * Params: 953 * T = A type. 954 * 955 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an abstract class, 956 * $(D_KEYWORD false) otherwise. 957 * 958 * See_Also: $(D_PSYMBOL isAbstractFunction). 959 */ 960 enum bool isAbstractClass(T) = __traits(isAbstractClass, T); 961 962 /// 963 @nogc nothrow pure @safe unittest 964 { 965 class A 966 { 967 } 968 abstract class B 969 { 970 } 971 class C 972 { 973 abstract void func(); 974 } 975 class D : C 976 { 977 } 978 class E : C 979 { 980 override void func() 981 { 982 } 983 } 984 static assert(!isAbstractClass!A); 985 static assert(isAbstractClass!B); 986 static assert(isAbstractClass!C); 987 static assert(isAbstractClass!D); 988 static assert(!isAbstractClass!E); 989 } 990 991 /** 992 * Checks whether $(D_PARAM T) is a type, same as `is(T)` does. 993 * 994 * Params: 995 * T = A symbol. 996 * 997 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a type, $(D_KEYWORD false) 998 * otherwise. 999 */ 1000 enum bool isType(alias T) = is(T); 1001 1002 /// ditto 1003 enum bool isType(T) = true; 1004 1005 /** 1006 * Determines whether $(D_PARAM Args) contains only types. 1007 * 1008 * Params: 1009 * Args = Alias sequence. 1010 * 1011 * Returns: $(D_KEYWORD true) if $(D_PARAM Args) consists only of types, 1012 * $(D_KEYWORD false) otherwise. 1013 */ 1014 enum bool isTypeTuple(Args...) = allSatisfy!(isType, Args); 1015 1016 /// 1017 @nogc nothrow pure @safe unittest 1018 { 1019 static assert(isTypeTuple!(int, uint, Object)); 1020 static assert(isTypeTuple!()); 1021 static assert(!isTypeTuple!(int, 8, Object)); 1022 static assert(!isTypeTuple!(5, 8, 2)); 1023 1024 class C 1025 { 1026 } 1027 enum E : bool 1028 { 1029 t, 1030 f, 1031 } 1032 union U 1033 { 1034 } 1035 static struct T() 1036 { 1037 } 1038 1039 static assert(isTypeTuple!C); 1040 static assert(isTypeTuple!E); 1041 static assert(isTypeTuple!U); 1042 static assert(isTypeTuple!void); 1043 static assert(isTypeTuple!int); 1044 static assert(!isTypeTuple!T); 1045 static assert(isTypeTuple!(T!())); 1046 static assert(!isTypeTuple!5); 1047 static assert(!isTypeTuple!(tanya.meta.trait)); 1048 } 1049 1050 /** 1051 * Tells whether $(D_PARAM Args) contains only expressions. 1052 * 1053 * An expression is determined by applying $(D_KEYWORD typeof) to an argument: 1054 * 1055 * --- 1056 * static if (is(typeof(Args[i]))) 1057 * { 1058 * // Args[i] is an expression. 1059 * } 1060 * else 1061 * { 1062 * // Args[i] is not an expression. 1063 * } 1064 * --- 1065 * 1066 * Params: 1067 * Args = Alias sequence. 1068 * 1069 * Returns: $(D_KEYWORD true) if $(D_PARAM Args) consists only of expressions, 1070 * $(D_KEYWORD false) otherwise. 1071 */ 1072 template isExpressions(Args...) 1073 { 1074 static if (Args.length == 0) 1075 { 1076 enum bool isExpressions = true; 1077 } 1078 else static if (is(typeof(Args[0]) U)) 1079 { 1080 enum bool isExpressions = !is(U == void) 1081 && isExpressions!(Args[1 .. $]); 1082 } 1083 else 1084 { 1085 enum bool isExpressions = false; 1086 } 1087 } 1088 1089 /// 1090 @nogc nothrow pure @safe unittest 1091 { 1092 static assert(isExpressions!(5, 8, 2)); 1093 static assert(isExpressions!()); 1094 static assert(!isExpressions!(int, uint, Object)); 1095 static assert(!isExpressions!(int, 8, Object)); 1096 1097 template T(U) 1098 { 1099 } 1100 static assert(!isExpressions!T); 1101 } 1102 1103 /** 1104 * Determines whether $(D_PARAM T) is a final class. 1105 * 1106 * Params: 1107 * T = A type. 1108 * 1109 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a final class, 1110 * $(D_KEYWORD false) otherwise. 1111 * 1112 * See_Also: $(D_PSYMBOL isFinalFunction). 1113 */ 1114 enum bool isFinalClass(T) = __traits(isFinalClass, T); 1115 1116 /// 1117 @nogc nothrow pure @safe unittest 1118 { 1119 final class A 1120 { 1121 } 1122 class B 1123 { 1124 } 1125 1126 static assert(isFinalClass!A); 1127 static assert(!isFinalClass!B); 1128 } 1129 1130 /** 1131 * Determines whether $(D_PARAM T) is an abstract method. 1132 * 1133 * Params: 1134 * F = A symbol. 1135 * 1136 * Returns: $(D_KEYWORD true) if $(D_PARAM F) is an abstract method, 1137 * $(D_KEYWORD false) otherwise. 1138 * 1139 * See_Also: $(D_PSYMBOL isAbstractClass). 1140 */ 1141 enum bool isAbstractFunction(alias F) = __traits(isAbstractFunction, F); 1142 1143 /// 1144 @nogc nothrow pure @safe unittest 1145 { 1146 class A 1147 { 1148 void func() 1149 { 1150 } 1151 } 1152 class B 1153 { 1154 abstract void func(); 1155 } 1156 class C : B 1157 { 1158 override void func() 1159 { 1160 } 1161 } 1162 static assert(!isAbstractFunction!(A.func)); 1163 static assert(isAbstractFunction!(B.func)); 1164 static assert(!isAbstractFunction!(C.func)); 1165 } 1166 1167 /** 1168 * Determines whether $(D_PARAM T) is a final method. 1169 * 1170 * Params: 1171 * F = A symbol. 1172 * 1173 * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a final method, 1174 * $(D_KEYWORD false) otherwise. 1175 * 1176 * See_Also: $(D_PSYMBOL isFinalClass). 1177 */ 1178 enum bool isFinalFunction(alias F) = __traits(isFinalFunction, F); 1179 1180 /// 1181 @nogc nothrow pure @safe unittest 1182 { 1183 class A 1184 { 1185 void virtualFunc() 1186 { 1187 } 1188 final void finalFunc() 1189 { 1190 } 1191 } 1192 1193 static assert(isFinalFunction!(A.finalFunc)); 1194 static assert(!isFinalFunction!(A.virtualFunc)); 1195 } 1196 1197 /** 1198 * Function pointer is a pointer to a function. So a simple function is not 1199 * a function pointer, but getting the address of such function returns a 1200 * function pointer. 1201 * 1202 * A function pointer doesn't save the context pointer, thus cannot have access 1203 * to its outer scope. 1204 * 1205 * Params: 1206 * F = A symbol. 1207 * 1208 * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a function pointer, 1209 * $(D_KEYWORD false) otherwise. 1210 * 1211 * See_Also: $(LINK2 http://dlang.org/spec/function.html#closures, 1212 * Delegates, Function Pointers, and Closures). 1213 */ 1214 template isFunctionPointer(F...) 1215 if (F.length == 1) 1216 { 1217 static if ((is(typeof(F[0]) T : T*) && is(T == function)) 1218 || (is(F[0] T : T*) && is(T == function))) 1219 { 1220 enum bool isFunctionPointer = true; 1221 } 1222 else 1223 { 1224 enum bool isFunctionPointer = false; 1225 } 1226 } 1227 1228 /// 1229 @nogc nothrow pure @safe unittest 1230 { 1231 static assert(isFunctionPointer!(void function())); 1232 static assert(!isFunctionPointer!(void delegate())); 1233 1234 static assert(isFunctionPointer!(() {})); 1235 1236 void func() 1237 { 1238 } 1239 static void staticFunc() 1240 { 1241 } 1242 interface I 1243 { 1244 @property int prop(); 1245 } 1246 1247 static assert(!isFunctionPointer!func); 1248 static assert(!isFunctionPointer!staticFunc); 1249 1250 auto functionPointer = &staticFunc; 1251 auto dg = &func; 1252 1253 static assert(isFunctionPointer!functionPointer); 1254 static assert(!isFunctionPointer!dg); 1255 1256 static assert(!isFunctionPointer!(I.prop)); 1257 } 1258 1259 /** 1260 * Delegate stores the function pointer and function context. 1261 * 1262 * Params: 1263 * F = A symbol. 1264 * 1265 * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a delegate, 1266 * $(D_KEYWORD false) delegate. 1267 * 1268 * See_Also: $(LINK2 http://dlang.org/spec/function.html#closures, 1269 * Delegates, Function Pointers, and Closures). 1270 */ 1271 template isDelegate(F...) 1272 if (F.length == 1) 1273 { 1274 static if (is(F[0] == delegate) 1275 || is(typeof(F[0]) == delegate)) 1276 { 1277 enum bool isDelegate = true; 1278 } 1279 else 1280 { 1281 enum bool isDelegate = false; 1282 } 1283 } 1284 1285 /// 1286 @nogc nothrow pure @safe unittest 1287 { 1288 static assert(isDelegate!(void delegate())); 1289 static assert(!isDelegate!(void function())); 1290 1291 static assert(!isDelegate!(() {})); 1292 1293 void func() 1294 { 1295 } 1296 static void staticFunc() 1297 { 1298 } 1299 interface I 1300 { 1301 @property int prop(); 1302 } 1303 1304 static assert(!isDelegate!func); 1305 static assert(!isDelegate!staticFunc); 1306 1307 auto functionPointer = &staticFunc; 1308 auto dg = &func; 1309 1310 static assert(!isDelegate!functionPointer); 1311 static assert(isDelegate!dg); 1312 1313 static assert(!isDelegate!(I.prop)); 1314 } 1315 1316 /** 1317 * $(D_PSYMBOL isFunction) returns $(D_KEYWORD true) only for plain functions, 1318 * not function pointers or delegates. Use $(D_PSYMBOL isFunctionPointer) or 1319 * $(D_PSYMBOL isDelegate) to detect them or $(D_PSYMBOL isSomeFunction) 1320 * for detecting a function of any type. 1321 * 1322 * Params: 1323 * F = A symbol. 1324 * 1325 * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a function, 1326 * $(D_KEYWORD false) otherwise. 1327 * 1328 * See_Also: $(LINK2 http://dlang.org/spec/function.html#closures, 1329 * Delegates, Function Pointers, and Closures). 1330 */ 1331 template isFunction(F...) 1332 if (F.length == 1) 1333 { 1334 static if (is(F[0] == function) 1335 || is(typeof(&F[0]) T == delegate) 1336 || (is(typeof(&F[0]) T : T*) && is(T == function))) 1337 { 1338 enum bool isFunction = true; 1339 } 1340 else 1341 { 1342 enum bool isFunction = false; 1343 } 1344 } 1345 1346 /// 1347 @nogc nothrow pure @safe unittest 1348 { 1349 static assert(!isFunction!(void function())); 1350 static assert(!isFunction!(() {})); 1351 static assert(!isFunction!(void delegate())); 1352 1353 void func() 1354 { 1355 } 1356 static void staticFunc() 1357 { 1358 } 1359 interface I 1360 { 1361 @property int prop(); 1362 } 1363 1364 static assert(isFunction!func); 1365 static assert(isFunction!staticFunc); 1366 1367 auto functionPointer = &staticFunc; 1368 auto dg = &func; 1369 1370 static assert(!isFunction!functionPointer); 1371 static assert(!isFunction!dg); 1372 1373 static assert(isFunction!(I.prop)); 1374 } 1375 1376 /** 1377 * Params: 1378 * F = A symbol. 1379 * 1380 * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a function, function pointer 1381 * or delegate, $(D_KEYWORD false) otherwise. 1382 * 1383 * See_Also: $(D_PSYMBOL isFunction), 1384 * $(D_PSYMBOL isDelegate), 1385 * $(D_PSYMBOL isFunctionPointer). 1386 */ 1387 template isSomeFunction(F...) 1388 if (F.length == 1) 1389 { 1390 enum bool isSomeFunction = isFunctionPointer!F 1391 || isFunction!F 1392 || isDelegate!F; 1393 } 1394 1395 /// 1396 @nogc nothrow pure @safe unittest 1397 { 1398 static assert(isSomeFunction!(void function())); 1399 static assert(isSomeFunction!(() {})); 1400 static assert(isSomeFunction!(void delegate())); 1401 1402 void func() 1403 { 1404 } 1405 static void staticFunc() 1406 { 1407 } 1408 1409 static assert(isSomeFunction!func); 1410 static assert(isSomeFunction!staticFunc); 1411 1412 auto functionPointer = &staticFunc; 1413 auto dg = &func; 1414 1415 static assert(isSomeFunction!functionPointer); 1416 static assert(isSomeFunction!dg); 1417 1418 static assert(!isSomeFunction!int); 1419 } 1420 1421 /** 1422 * Params: 1423 * F = A symbol. 1424 * 1425 * Returns: $(D_KEYWORD true) if $(D_PARAM F) is callable, 1426 * $(D_KEYWORD false) otherwise. 1427 */ 1428 template isCallable(F...) 1429 if (F.length == 1) 1430 { 1431 static if (isSomeFunction!F 1432 || (is(typeof(F[0].opCall)) && isFunction!(F[0].opCall))) 1433 { 1434 enum bool isCallable = true; 1435 } 1436 else 1437 { 1438 enum bool isCallable = false; 1439 } 1440 } 1441 1442 /// 1443 @nogc nothrow pure @safe unittest 1444 { 1445 static struct S 1446 { 1447 void opCall() 1448 { 1449 } 1450 } 1451 class C 1452 { 1453 static void opCall() 1454 { 1455 } 1456 } 1457 interface I 1458 { 1459 } 1460 S s; 1461 1462 static assert(isCallable!s); 1463 static assert(isCallable!C); 1464 static assert(isCallable!S); 1465 static assert(!isCallable!I); 1466 } 1467 1468 /** 1469 * Determines whether $(D_PARAM T) defines a symbol $(D_PARAM member). 1470 * 1471 * Params: 1472 * T = Aggregate type. 1473 * member = Symbol name. 1474 * 1475 * Returns: $(D_KEYWORD true) if $(D_PARAM T) defines a symbol 1476 * $(D_PARAM member), $(D_KEYWORD false) otherwise. 1477 */ 1478 enum bool hasMember(T, string member) = __traits(hasMember, T, member); 1479 1480 /// 1481 @nogc nothrow pure @safe unittest 1482 { 1483 static struct S 1484 { 1485 int member1; 1486 void member2() 1487 { 1488 } 1489 static int member3; 1490 static void member4() 1491 { 1492 } 1493 } 1494 static assert(hasMember!(S, "member1")); 1495 static assert(hasMember!(S, "member2")); 1496 static assert(hasMember!(S, "member3")); 1497 static assert(hasMember!(S, "member4")); 1498 static assert(!hasMember!(S, "member6")); 1499 } 1500 1501 /** 1502 * Determines whether $(D_PARAM T) is mutable, i.e. has one of the following 1503 * qualifiers or a combination of them: 1504 * 1505 * $(UL 1506 * $(LI $(D_KEYWORD const)) 1507 * $(LI $(D_KEYWORD immutable)) 1508 * $(LI $(D_KEYWORD const)) 1509 * ) 1510 * 1511 * Params: 1512 * T = A type. 1513 * 1514 * Returns: $(D_KEYWORD true) if $(D_PARAM T) is mutable, 1515 * $(D_KEYWORD false) otherwise. 1516 */ 1517 template isMutable(T) 1518 { 1519 static if (is(T U == const U) 1520 || is(T U == inout U) 1521 || is(T U == inout const U) 1522 || is(T U == immutable U) 1523 || is(T U == shared const U) 1524 || is(T U == shared inout U) 1525 || is(T U == shared inout const U)) 1526 { 1527 enum bool isMutable = false; 1528 } 1529 else 1530 { 1531 enum bool isMutable = true; 1532 } 1533 } 1534 1535 /// 1536 @nogc nothrow pure @safe unittest 1537 { 1538 static struct S 1539 { 1540 void method() 1541 { 1542 static assert(isMutable!(typeof(this))); 1543 } 1544 1545 void method() inout 1546 { 1547 static assert(!isMutable!(typeof(this))); 1548 } 1549 1550 void immMethod() const 1551 { 1552 static assert(!isMutable!(typeof(this))); 1553 } 1554 void immMethod() immutable 1555 { 1556 static assert(!isMutable!(typeof(this))); 1557 } 1558 } 1559 } 1560 1561 /** 1562 * Determines whether $(D_PARAM T) is a nested type, i.e. $(D_KEYWORD class), 1563 * $(D_KEYWORD struct) or $(D_KEYWORD union), which internally stores a context 1564 * pointer. 1565 * 1566 * Params: 1567 * T = $(D_KEYWORD class), $(D_KEYWORD struct) or $(D_KEYWORD union) type. 1568 * 1569 * Returns: $(D_KEYWORD true) if the argument is a nested type which internally 1570 * stores a context pointer, $(D_KEYWORD false) otherwise. 1571 */ 1572 template isNested(T) 1573 if (is(T == class) || is(T == struct) || is(T == union)) 1574 { 1575 enum bool isNested = __traits(isNested, T); 1576 } 1577 1578 /// 1579 @nogc pure nothrow @safe unittest 1580 { 1581 static struct S 1582 { 1583 } 1584 static assert(!isNested!S); 1585 1586 class C 1587 { 1588 void method() 1589 { 1590 } 1591 } 1592 static assert(isNested!C); 1593 } 1594 1595 /** 1596 * Determines whether $(D_PARAM T) is a nested function. 1597 * 1598 * Params: 1599 * F = A function. 1600 * 1601 * Returns $(D_KEYWORD true) if the $(D_PARAM T) is a nested function, 1602 * $(D_KEYWORD false) otherwise. 1603 */ 1604 enum bool isNestedFunction(alias F) = __traits(isNested, F); 1605 1606 /// 1607 @nogc nothrow pure @safe unittest 1608 { 1609 void func() 1610 { 1611 void nestedFunc() 1612 { 1613 } 1614 static assert(isNestedFunction!nestedFunc); 1615 } 1616 } 1617 1618 /** 1619 * Determines the type of the callable $(D_PARAM F). 1620 * 1621 * Params: 1622 * F = A function. 1623 * 1624 * Returns: Type of the function $(D_PARAM F). 1625 */ 1626 template FunctionTypeOf(F...) 1627 if (isCallable!F) 1628 { 1629 static if ((is(typeof(F[0]) T : T*) && is(T == function)) 1630 || (is(F[0] T : T*) && is(T == function)) 1631 || is(F[0] T == delegate) 1632 || is(typeof(F[0]) T == delegate) 1633 || is(F[0] T == function) 1634 || is(typeof(&F[0]) T == delegate) 1635 || (is(typeof(&F[0]) T : T*) && is(T == function))) 1636 { 1637 alias FunctionTypeOf = T; 1638 } 1639 else 1640 { 1641 alias FunctionTypeOf = FunctionTypeOf!(F[0].opCall); 1642 } 1643 } 1644 1645 /// 1646 @nogc nothrow pure @safe unittest 1647 { 1648 static assert(is(FunctionTypeOf!(void function()) == function)); 1649 static assert(is(FunctionTypeOf!(() {}) == function)); 1650 } 1651 1652 /** 1653 * Determines the return type of the callable $(D_PARAM F). 1654 * 1655 * Params: 1656 * F = A callable object. 1657 * 1658 * Returns: Return type of $(D_PARAM F). 1659 */ 1660 template ReturnType(F...) 1661 if (isCallable!F) 1662 { 1663 static if (is(FunctionTypeOf!(F[0]) T == return)) 1664 { 1665 alias ReturnType = T; 1666 } 1667 else 1668 { 1669 static assert(false, "Argument is not a callable"); 1670 } 1671 } 1672 1673 /// 1674 @nogc nothrow pure @safe unittest 1675 { 1676 static assert(is(ReturnType!(int delegate()) == int)); 1677 static assert(is(ReturnType!(bool function()) == bool)); 1678 } 1679 1680 /** 1681 * Determines the template $(D_PARAM T) is an instance of. 1682 * 1683 * Params: 1684 * T = Template instance. 1685 * 1686 * Returns: Template $(D_PARAM T) is an instance of. 1687 */ 1688 alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base; 1689 1690 /// 1691 @nogc nothrow pure @safe unittest 1692 { 1693 static struct S(T) 1694 { 1695 } 1696 static assert(__traits(isSame, TemplateOf!(S!int), S)); 1697 1698 static void func(T)() 1699 { 1700 } 1701 static assert(__traits(isSame, TemplateOf!(func!int), func)); 1702 1703 template T(U) 1704 { 1705 } 1706 static assert(__traits(isSame, TemplateOf!(T!int), T)); 1707 } 1708 1709 /** 1710 * Returns the mangled name of the symbol $(D_PARAM T). 1711 * 1712 * Params: 1713 * T = A symbol. 1714 * 1715 * Returns: Mangled name of $(D_PARAM T). 1716 */ 1717 enum string mangledName(T) = T.mangleof; 1718 1719 /// 1720 enum string mangledName(alias T) = T.mangleof; 1721 1722 /** 1723 * Tests whether $(D_PARAM I) is an instance of template $(D_PARAM T). 1724 * 1725 * Params: 1726 * T = Template. 1727 * I = Template instance. 1728 * 1729 * Returns: $(D_KEYWORD true) if $(D_PARAM I) is an instance of $(D_PARAM T), 1730 * $(D_KEYWORD false) otherwise. 1731 */ 1732 enum bool isInstanceOf(alias T, I) = is(I == T!Args, Args...); 1733 1734 template isInstanceOf(alias T, alias I) 1735 { 1736 static if (is(typeof(TemplateOf!I))) 1737 { 1738 enum bool isInstanceOf = __traits(isSame, TemplateOf!I, T); 1739 } 1740 else 1741 { 1742 enum bool isInstanceOf = false; 1743 } 1744 } 1745 1746 /// 1747 @nogc nothrow pure @safe unittest 1748 { 1749 static struct S(T) 1750 { 1751 } 1752 static assert(isInstanceOf!(S, S!int)); 1753 1754 static void func(T)(); 1755 static assert(isInstanceOf!(func, func!int)); 1756 1757 template T(U) 1758 { 1759 } 1760 static assert(isInstanceOf!(T, T!int)); 1761 } 1762 1763 /** 1764 * Checks whether $(D_PARAM From) is implicitly (without explicit 1765 * $(D_KEYWORD cast)) to $(D_PARAM To). 1766 * 1767 * Params: 1768 * From = Source type. 1769 * To = Conversion target type. 1770 * 1771 * Returns: $(D_KEYWORD true) if $(D_PARAM From) is implicitly convertible to 1772 * $(D_PARAM To), $(D_KEYWORD false) if not. 1773 */ 1774 enum bool isImplicitlyConvertible(From, To) = is(From : To); 1775 1776 /// 1777 @nogc nothrow pure @safe unittest 1778 { 1779 static assert(isImplicitlyConvertible!(const(byte), byte)); 1780 static assert(isImplicitlyConvertible!(byte, char)); 1781 static assert(isImplicitlyConvertible!(byte, short)); 1782 static assert(!isImplicitlyConvertible!(short, byte)); 1783 static assert(isImplicitlyConvertible!(string, const(char)[])); 1784 } 1785 1786 /** 1787 * Returns a tuple of base classes and interfaces of $(D_PARAM T). 1788 * 1789 * $(D_PSYMBOL BaseTypeTuple) returns only classes and interfaces $(D_PARAM T) 1790 * directly inherits from, but not the base classes and interfaces of its parents. 1791 * 1792 * Params: 1793 * T = Class or interface type. 1794 * 1795 * Returns: A tuple of base classes or interfaces of ($D_PARAM T). 1796 * 1797 * See_Also: $(D_PSYMBOL TransitiveBaseTypeTuple). 1798 */ 1799 template BaseTypeTuple(T) 1800 if (is(T == class) || (is(T == interface))) 1801 { 1802 static if (is(T Tuple == super)) 1803 { 1804 alias BaseTypeTuple = Tuple; 1805 } 1806 else 1807 { 1808 static assert(false, "Argument isn't a class or interface"); 1809 } 1810 } 1811 1812 /// 1813 @nogc nothrow pure @safe unittest 1814 { 1815 interface I1 1816 { 1817 } 1818 interface I2 1819 { 1820 } 1821 interface I3 : I1, I2 1822 { 1823 } 1824 interface I4 1825 { 1826 } 1827 class A : I3, I4 1828 { 1829 } 1830 static assert(is(BaseTypeTuple!A == AliasSeq!(Object, I3, I4))); 1831 static assert(BaseTypeTuple!Object.length == 0); 1832 } 1833 1834 /** 1835 * Returns a tuple of all base classes and interfaces of $(D_PARAM T). 1836 * 1837 * $(D_PSYMBOL TransitiveBaseTypeTuple) returns first the parent class, then 1838 * grandparent and so on. The last class is $(D_PSYMBOL Object). Then the interfaces 1839 * follow. 1840 * 1841 * Params: 1842 * T = Class or interface type. 1843 * 1844 * Returns: A tuple of all base classes and interfaces of ($D_PARAM T). 1845 * 1846 * See_Also: $(D_PSYMBOL BaseTypeTuple). 1847 */ 1848 template TransitiveBaseTypeTuple(T) 1849 if (is(T == class) || is(T == interface)) 1850 { 1851 private template Impl(T...) 1852 { 1853 static if (T.length == 0) 1854 { 1855 alias Impl = AliasSeq!(); 1856 } 1857 else 1858 { 1859 alias Impl = AliasSeq!(BaseTypeTuple!(T[0]), 1860 Map!(ImplCopy, BaseTypeTuple!(T[0]))); 1861 } 1862 } 1863 private alias ImplCopy = Impl; // To avoid recursive template expansion. 1864 private enum bool cmp(A, B) = is(B == interface) && is(A == class); 1865 1866 alias TransitiveBaseTypeTuple = NoDuplicates!(Sort!(cmp, Impl!T)); 1867 } 1868 1869 /// 1870 @nogc nothrow pure @safe unittest 1871 { 1872 interface I1 1873 { 1874 } 1875 interface I2 : I1 1876 { 1877 } 1878 class A : I2 1879 { 1880 } 1881 class B : A, I1 1882 { 1883 } 1884 class C : B, I2 1885 { 1886 } 1887 alias Expected = AliasSeq!(B, A, Object, I2, I1); 1888 static assert(is(TransitiveBaseTypeTuple!C == Expected)); 1889 1890 static assert(is(TransitiveBaseTypeTuple!Object == AliasSeq!())); 1891 static assert(is(TransitiveBaseTypeTuple!I2 == AliasSeq!(I1))); 1892 } 1893 1894 /** 1895 * Returns all the base classes of $(D_PARAM T), the direct parent class comes 1896 * first, $(D_PSYMBOL Object) ist the last one. 1897 * 1898 * The only type that doesn't have any base class is $(D_PSYMBOL Object). 1899 * 1900 * Params: 1901 * T = Class type. 1902 * 1903 * Returns: Base classes of $(D_PARAM T). 1904 */ 1905 template BaseClassesTuple(T) 1906 if (is(T == class)) 1907 { 1908 static if (is(T == Object)) 1909 { 1910 alias BaseClassesTuple = AliasSeq!(); 1911 } 1912 else 1913 { 1914 private alias Parents = BaseTypeTuple!T; 1915 alias BaseClassesTuple = AliasSeq!(Parents[0], BaseClassesTuple!(Parents[0])); 1916 } 1917 } 1918 1919 /// 1920 @nogc nothrow pure @safe unittest 1921 { 1922 interface I1 1923 { 1924 } 1925 interface I2 1926 { 1927 } 1928 class A : I1, I2 1929 { 1930 } 1931 class B : A, I1 1932 { 1933 } 1934 class C : B, I2 1935 { 1936 } 1937 static assert(is(BaseClassesTuple!C == AliasSeq!(B, A, Object))); 1938 static assert(BaseClassesTuple!Object.length == 0); 1939 } 1940 1941 /** 1942 * Returns all the interfaces $(D_PARAM T) inherits from. 1943 * 1944 * Params: 1945 * T = Class or interface type. 1946 * 1947 * Returns: Interfaces $(D_PARAM T) inherits from. 1948 */ 1949 template InterfacesTuple(T) 1950 if (is(T == class) || is(T == interface)) 1951 { 1952 alias InterfacesTuple = Filter!(isInterface, TransitiveBaseTypeTuple!T); 1953 } 1954 1955 /// 1956 @nogc nothrow pure @safe unittest 1957 { 1958 interface I1 1959 { 1960 } 1961 interface I2 : I1 1962 { 1963 } 1964 class A : I2 1965 { 1966 } 1967 class B : A, I1 1968 { 1969 } 1970 class C : B, I2 1971 { 1972 } 1973 static assert(is(InterfacesTuple!C == AliasSeq!(I2, I1))); 1974 1975 static assert(is(InterfacesTuple!Object == AliasSeq!())); 1976 static assert(is(InterfacesTuple!I1 == AliasSeq!())); 1977 } 1978 1979 /** 1980 * Tests whether a value of type $(D_PARAM Rhs) can be assigned to a variable 1981 * of type $(D_PARAM Lhs). 1982 * 1983 * If $(D_PARAM Rhs) isn't specified, $(D_PSYMBOL isAssignable) tests whether a 1984 * value of type $(D_PARAM Lhs) can be assigned to a variable of the same type. 1985 * 1986 * $(D_PSYMBOL isAssignable) tells whether $(D_PARAM Rhs) can be assigned by 1987 * value as well by reference. 1988 * 1989 * Params: 1990 * Lhs = Variable type. 1991 * Rhs = Expression type. 1992 * 1993 * Returns: $(D_KEYWORD true) if a value of type $(D_PARAM Rhs) can be assigned 1994 * to a variable of type $(D_PARAM Lhs), $(D_KEYWORD false) otherwise. 1995 */ 1996 template isAssignable(Lhs, Rhs = Lhs) 1997 { 1998 enum bool isAssignable = is(typeof({ 1999 Lhs lhs = Lhs.init; 2000 Rhs rhs = Rhs.init; 2001 lhs = ((inout ref Rhs) => Rhs.init)(rhs); 2002 })); 2003 } 2004 2005 /// 2006 @nogc nothrow pure @safe unittest 2007 { 2008 static struct S1 2009 { 2010 @disable this(); 2011 @disable this(this); 2012 } 2013 static struct S2 2014 { 2015 void opAssign(S1 s) pure nothrow @safe @nogc 2016 { 2017 } 2018 } 2019 static struct S3 2020 { 2021 void opAssign(ref S1 s) pure nothrow @safe @nogc 2022 { 2023 } 2024 } 2025 static assert(isAssignable!(S2, S1)); 2026 static assert(!isAssignable!(S3, S1)); 2027 2028 static assert(isAssignable!(const(char)[], string)); 2029 static assert(!isAssignable!(string, char[])); 2030 2031 static assert(isAssignable!int); 2032 static assert(!isAssignable!(const int, int)); 2033 } 2034 2035 /** 2036 * Returns template parameters of $(D_PARAM T). 2037 * 2038 * Params: 2039 * T = Template instance. 2040 * 2041 * Returns: Template parameters of $(D_PARAM T). 2042 */ 2043 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args; 2044 2045 /// 2046 @nogc nothrow pure @safe unittest 2047 { 2048 template T(A, B) 2049 { 2050 } 2051 static assert(is(TemplateArgsOf!(T!(int, uint)) == AliasSeq!(int, uint))); 2052 } 2053 2054 /** 2055 * Returns a tuple with parameter types of a function. 2056 * 2057 * Params: 2058 * F = A function. 2059 * 2060 * Returns: Tuple with parameter types of a function. 2061 */ 2062 template Parameters(F...) 2063 if (isCallable!F) 2064 { 2065 static if (is(FunctionTypeOf!F T == function)) 2066 { 2067 alias Parameters = T; 2068 } 2069 else 2070 { 2071 static assert(false, "Function has no parameters"); 2072 } 2073 } 2074 2075 /// 2076 @nogc nothrow pure @safe unittest 2077 { 2078 int func(Object, uint[]); 2079 static assert(is(Parameters!func == AliasSeq!(Object, uint[]))); 2080 } 2081 2082 /** 2083 * Returns a string array with all parameter names of a function. 2084 * 2085 * If a parameter has no name, an empty string is placed into array. 2086 * 2087 * Params: 2088 * F = A function. 2089 * 2090 * Returns: Function parameter names. 2091 */ 2092 template ParameterIdentifierTuple(F...) 2093 if (isCallable!F) 2094 { 2095 static if (is(FunctionTypeOf!F Params == __parameters)) 2096 { 2097 string[] Impl() 2098 { 2099 string[] tuple; 2100 2101 foreach (k, P; Params) 2102 { 2103 static if (is(typeof(__traits(identifier, Params[k .. $])))) 2104 { 2105 tuple ~= __traits(identifier, Params[k .. $]); 2106 } 2107 else 2108 { 2109 tuple ~= ""; 2110 } 2111 } 2112 2113 return tuple; 2114 } 2115 enum string[] ParameterIdentifierTuple = Impl(); 2116 } 2117 else 2118 { 2119 static assert(false, "Function has no parameters"); 2120 } 2121 } 2122 2123 /// 2124 @nogc nothrow pure @safe unittest 2125 { 2126 int func(ref Object stuff, uint[] = null, scope uint k = 1); 2127 alias P = ParameterIdentifierTuple!func; 2128 static assert(P[0] == "stuff"); 2129 static assert(P[1] == ""); 2130 static assert(P[2] == "k"); 2131 } 2132 2133 /// Attributes can be attached to a function. 2134 enum FunctionAttribute : uint 2135 { 2136 none = 0x0000, 2137 pure_ = 0x0001, 2138 nothrow_ = 0x0002, 2139 ref_ = 0x0004, 2140 property = 0x0008, 2141 trusted = 0x0010, 2142 safe = 0x0020, 2143 nogc = 0x0040, 2144 system = 0x0080, 2145 const_ = 0x0100, 2146 immutable_ = 0x0200, 2147 inout_ = 0x0400, 2148 shared_ = 0x0800, 2149 return_ = 0x1000, 2150 scope_ = 0x2000, 2151 } 2152 2153 /** 2154 * Retrieves the attributes of the function $(D_PARAM F). 2155 * 2156 * The attributes are returned as a bit-mask of 2157 * $(D_PSYMBOL FunctionAttribute) values. 2158 * 2159 * Params: A function. 2160 * 2161 * Returns: Attributes of the function $(D_PARAM F). 2162 * 2163 * See_Also: $(D_PSYMBOL FunctionAttribute). 2164 */ 2165 template functionAttributes(F...) 2166 if (isCallable!F) 2167 { 2168 uint Impl() 2169 { 2170 uint attrs = FunctionAttribute.none; 2171 foreach (a; __traits(getFunctionAttributes, F[0])) 2172 { 2173 static if (a == "const") 2174 { 2175 attrs |= FunctionAttribute.const_; 2176 } 2177 else static if (a == "immutable") 2178 { 2179 attrs |= FunctionAttribute.immutable_; 2180 } 2181 else static if (a == "inout") 2182 { 2183 attrs |= FunctionAttribute.inout_; 2184 } 2185 else static if (a == "@nogc") 2186 { 2187 attrs |= FunctionAttribute.nogc; 2188 } 2189 else static if (a == "nothrow") 2190 { 2191 attrs |= FunctionAttribute.nothrow_; 2192 } 2193 else static if (a == "@property") 2194 { 2195 attrs |= FunctionAttribute.property; 2196 } 2197 else static if (a == "pure") 2198 { 2199 attrs |= FunctionAttribute.pure_; 2200 } 2201 else static if (a == "ref") 2202 { 2203 attrs |= FunctionAttribute.ref_; 2204 } 2205 else static if (a == "return") 2206 { 2207 attrs |= FunctionAttribute.return_; 2208 } 2209 else static if (a == "@safe") 2210 { 2211 attrs |= FunctionAttribute.safe; 2212 } 2213 else static if (a == "scope") 2214 { 2215 attrs |= FunctionAttribute.scope_; 2216 } 2217 else static if (a == "shared") 2218 { 2219 attrs |= FunctionAttribute.shared_; 2220 } 2221 else static if (a == "@system") 2222 { 2223 attrs |= FunctionAttribute.system; 2224 } 2225 else static if (a == "@trusted") 2226 { 2227 attrs |= FunctionAttribute.trusted; 2228 } 2229 } 2230 return attrs; 2231 } 2232 enum uint functionAttributes = Impl(); 2233 } 2234 2235 /// 2236 @nogc nothrow pure @safe unittest 2237 { 2238 @property ref int func1() pure nothrow @safe @nogc shared scope; 2239 static assert((functionAttributes!func1 & FunctionAttribute.pure_) 2240 == FunctionAttribute.pure_); 2241 static assert((functionAttributes!func1 & FunctionAttribute.nothrow_) 2242 == FunctionAttribute.nothrow_); 2243 static assert((functionAttributes!func1 & FunctionAttribute.safe) 2244 == FunctionAttribute.safe); 2245 static assert((functionAttributes!func1 & FunctionAttribute.nogc) 2246 == FunctionAttribute.nogc); 2247 static assert((functionAttributes!func1 & FunctionAttribute.shared_) 2248 == FunctionAttribute.shared_); 2249 static assert((functionAttributes!func1 & FunctionAttribute.ref_) 2250 == FunctionAttribute.ref_); 2251 static assert((functionAttributes!func1 & FunctionAttribute.property) 2252 == FunctionAttribute.property); 2253 static assert((functionAttributes!func1 & FunctionAttribute.scope_) 2254 == FunctionAttribute.scope_); 2255 static assert((functionAttributes!func1 & FunctionAttribute.system) == 0); 2256 static assert((functionAttributes!func1 & FunctionAttribute.trusted) == 0); 2257 static assert((functionAttributes!func1 & FunctionAttribute.return_) == 0); 2258 } 2259 2260 /** 2261 * Determines whether a function has attribute. 2262 * 2263 * This template should get at least two arguments: the function itself and the 2264 * attributes it should be tested for. If more than one attribute is given, 2265 * $(D_PSYMBOL hasFunctionAttributes) evaluates to $(D_KEYWORD true) if all of 2266 * them are present. The attributes should be $(D_PSYMBOL FunctionAttribute) 2267 * members. 2268 * 2269 * Params: 2270 * Args = The function and attributes. 2271 * 2272 * Returns: 2273 * 2274 * See_Also: $(D_PSYMBOL FunctionAttribute). 2275 */ 2276 template hasFunctionAttributes(Args...) 2277 if (Args.length > 1 2278 && is(typeof(Args[1]) == FunctionAttribute) 2279 && isCallable!(Args[0]) 2280 && allSameType!(Map!(TypeOf, Args[1 .. $]))) 2281 { 2282 enum uint pred(Args_...) = Args_[0] | Args_[1]; 2283 2284 template Reduce(Args_...) 2285 { 2286 static if (Args_.length == 1) 2287 { 2288 enum uint Reduce = Args_[0]; 2289 } 2290 else 2291 { 2292 enum uint Reduce = Reduce!(pred!(Args_[0], Args_[1]), Args_[2 .. $]); 2293 } 2294 } 2295 enum uint field = Reduce!(0, Args[1 .. $]); 2296 enum hasFunctionAttributes = (functionAttributes!(Args[0]) & field) == field; 2297 } 2298 2299 /// 2300 @nogc nothrow pure @safe unittest 2301 { 2302 static struct Range 2303 { 2304 @property auto front() inout 2305 { 2306 return 8; 2307 } 2308 } 2309 static assert(hasFunctionAttributes!(Range.init.front, FunctionAttribute.inout_)); 2310 static assert(!hasFunctionAttributes!(Range.init.front, FunctionAttribute.const_)); 2311 static assert(!hasFunctionAttributes!(Range.init.front, 2312 FunctionAttribute.inout_, FunctionAttribute.const_)); 2313 } 2314 2315 /** 2316 * Returns a tuple with default values of the parameters to $(D_PARAM F). 2317 * 2318 * If a parameter doesn't have a default value, $(D_KEYWORD void) is returned. 2319 * 2320 * Params: 2321 * F = A function. 2322 * 2323 * Returns: Default values of the parameters to $(D_PARAM F). 2324 */ 2325 template ParameterDefaults(F...) 2326 if (isCallable!F) 2327 { 2328 static if (is(FunctionTypeOf!F T == __parameters)) 2329 { 2330 private template GetDefault(size_t i) 2331 { 2332 static if (i == T.length) 2333 { 2334 alias GetDefault = AliasSeq!(); 2335 } 2336 else 2337 { 2338 enum getDefault(T[i .. i + 1] name) 2339 { 2340 return name[0]; 2341 } 2342 static if (is(typeof(getDefault()))) 2343 { 2344 alias Default = Alias!(getDefault()); 2345 } 2346 else 2347 { 2348 alias Default = void; 2349 } 2350 alias GetDefault = AliasSeq!(Default, GetDefault!(i + 1)); 2351 } 2352 } 2353 2354 alias ParameterDefaults = GetDefault!0; 2355 } 2356 } 2357 2358 /// 2359 @nogc nothrow pure @safe unittest 2360 { 2361 void func1(int k, uint b = 5, int[] = [1, 2]); 2362 alias Defaults = ParameterDefaults!func1; 2363 static assert(is(Defaults[0] == void)); 2364 static assert(Defaults[1 .. 3] == AliasSeq!(5, [1, 2])); 2365 } 2366 2367 /** 2368 * Determines whether $(D_PARAM T) has an elaborate destructor. 2369 * 2370 * Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the 2371 * length greater than`0` can have elaborate destructors, for all other types 2372 * $(D_PSYMBOL hasElaborateDestructor) evaluates to $(D_KEYWORD false). 2373 * 2374 * An elaborate destructor is an explicitly defined destructor or one generated 2375 * by the compiler. The compiler generates a destructor for a 2376 * $(D_KEYWORD struct) if it has members with an elaborate destructor. 2377 * 2378 * Params: 2379 * T = A type. 2380 * 2381 * Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate destructor, 2382 * $(D_KEYWORD false) otherwise. 2383 */ 2384 template hasElaborateDestructor(T) 2385 { 2386 static if (is(T E : E[L], size_t L)) 2387 { 2388 enum bool hasElaborateDestructor = L > 0 && hasElaborateDestructor!E; 2389 } 2390 else 2391 { 2392 enum bool hasElaborateDestructor = is(T == struct) 2393 && hasMember!(T, "__xdtor"); 2394 } 2395 } 2396 2397 /// 2398 @nogc nothrow pure @safe unittest 2399 { 2400 class C 2401 { 2402 ~this() 2403 { 2404 } 2405 } 2406 static assert(!hasElaborateDestructor!C); 2407 2408 static struct S 2409 { 2410 ~this() 2411 { 2412 } 2413 } 2414 static struct S1 2415 { 2416 S s; 2417 } 2418 static struct S2 2419 { 2420 } 2421 static assert(hasElaborateDestructor!S); // Explicit destructor. 2422 static assert(hasElaborateDestructor!S1); // Compiler-generated destructor. 2423 static assert(!hasElaborateDestructor!S2); // No destructor. 2424 2425 static assert(hasElaborateDestructor!(S[1])); 2426 static assert(!hasElaborateDestructor!(S[0])); 2427 } 2428 2429 /** 2430 * Determines whether $(D_PARAM T) has an elaborate postblit constructor. 2431 * 2432 * Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the 2433 * length greater than`0` can have elaborate postblit constructors, for all 2434 * other types $(D_PSYMBOL hasElaborateCopyConstructor) evaluates to 2435 * $(D_KEYWORD false). 2436 * 2437 * An elaborate postblit constructor is an explicitly defined postblit 2438 * constructor or one generated by the compiler. The compiler generates a 2439 * postblit constructor for a 2440 * $(D_KEYWORD struct) if it has members with an elaborate postblit 2441 * constructor. 2442 * 2443 * Params: 2444 * T = A type. 2445 * 2446 * Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate postblit 2447 * constructor, $(D_KEYWORD false) otherwise. 2448 */ 2449 template hasElaborateCopyConstructor(T) 2450 { 2451 static if (is(T E : E[L], size_t L)) 2452 { 2453 enum bool hasElaborateCopyConstructor = L > 0 2454 && hasElaborateCopyConstructor!E; 2455 } 2456 else 2457 { 2458 enum bool hasElaborateCopyConstructor = is(T == struct) 2459 && hasMember!(T, "__xpostblit"); 2460 } 2461 } 2462 2463 /// 2464 @nogc nothrow pure @safe unittest 2465 { 2466 static assert(!hasElaborateCopyConstructor!int); 2467 2468 static struct S 2469 { 2470 this(this) 2471 { 2472 } 2473 } 2474 static struct S1 2475 { 2476 S s; 2477 } 2478 static struct S2 2479 { 2480 } 2481 static assert(hasElaborateCopyConstructor!S); // Explicit destructor. 2482 static assert(hasElaborateCopyConstructor!S1); // Compiler-generated destructor. 2483 static assert(!hasElaborateCopyConstructor!S2); // No destructor. 2484 static assert(hasElaborateCopyConstructor!(S[1])); 2485 static assert(!hasElaborateCopyConstructor!(S[0])); 2486 } 2487 2488 /** 2489 * Determines whether $(D_PARAM T) has an elaborate assign. 2490 * 2491 * Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the 2492 * length greater than`0` can have an elaborate assign, for all 2493 * other types $(D_PSYMBOL hasElaborateAssign) evaluates to $(D_KEYWORD false). 2494 * 2495 * An elaborate assign is defined with $(D_INLINECODE opAssign(typeof(this))) 2496 * or $(D_INLINECODE opAssign(ref typeof(this))). An elaborate assign can be 2497 * generated for a $(D_KEYWORD struct) by the compiler if one of the members of 2498 * this $(D_KEYWORD struct) has an elaborate assign. 2499 * 2500 * Params: 2501 * T = A type. 2502 * 2503 * Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate assign, 2504 * $(D_KEYWORD false) otherwise. 2505 */ 2506 template hasElaborateAssign(T) 2507 { 2508 static if (is(T E : E[L], size_t L)) 2509 { 2510 enum bool hasElaborateAssign = L > 0 && hasElaborateAssign!E; 2511 } 2512 else static if (is(T == struct)) 2513 { 2514 private enum bool valueAssign = is(typeof({ T.init.opAssign(T()); })); 2515 enum bool hasElaborateAssign = valueAssign || is(typeof({ 2516 T s; 2517 s.opAssign(s); 2518 })); 2519 } 2520 else 2521 { 2522 enum bool hasElaborateAssign = false; 2523 } 2524 } 2525 2526 /** 2527 * Returns all members of $(D_KEYWORD enum) $(D_PARAM T). 2528 * 2529 * The members of $(D_PARAM T) are typed as $(D_PARAM T), not as a base type 2530 * of the enum. 2531 * 2532 * $(D_PARAM EnumMembers) returns all members of $(D_PARAM T), also if there 2533 * are some duplicates. 2534 * 2535 * Params: 2536 * T = A $(D_KEYWORD enum). 2537 * 2538 * Returns: All members of $(D_PARAM T). 2539 */ 2540 template EnumMembers(T) 2541 if (is(T == enum)) 2542 { 2543 private template getEnumMembers(Args...) 2544 { 2545 static if (Args.length == 1) 2546 { 2547 enum T getEnumMembers = __traits(getMember, T, Args[0]); 2548 } 2549 else 2550 { 2551 alias getEnumMembers = AliasSeq!(__traits(getMember, T, Args[0]), 2552 getEnumMembers!(Args[1 .. $])); 2553 } 2554 } 2555 private alias allMembers = AliasSeq!(__traits(allMembers, T)); 2556 static if (allMembers.length == 1) 2557 { 2558 alias EnumMembers = AliasSeq!(__traits(getMember, T, allMembers)); 2559 } 2560 else 2561 { 2562 alias EnumMembers = getEnumMembers!allMembers; 2563 } 2564 } 2565 2566 /// 2567 @nogc nothrow pure @safe unittest 2568 { 2569 enum E : int 2570 { 2571 one, 2572 two, 2573 three, 2574 } 2575 static assert([EnumMembers!E] == [E.one, E.two, E.three]); 2576 } 2577 2578 /** 2579 * Different than $(D_INLINECODE T.alignof), which is the same for all class 2580 * types, $(D_PSYMBOL classInstanceOf) determines the alignment of the class 2581 * instance and not of its reference. 2582 * 2583 * Params: 2584 * T = A class. 2585 * 2586 * Returns: Alignment of an instance of the class $(D_PARAM T). 2587 */ 2588 template classInstanceAlignment(T) 2589 if (is(T == class)) 2590 { 2591 private enum ptrdiff_t pred(U1, U2) = U1.alignof - U2.alignof; 2592 private alias Fields = typeof(T.tupleof); 2593 enum size_t classInstanceAlignment = Max!(pred, T, Fields).alignof; 2594 } 2595 2596 /// 2597 @nogc nothrow pure @safe unittest 2598 { 2599 class C1 2600 { 2601 } 2602 static assert(classInstanceAlignment!C1 == C1.alignof); 2603 2604 static struct S 2605 { 2606 align(8) 2607 uint s; 2608 2609 int i; 2610 } 2611 class C2 2612 { 2613 S s; 2614 } 2615 static assert(classInstanceAlignment!C2 == S.alignof); 2616 } 2617 2618 /** 2619 * Returns the size in bytes of the state that needs to be allocated to hold an 2620 * object of type $(D_PARAM T). 2621 * 2622 * There is a difference between the `.sizeof`-property and 2623 * $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface. 2624 * `T.sizeof` is constant on the given architecture then and is the same as 2625 * `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and 2626 * interfaces are reference types and `.sizeof` returns the size of the 2627 * reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize) 2628 * returns the size of the instance itself. 2629 * 2630 * The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array 2631 * stores its length and a data pointer. The size of the static arrays is 2632 * calculated differently since they are value types. It is the array length 2633 * multiplied by the element size. 2634 * 2635 * `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym 2636 * for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`. 2637 * 2638 * Params: 2639 * T = Object type. 2640 * 2641 * Returns: Size of an instance of type $(D_PARAM T). 2642 */ 2643 template stateSize(T) 2644 { 2645 static if (isPolymorphicType!T) 2646 { 2647 enum size_t stateSize = __traits(classInstanceSize, T); 2648 } 2649 else 2650 { 2651 enum size_t stateSize = T.sizeof; 2652 } 2653 } 2654 2655 /// 2656 @nogc nothrow pure @safe unittest 2657 { 2658 static assert(stateSize!int == 4); 2659 static assert(stateSize!bool == 1); 2660 static assert(stateSize!(int[]) == (size_t.sizeof * 2)); 2661 static assert(stateSize!(short[3]) == 6); 2662 2663 static struct Empty 2664 { 2665 } 2666 static assert(stateSize!Empty == 1); 2667 static assert(stateSize!void == 1); 2668 } 2669 2670 /** 2671 * Tests whether $(D_INLINECODE pred(T)) can be used as condition in an 2672 * $(D_KEYWORD if)-statement or a ternary operator. 2673 * 2674 * $(D_PARAM pred) is an optional parameter. By default $(D_PSYMBOL ifTestable) 2675 * tests whether $(D_PARAM T) itself is usable as condition in an 2676 * $(D_KEYWORD if)-statement or a ternary operator, i.e. if it a value of type 2677 * $(D_PARAM T) can be converted to a boolean. 2678 * 2679 * Params: 2680 * T = A type. 2681 * pred = Function with one argument. 2682 * 2683 * Returns: $(D_KEYWORD true) if $(D_INLINECODE pred(T)) can be used as 2684 * condition in an $(D_KEYWORD if)-statement or a ternary operator. 2685 */ 2686 template ifTestable(T, alias pred = a => a) 2687 { 2688 enum bool ifTestable = is(typeof(pred(T.init) ? true : false)); 2689 } 2690 2691 /// 2692 @nogc nothrow pure @safe unittest 2693 { 2694 static assert(ifTestable!int); 2695 2696 static struct S1 2697 { 2698 } 2699 static assert(!ifTestable!S1); 2700 2701 static struct S2 2702 { 2703 bool opCast(T : bool)() 2704 { 2705 return true; 2706 } 2707 } 2708 static assert(ifTestable!S2); 2709 } 2710 2711 /** 2712 * Returns a compile-time tuple of user-defined attributes (UDA) attached to 2713 * $(D_PARAM symbol). 2714 * 2715 * $(D_PARAM symbol) can be: 2716 * 2717 * $(DL 2718 * $(DT Template) 2719 * $(DD The attribute is matched if it is an instance of the template 2720 * $(D_PARAM attr).) 2721 * $(DT Type) 2722 * $(DD The attribute is matched if it its type is $(D_PARAM attr).) 2723 * $(DT Expression) 2724 * $(DD The attribute is matched if it equals to $(D_PARAM attr).) 2725 * ) 2726 * 2727 * If $(D_PARAM attr) isn't given, all user-defined attributes of 2728 * $(D_PARAM symbol) are returned. 2729 * 2730 * Params: 2731 * symbol = A symbol. 2732 * attr = User-defined attribute. 2733 * 2734 * Returns: A tuple of user-defined attributes attached to $(D_PARAM symbol) 2735 * and matching $(D_PARAM attr). 2736 * 2737 * See_Also: $(LINK2 https://dlang.org/spec/attribute.html#uda, 2738 * User Defined Attributes). 2739 */ 2740 template getUDAs(alias symbol, alias attr) 2741 { 2742 private template FindUDA(T...) 2743 { 2744 static if (T.length == 0) 2745 { 2746 alias FindUDA = AliasSeq!(); 2747 } 2748 else static if ((isTypeTuple!attr && is(TypeOf!(T[0]) == attr)) 2749 || (is(typeof(T[0] == attr)) && (T[0] == attr)) 2750 || isInstanceOf!(attr, TypeOf!(T[0]))) 2751 { 2752 alias FindUDA = AliasSeq!(T[0], FindUDA!(T[1 .. $])); 2753 } 2754 else 2755 { 2756 alias FindUDA = FindUDA!(T[1 .. $]); 2757 } 2758 } 2759 alias getUDAs = FindUDA!(__traits(getAttributes, symbol)); 2760 } 2761 2762 /// 2763 alias getUDAs(alias symbol) = AliasSeq!(__traits(getAttributes, symbol)); 2764 2765 /// 2766 @nogc nothrow pure @safe unittest 2767 { 2768 static struct Attr 2769 { 2770 int i; 2771 } 2772 @Attr int a; 2773 static assert(getUDAs!(a, Attr).length == 1); 2774 2775 @Attr(8) int b; 2776 static assert(getUDAs!(b, Attr).length == 1); 2777 static assert(getUDAs!(b, Attr)[0].i == 8); 2778 static assert(getUDAs!(b, Attr(8)).length == 1); 2779 static assert(getUDAs!(b, Attr(7)).length == 0); 2780 2781 @("string", 5) int c; 2782 static assert(getUDAs!(c, "string").length == 1); 2783 static assert(getUDAs!(c, 5).length == 1); 2784 static assert(getUDAs!(c, "String").length == 0); 2785 static assert(getUDAs!(c, 4).length == 0); 2786 2787 static struct T(U) 2788 { 2789 enum U s = 7; 2790 U i; 2791 } 2792 @T!int @T!int(8) int d; 2793 static assert(getUDAs!(d, T).length == 2); 2794 static assert(getUDAs!(d, T)[0].s == 7); 2795 static assert(getUDAs!(d, T)[1].i == 8); 2796 2797 @T int e; 2798 static assert(getUDAs!(e, T).length == 0); 2799 } 2800 2801 /** 2802 * Determines whether $(D_PARAM symbol) has user-defined attribute 2803 * $(D_PARAM attr) attached to it. 2804 * 2805 * Params: 2806 * symbol = A symbol. 2807 * attr = User-defined attribute. 2808 * 2809 * Returns: $(D_KEYWORD true) if $(D_PARAM symbol) has user-defined attribute 2810 * $(D_PARAM attr), $(D_KEYWORD false) otherwise. 2811 * 2812 * See_Also: $(LINK2 https://dlang.org/spec/attribute.html#uda, 2813 * User Defined Attributes). 2814 */ 2815 template hasUDA(alias symbol, alias attr) 2816 { 2817 enum bool hasUDA = getUDAs!(symbol, attr).length != 0; 2818 } 2819 2820 /// 2821 @nogc nothrow pure @safe unittest 2822 { 2823 static struct Attr1 2824 { 2825 } 2826 static struct Attr2 2827 { 2828 } 2829 @Attr1 int a; 2830 static assert(hasUDA!(a, Attr1)); 2831 static assert(!hasUDA!(a, Attr2)); 2832 } 2833 2834 /** 2835 * If $(D_PARAM T) is a type, constructs its default value, otherwise 2836 * $(D_PSYMBOL evalUDA) aliases itself to $(D_PARAM T). 2837 * 2838 * This template is useful when working with UDAs with default parameters, 2839 * i.e. if an attribute can be given as `@Attr` or `@Attr("param")`, 2840 * $(D_PSYMBOL evalUDA) makes `@Attr()` from `@Attr`, but returns 2841 * `@Attr("param")` as is. 2842 * 2843 * $(D_PARAM T) (or its type if it isn't a type already) should have a default 2844 * constructor. 2845 * 2846 * Params: 2847 * T = User Defined Attribute. 2848 */ 2849 alias evalUDA(alias T) = T; 2850 2851 /// ditto 2852 alias evalUDA(T) = Alias!(T()); 2853 2854 /// 2855 @nogc nothrow pure @safe unittest 2856 { 2857 static struct Length 2858 { 2859 size_t length = 8; 2860 } 2861 @Length @Length(0) int i; 2862 alias uda = AliasSeq!(__traits(getAttributes, i)); 2863 2864 alias attr1 = evalUDA!(uda[0]); 2865 alias attr2 = evalUDA!(uda[1]); 2866 2867 static assert(is(typeof(attr1) == Length)); 2868 static assert(is(typeof(attr2) == Length)); 2869 2870 static assert(attr1.length == 8); 2871 static assert(attr2.length == 0); 2872 } 2873 2874 /** 2875 * Tests whether $(D_PARAM T) is an inner class, i.e. a class nested inside 2876 * another class. 2877 * 2878 * All inner classes get `outer` propery automatically generated, which points 2879 * to its parent class, though it can be explicitly defined to be something 2880 * different. If $(D_PARAM T) does this, $(D_PSYMBOL isInnerClass) 2881 * evaluates to $(D_KEYWORD false). 2882 * 2883 * Params: 2884 * T = Class to be tested. 2885 * 2886 * Returns $(D_KEYWORD true) if $(D_PARAM T) is an inner class, 2887 * $(D_KEYWORD false) otherwise. 2888 */ 2889 template isInnerClass(T) 2890 { 2891 static if (is(T == class) && is(typeof(T.outer) == class)) 2892 { 2893 enum bool isInnerClass = !canFind!("outer", __traits(allMembers, T)); 2894 } 2895 else 2896 { 2897 enum bool isInnerClass = false; 2898 } 2899 } 2900 2901 /// 2902 @nogc nothrow pure @safe unittest 2903 { 2904 class A 2905 { 2906 } 2907 class O 2908 { 2909 class I 2910 { 2911 } 2912 class Fake 2913 { 2914 bool outer; 2915 } 2916 } 2917 static assert(!isInnerClass!(O)); 2918 static assert(isInnerClass!(O.I)); 2919 static assert(!isInnerClass!(O.Fake)); 2920 } 2921 2922 /** 2923 * Returns the types of all members of $(D_PARAM T). 2924 * 2925 * If $(D_PARAM T) is a $(D_KEYWORD struct) or $(D_KEYWORD union) or 2926 * $(D_KEYWORD class), returns the types of all its fields. It is actually the 2927 * same as `T.tupleof`, but the content pointer for the nested type isn't 2928 * included. 2929 * 2930 * If $(D_PARAM T) is neither a $(D_KEYWORD struct) nor $(D_KEYWORD union) nor 2931 * $(D_KEYWORD class), $(D_PSYMBOL Fields) returns an $(D_PSYMBOL AliasSeq) 2932 * with the single element $(D_PARAM T). 2933 * 2934 * Params: 2935 * T = A type. 2936 * 2937 * Returns: $(D_PARAM T)'s fields. 2938 */ 2939 template Fields(T) 2940 { 2941 static if ((is(T == struct) || is(T == union)) && isNested!T) 2942 { 2943 // The last element of .tupleof of a nested struct or union is "this", 2944 // the context pointer, type "void*". 2945 alias Fields = typeof(T.tupleof[0 .. $ - 1]); 2946 } 2947 else static if (is(T == class) || is(T == struct) || is(T == union)) 2948 { 2949 alias Fields = typeof(T.tupleof); 2950 } 2951 else 2952 { 2953 alias Fields = AliasSeq!T; 2954 } 2955 } 2956 2957 /// 2958 @nogc nothrow pure @safe unittest 2959 { 2960 struct Nested 2961 { 2962 int i; 2963 2964 void func() 2965 { 2966 } 2967 } 2968 static assert(is(Fields!Nested == AliasSeq!int)); 2969 2970 class C 2971 { 2972 uint u; 2973 } 2974 static assert(is(Fields!C == AliasSeq!uint)); 2975 2976 static assert(is(Fields!short == AliasSeq!short)); 2977 } 2978 2979 /** 2980 * Determines whether all $(D_PARAM Types) are the same. 2981 * 2982 * If $(D_PARAM Types) is empty, returns $(D_KEYWORD true). 2983 * 2984 * Params: 2985 * Types = Type sequence. 2986 * 2987 * Returns: $(D_KEYWORD true) if all $(D_PARAM Types) are the same, 2988 * $(D_KEYWORD false) otherwise. 2989 */ 2990 template allSameType(Types...) 2991 { 2992 static if (Types.length == 0) 2993 { 2994 enum bool allSameType = true; 2995 } 2996 else 2997 { 2998 private enum bool sameType(T) = is(T == Types[0]); 2999 3000 enum bool allSameType = allSatisfy!(sameType, Types[1 .. $]); 3001 } 3002 } 3003 3004 /// 3005 @nogc nothrow pure @safe unittest 3006 { 3007 static assert(allSameType!()); 3008 static assert(allSameType!int); 3009 static assert(allSameType!(int, int, int)); 3010 static assert(!allSameType!(int, uint, int)); 3011 static assert(!allSameType!(int, uint, short)); 3012 } 3013 3014 /** 3015 * Determines whether values of type $(D_PARAM T) can be compared for equality, 3016 * i.e. using `==` or `!=` binary operators. 3017 * 3018 * Params: 3019 * T = Type to test. 3020 * 3021 * Returns: $(D_KEYWORD true) if $(D_PARAM T) can be compared for equality, 3022 * $(D_KEYWORD false) otherwise. 3023 */ 3024 enum bool isEqualityComparable(T) = ifTestable!(T, a => a == a); 3025 3026 /// 3027 @nogc nothrow pure @safe unittest 3028 { 3029 static assert(isEqualityComparable!int); 3030 } 3031 3032 /** 3033 * Determines whether values of type $(D_PARAM T) can be compared for ordering, 3034 * i.e. using `>`, `>=`, `<` or `<=` binary operators. 3035 * 3036 * Params: 3037 * T = Type to test. 3038 * 3039 * Returns: $(D_KEYWORD true) if $(D_PARAM T) can be compared for ordering, 3040 * $(D_KEYWORD false) otherwise. 3041 */ 3042 enum bool isOrderingComparable(T) = ifTestable!(T, a => a > a); 3043 3044 /// 3045 @nogc nothrow pure @safe unittest 3046 { 3047 static assert(isOrderingComparable!int); 3048 }