1 // Written in the D programming language 2 /++ 3 Templates which extract information about types and symbols at compile time. 4 5 In the context of phobos.sys.traits, a "trait" is a template which provides 6 information about a type or symbol. Most traits evaluate to 7 $(D true) or $(D false), telling the code using it whether the given 8 arguments match / have that specific trait (e.g. whether the given type is 9 a dynamic array or whether the given function is $(D @safe)). However, some 10 traits may provide other kinds of information about a type (e.g. the trait 11 could evaluate to the base type for an enum type, or it could strip 12 $(D const) from the type to provide the mutable version of that type). 13 14 These traits are then used primarily in template constraints so that they 15 can test that the template arguments meet the criteria required by those 16 templates, though they can be useful in a variety of compile-time contexts 17 (e.g. the condition of a $(D static if)). 18 19 Note that unless otherwise specified, the isXXXX and hasXXX traits in this 20 module are checking for exact matches, so base types (e.g. with enums) and 21 other implicit conversions do not factor into whether such traits are true 22 or false. The type itself is being checked, not what it can be converted 23 to. 24 25 This is because these traits are often used in templated constraints, and 26 having a type pass a template constraint based on an implicit conversion 27 but then not have the implicit conversion actually take place (which it 28 won't unless the template does something to force it internally) can lead 29 to either compilation errors or subtle behavioral differences - and even 30 when the conversion is done explicitly within a templated function, since 31 it's not done at the call site, it can still lead to subtle bugs in some 32 cases (e.g. if slicing a static array is involved). 33 34 So, it's typically best to be explicit and clear about a template constraint 35 accepting any kind of implicit conversion rather than having it buried in a 36 trait where programmers stand a good chance of using the trait without 37 realizing that enums might pass based on their base type - or that a type 38 might pass based on some other implicit conversion. 39 40 Regardless of what a trait is testing for, the documentation strives to be 41 $(I very) clear about what the trait does, and of course, the names do try 42 to make it clear as well - though obviously, only so much information can 43 be put into a name, and some folks will misintrepret some symbols no matter 44 how well they're named. So, please be sure that you clearly understand what 45 these traits do when using them, since messing up template constraints can 46 unfortunately be a great way to introduce subtle bugs into your program. 47 Either way, of course, unit tests are your friends. 48 49 $(SCRIPT inhibitQuickIndex = 1;) 50 51 $(BOOKTABLE , 52 $(TR $(TH Category) $(TH Templates)) 53 $(TR $(TD Categories of types) $(TD 54 $(LREF isAggregateType) 55 $(LREF isDynamicArray) 56 $(LREF isFloatingPoint) 57 $(LREF isInstantiationOf) 58 $(LREF isInteger) 59 $(LREF isNumeric) 60 $(LREF isPointer) 61 $(LREF isSignedInteger) 62 $(LREF isStaticArray) 63 $(LREF isUnsignedInteger) 64 )) 65 $(TR $(TD Aggregate Type traits) $(TD 66 $(LREF EnumMembers) 67 )) 68 $(TR $(TD Traits testing for type conversions) $(TD 69 $(LREF isImplicitlyConvertible) 70 $(LREF isQualifierConvertible) 71 )) 72 $(TR $(TD Traits for comparisons) $(TD 73 $(LREF isEqual) 74 $(LREF isSameSymbol) 75 $(LREF isSameType) 76 )) 77 $(TR $(TD Aggregate Type Traits) $(TD 78 $(LREF FieldNames) 79 $(LREF FieldSymbols) 80 $(LREF FieldTypes) 81 )) 82 $(TR $(TD General Types) $(TD 83 $(LREF KeyType) 84 $(LREF OriginalType) 85 $(LREF ValueType) 86 )) 87 $(TR $(TD Traits for removing type qualfiers) $(TD 88 $(LREF Unconst) 89 $(LREF Unshared) 90 $(LREF Unqualified) 91 )) 92 $(TR $(TD Type Constructors) $(TD 93 $(LREF ConstOf) 94 $(LREF ImmutableOf) 95 $(LREF InoutOf) 96 $(LREF SharedOf) 97 )) 98 $(TR $(TD Misc) $(TD 99 $(LREF lvalueOf) 100 $(LREF rvalueOf) 101 )) 102 ) 103 104 Copyright: Copyright The D Language Foundation 2005 - 2024. 105 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 106 Authors: $(HTTP jmdavisprog.com, Jonathan M Davis) 107 $(HTTP digitalmars.com, Walter Bright), 108 Tomasz Stachowiak (`isExpressions`), 109 $(HTTP erdani.org, Andrei Alexandrescu), 110 Shin Fujishiro, 111 $(HTTP octarineparrot.com, Robert Clipsham), 112 $(HTTP klickverbot.at, David Nadlinger), 113 Kenji Hara, 114 Shoichi Kato 115 Source: $(PHOBOSSRC phobos/sys/traits) 116 +/ 117 module phobos.sys.traits; 118 119 /++ 120 Whether the given type is an "aggregate type" - i.e. a struct, class, 121 interface, or union. 122 +/ 123 enum isAggregateType(T) = is(T == struct) || is(T == class) || is(T == interface) || is(T == union); 124 125 @safe unittest 126 { 127 struct S {} 128 class C {} 129 interface I {} 130 union U {} 131 132 static assert( isAggregateType!S); 133 static assert( isAggregateType!C); 134 static assert( isAggregateType!I); 135 static assert( isAggregateType!U); 136 static assert( isAggregateType!(const S)); 137 static assert( isAggregateType!(shared C)); 138 139 static assert(!isAggregateType!int); 140 static assert(!isAggregateType!string); 141 static assert(!isAggregateType!(S*)); 142 static assert(!isAggregateType!(C[])); 143 static assert(!isAggregateType!(I[string])); 144 } 145 146 /++ 147 Whether the given type is a dynamic array (or what is sometimes referred to 148 as a slice, since a dynamic array in D is a slice of memory). 149 150 Note that this does not include implicit conversions or enum types. The 151 type itself must be a dynamic array. 152 153 Remember that D's dynamic arrays are essentially: 154 --- 155 struct DynamicArray(T) 156 { 157 size_t length; 158 T* ptr; 159 } 160 --- 161 where $(D ptr) points to the first element in the array, and $(D length) is 162 the number of elements in the array. 163 164 A dynamic array is not a pointer (unlike arrays in C/C++), and its elements 165 do not live inside the dynamic array itself. The dynamic array is simply a 166 slice of memory and does not own or manage its own memory. It can be a 167 slice of any piece of memory, including GC-allocated memory, the stack, 168 malloc-ed memory, etc. (with what kind of memory it is of course being 169 determined by how the dynamic array was created in the first place) 170 - though if you do any operations on it which end up requiring allocation 171 (e.g. appending to it if it doesn't have the capacity to expand in-place, 172 which it won't if it isn't a slice of GC-allocated memory), then that 173 reallocation will result in the dynamic array being a slice of newly 174 allocated, GC-backed memory (regardless of what it was a slice of before), 175 since it's the GC that deals with those allocations. 176 177 As long as code just accesses the elements or members of the dynamic array 178 - or reduces its length so that it's a smaller slice - it will continue to 179 point to whatever block of memory it pointed to originally. And because the 180 GC makes sure that appending to a dynamic array does not stomp on the 181 memory of any other dynamic arrays, appending to a dynamic array will not 182 affect any other dynamic array which is a slice of that same block of 183 memory whether a reallocation occurs or not. 184 185 Regardless, since what allocated the memory that the dynamic array is a 186 slice of is irrevelant to the type of the dynamic array, whether a given 187 type is a dynamic array has nothing to do with the kind of memory that's 188 backing it. A dynamic array which is a slice of a static array of $(D int) 189 is the the same type as a dynamic array of $(D int) allocated with $(D new) 190 - i.e. both are $(D int[]). So, this trait will not tell you anything about 191 what kind of memory a dynamic array is a slice of. It just tells you 192 whether the type is a dynamic array or not. 193 194 If for some reason, it matters for a function what kind of memory backs one 195 of its parameters which is a dynamic array, or it needs to be made clear 196 whether the function will possibly cause that dynamic array to be 197 reallocated, then that needs to be indicated by the documentation and 198 cannot be enforced with a template constraint. A template constraint can 199 enforce that a type used with a template meets certain criteria (e.g. that 200 it's a dynamic array), but it cannot enforce anything about how the 201 template actually uses the type. 202 203 However, it $(D is) possible to enforce that a function doesn't use any 204 operations on a dynamic array which might cause it to be reallocated by 205 marking that function as $(D @nogc). 206 207 In most cases though, code can be written to not care what kind of memory 208 backs a dynamic array, because none of the operations on a dynamic array 209 actually care what kind of memory it's a slice of. It mostly just matters 210 when you need to track the lifetime of the memory, because it wasn't 211 allocated by the GC, or when it matters whether a dynamic array could be 212 reallocated or not (e.g. because the code needs to have that dynamic array 213 continue to point to the same block of memory). 214 215 See_Also: 216 $(LREF isPointer) 217 $(LREF isStaticArray) 218 $(DDSUBLINK spec/arrays, , The language spec for arrays) 219 +/ 220 enum isDynamicArray(T) = is(T == U[], U); 221 222 /// 223 @safe unittest 224 { 225 // Some types which are dynamic arrays. 226 static assert( isDynamicArray!(int[])); 227 static assert( isDynamicArray!(const int[])); 228 static assert( isDynamicArray!(inout int[])); 229 static assert( isDynamicArray!(shared(int)[])); 230 static assert( isDynamicArray!string); 231 232 static assert( isDynamicArray!(typeof([1, 2, 3]))); 233 static assert( isDynamicArray!(typeof("dlang"))); 234 235 int[] arr; 236 static assert( isDynamicArray!(typeof(arr))); 237 238 // Some types which aren't dynamic arrays. 239 static assert(!isDynamicArray!int); 240 static assert(!isDynamicArray!(int*)); 241 static assert(!isDynamicArray!real); 242 243 static struct S 244 { 245 int[] arr; 246 } 247 static assert(!isDynamicArray!S); 248 249 // The struct itself isn't considered a dynamic array, 250 // but its member variable is when checked directly. 251 static assert( isDynamicArray!(typeof(S.arr))); 252 253 // Static arrays. 254 static assert(!isDynamicArray!(int[5])); 255 static assert(!isDynamicArray!(const(int)[5])); 256 257 int[2] sArr = [42, 97]; 258 static assert(!isDynamicArray!(typeof(sArr))); 259 260 // While a static array is not a dynamic array, 261 // a slice of a static array is a dynamic array. 262 static assert( isDynamicArray!(typeof(sArr[]))); 263 264 // Dynamic array of static arrays. 265 static assert( isDynamicArray!(long[3][])); 266 267 // Static array of dynamic arrays. 268 static assert(!isDynamicArray!(long[][3])); 269 270 // Associative array. 271 static assert(!isDynamicArray!(int[string])); 272 273 // While typeof(null) gets treated as void[] in some contexts, it is 274 // distinct from void[] and is not considered to be a dynamic array. 275 static assert(!isDynamicArray!(typeof(null))); 276 277 // However, naturally, if null is cast to a dynamic array, it's a 278 // dynamic array, since the cast forces the type. 279 static assert( isDynamicArray!(typeof(cast(int[]) null))); 280 281 enum E : int[] 282 { 283 a = [1, 2, 3], 284 } 285 286 // Enums do not count. 287 static assert(!isDynamicArray!E); 288 289 static struct AliasThis 290 { 291 int[] arr; 292 alias this = arr; 293 } 294 295 // Other implicit conversions do not count. 296 static assert(!isDynamicArray!AliasThis); 297 } 298 299 @safe unittest 300 { 301 import phobos.sys.meta : Alias, AliasSeq; 302 303 static struct AliasThis(T) 304 { 305 T member; 306 alias this = member; 307 } 308 309 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 310 { 311 foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][])) 312 { 313 enum E : Q!T { a = Q!T.init } 314 315 static assert( isDynamicArray!(Q!T)); 316 static assert(!isDynamicArray!E); 317 static assert(!isDynamicArray!(AliasThis!(Q!T))); 318 } 319 320 foreach (T; AliasSeq!(int, int[51], int[][2], 321 char[][int][11], immutable char[13u], 322 const(real)[1], const(real)[1][1], void[0])) 323 { 324 enum E : Q!T { a = Q!T.init } 325 326 static assert(!isDynamicArray!(Q!T)); 327 static assert(!isDynamicArray!E); 328 static assert(!isDynamicArray!(AliasThis!(Q!T))); 329 } 330 } 331 } 332 333 /++ 334 Whether type $(D T) is a static array. 335 336 Note that this does not include implicit conversions or enum types. The 337 type itself must be a static array. This is in contrast to 338 $(D __traits(isStaticArray, T)) which is true for enums (but not for other 339 implict conversions to static arrays). 340 341 As explained in the module documentation, traits like this one are not true 342 for enums (unlike most of the $(D __traits) traits) in order to avoid 343 testing for implicit conversions by default with template constraints, 344 since that tends to lead to subtle bugs when the code isn't carefully 345 written to take implicit conversions into account. 346 347 See also: 348 $(DDSUBLINK spec/traits, isStaticArray, $(D __traits(isStaticArray, T))) 349 $(DDSUBLINK spec/arrays, , The language spec for arrays) 350 +/ 351 enum isStaticArray(T) = is(T == U[n], U, size_t n); 352 353 /// 354 @safe unittest 355 { 356 // Some types which are static arrays. 357 static assert( isStaticArray!(int[12])); 358 static assert( isStaticArray!(const int[42])); 359 static assert( isStaticArray!(inout int[0])); 360 static assert( isStaticArray!(shared(int)[907])); 361 static assert( isStaticArray!(immutable(char)[5])); 362 363 // D doesn't have static array literals, but you get the same effect 364 // by casting a dynamic array literal to a static array, and of course, 365 // the result is typed as a static array. 366 static assert( isStaticArray!(typeof(cast(int[3]) [1, 2, 3]))); 367 368 int[2] sArr = [1, 2]; 369 static assert( isStaticArray!(typeof(sArr))); 370 371 // Some types which are not static arrays. 372 static assert(!isStaticArray!int); 373 static assert(!isStaticArray!(int*)); 374 static assert(!isStaticArray!real); 375 376 static struct S 377 { 378 int[4] arr; 379 } 380 static assert(!isStaticArray!S); 381 382 // The struct itself isn't considered a static array, 383 // but its member variable is when checked directly. 384 static assert( isStaticArray!(typeof(S.arr))); 385 386 // Dynamic arrays. 387 static assert(!isStaticArray!(int[])); 388 static assert(!isStaticArray!(const(int)[])); 389 static assert(!isStaticArray!string); 390 391 int[] arr; 392 static assert(!isStaticArray!(typeof(arr))); 393 394 // A slice of a static array is of course not a static array, 395 // because it's a dynamic array. 396 static assert(!isStaticArray!(typeof(sArr[]))); 397 398 // Static array of dynamic arrays. 399 static assert( isStaticArray!(long[][3])); 400 401 // Dynamic array of static arrays. 402 static assert(!isStaticArray!(long[3][])); 403 404 // Associative array. 405 static assert(!isStaticArray!(int[string])); 406 407 // Of course, null is not considered to be a static array. 408 static assert(!isStaticArray!(typeof(null))); 409 410 enum E : int[3] 411 { 412 a = [1, 2, 3], 413 } 414 415 // Enums do not count. 416 static assert(!isStaticArray!E); 417 418 // This is where isStaticArray differs from __traits(isStaticArray, ...) 419 static assert( __traits(isStaticArray, E)); 420 421 static struct AliasThis 422 { 423 int[] arr; 424 alias this = arr; 425 } 426 427 // Other implicit conversions do not count. 428 static assert(!isStaticArray!AliasThis); 429 430 static assert(!__traits(isStaticArray, AliasThis)); 431 } 432 433 @safe unittest 434 { 435 import phobos.sys.meta : Alias, AliasSeq; 436 437 static struct AliasThis(T) 438 { 439 T member; 440 alias this = member; 441 } 442 443 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 444 { 445 foreach (T; AliasSeq!(int[51], int[][2], 446 char[][int][11], immutable char[13u], 447 const(real)[1], const(real)[1][1], void[0])) 448 { 449 enum E : Q!T { a = Q!T.init, } 450 451 static assert( isStaticArray!(Q!T)); 452 static assert(!isStaticArray!E); 453 static assert(!isStaticArray!(AliasThis!(Q!T))); 454 } 455 456 foreach (T; AliasSeq!(int, int[], char[], string, long[3][], double[string][])) 457 { 458 enum E : Q!T { a = Q!T.init, } 459 460 static assert(!isStaticArray!(Q!T)); 461 static assert(!isStaticArray!E); 462 static assert(!isStaticArray!(AliasThis!(Q!T))); 463 } 464 } 465 } 466 467 /++ 468 Whether the given type is one of the built-in integer types, ignoring all 469 qualifiers. 470 471 $(TABLE 472 $(TR $(TH Integer Types)) 473 $(TR $(TD byte)) 474 $(TR $(TD ubyte)) 475 $(TR $(TD short)) 476 $(TR $(TD ushort)) 477 $(TR $(TD int)) 478 $(TR $(TD uint)) 479 $(TR $(TD long)) 480 $(TR $(TD ulong)) 481 ) 482 483 Note that this does not include implicit conversions or enum types. The 484 type itself must be one of the built-in integer types. 485 486 This trait does have some similarities with $(D __traits(isIntegral, T)), 487 but $(D isIntegral) accepts a $(I lot) more types than isInteger does. 488 isInteger is specifically for testing for the built-in integer types, 489 whereas $(D isIntegral) tests for a whole set of types that are vaguely 490 integer-like (including $(D bool), the three built-in character types, and 491 some of the vector types from core.simd). So, for most code, isInteger is 492 going to be more appropriate, but obviously, it depends on what the code is 493 trying to do. 494 495 See also: 496 $(DDSUBLINK spec/traits, isIntegral, $(D __traits(isIntegral, T))) 497 $(LREF isFloatingPoint) 498 $(LREF isSignedInteger) 499 $(LREF isNumeric) 500 $(LREF isUnsignedInteger) 501 +/ 502 enum isInteger(T) = is(immutable T == immutable byte) || 503 is(immutable T == immutable ubyte) || 504 is(immutable T == immutable short) || 505 is(immutable T == immutable ushort) || 506 is(immutable T == immutable int) || 507 is(immutable T == immutable uint) || 508 is(immutable T == immutable long) || 509 is(immutable T == immutable ulong); 510 511 /// 512 @safe unittest 513 { 514 // Some types which are integer types. 515 static assert( isInteger!byte); 516 static assert( isInteger!ubyte); 517 static assert( isInteger!short); 518 static assert( isInteger!ushort); 519 static assert( isInteger!int); 520 static assert( isInteger!uint); 521 static assert( isInteger!long); 522 static assert( isInteger!ulong); 523 524 static assert( isInteger!(const ubyte)); 525 static assert( isInteger!(immutable short)); 526 static assert( isInteger!(inout int)); 527 static assert( isInteger!(shared uint)); 528 static assert( isInteger!(const shared ulong)); 529 530 static assert( isInteger!(typeof(42))); 531 static assert( isInteger!(typeof(1234567890L))); 532 533 int i; 534 static assert( isInteger!(typeof(i))); 535 536 // Some types which aren't integer types. 537 static assert(!isInteger!bool); 538 static assert(!isInteger!char); 539 static assert(!isInteger!wchar); 540 static assert(!isInteger!dchar); 541 static assert(!isInteger!(int[])); 542 static assert(!isInteger!(ubyte[4])); 543 static assert(!isInteger!(int*)); 544 static assert(!isInteger!double); 545 static assert(!isInteger!string); 546 547 static struct S 548 { 549 int i; 550 } 551 static assert(!isInteger!S); 552 553 // The struct itself isn't considered an integer, 554 // but its member variable is when checked directly. 555 static assert( isInteger!(typeof(S.i))); 556 557 enum E : int 558 { 559 a = 42 560 } 561 562 // Enums do not count. 563 static assert(!isInteger!E); 564 565 static struct AliasThis 566 { 567 int i; 568 alias this = i; 569 } 570 571 // Other implicit conversions do not count. 572 static assert(!isInteger!AliasThis); 573 } 574 575 @safe unittest 576 { 577 import phobos.sys.meta : Alias, AliasSeq; 578 579 static struct AliasThis(T) 580 { 581 T member; 582 alias this = member; 583 } 584 585 // The actual core.simd types available vary from system to system, so we 586 // have to be a bit creative here. The reason that we're testing these types 587 // is because __traits(isIntegral, T) accepts them, but isInteger is not 588 // supposed to. 589 template SIMDTypes() 590 { 591 import core.simd; 592 593 alias SIMDTypes = AliasSeq!(); 594 static if (is(ubyte16)) 595 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 596 static if (is(int4)) 597 SIMDTypes = AliasSeq!(SIMDTypes, int4); 598 static if (is(double2)) 599 SIMDTypes = AliasSeq!(SIMDTypes, double2); 600 static if (is(void16)) 601 SIMDTypes = AliasSeq!(SIMDTypes, void16); 602 } 603 604 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 605 { 606 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong)) 607 { 608 enum E : Q!T { a = Q!T.init } 609 610 static assert( isInteger!(Q!T)); 611 static assert(!isInteger!E); 612 static assert(!isInteger!(AliasThis!(Q!T))); 613 } 614 615 foreach (T; AliasSeq!(bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 616 int[], ubyte[8], dchar[], void[], long*)) 617 { 618 enum E : Q!T { a = Q!T.init } 619 620 static assert(!isInteger!(Q!T)); 621 static assert(!isInteger!E); 622 static assert(!isInteger!(AliasThis!(Q!T))); 623 } 624 } 625 } 626 627 /++ 628 Whether the given type is one of the built-in signed integer types, ignoring 629 all qualifiers. 630 631 $(TABLE 632 $(TR $(TH Signed Integer Types)) 633 $(TR $(TD byte)) 634 $(TR $(TD short)) 635 $(TR $(TD int)) 636 $(TR $(TD long)) 637 ) 638 639 Note that this does not include implicit conversions or enum types. The 640 type itself must be one of the built-in signed integer types. 641 642 See also: 643 $(LREF isFloatingPoint) 644 $(LREF isInteger) 645 $(LREF isNumeric) 646 $(LREF isUnsignedInteger) 647 +/ 648 enum isSignedInteger(T) = is(immutable T == immutable byte) || 649 is(immutable T == immutable short) || 650 is(immutable T == immutable int) || 651 is(immutable T == immutable long); 652 653 /// 654 @safe unittest 655 { 656 // Some types which are signed integer types. 657 static assert( isSignedInteger!byte); 658 static assert( isSignedInteger!short); 659 static assert( isSignedInteger!int); 660 static assert( isSignedInteger!long); 661 662 static assert( isSignedInteger!(const byte)); 663 static assert( isSignedInteger!(immutable short)); 664 static assert( isSignedInteger!(inout int)); 665 static assert( isSignedInteger!(shared int)); 666 static assert( isSignedInteger!(const shared long)); 667 668 static assert( isSignedInteger!(typeof(42))); 669 static assert( isSignedInteger!(typeof(1234567890L))); 670 671 int i; 672 static assert( isSignedInteger!(typeof(i))); 673 674 // Some types which aren't signed integer types. 675 static assert(!isSignedInteger!ubyte); 676 static assert(!isSignedInteger!ushort); 677 static assert(!isSignedInteger!uint); 678 static assert(!isSignedInteger!ulong); 679 680 static assert(!isSignedInteger!bool); 681 static assert(!isSignedInteger!char); 682 static assert(!isSignedInteger!wchar); 683 static assert(!isSignedInteger!dchar); 684 static assert(!isSignedInteger!(int[])); 685 static assert(!isSignedInteger!(ubyte[4])); 686 static assert(!isSignedInteger!(int*)); 687 static assert(!isSignedInteger!double); 688 static assert(!isSignedInteger!string); 689 690 static struct S 691 { 692 int i; 693 } 694 static assert(!isSignedInteger!S); 695 696 // The struct itself isn't considered a signed integer, 697 // but its member variable is when checked directly. 698 static assert( isSignedInteger!(typeof(S.i))); 699 700 enum E : int 701 { 702 a = 42 703 } 704 705 // Enums do not count. 706 static assert(!isSignedInteger!E); 707 708 static struct AliasThis 709 { 710 int i; 711 alias this = i; 712 } 713 714 // Other implicit conversions do not count. 715 static assert(!isSignedInteger!AliasThis); 716 } 717 718 @safe unittest 719 { 720 import phobos.sys.meta : Alias, AliasSeq; 721 722 static struct AliasThis(T) 723 { 724 T member; 725 alias this = member; 726 } 727 728 // The actual core.simd types available vary from system to system, so we 729 // have to be a bit creative here. The reason that we're testing these types 730 // is because __traits(isIntegral, T) accepts them, but isSignedInteger is 731 // not supposed to. 732 template SIMDTypes() 733 { 734 import core.simd; 735 736 alias SIMDTypes = AliasSeq!(); 737 static if (is(ubyte16)) 738 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 739 static if (is(int4)) 740 SIMDTypes = AliasSeq!(SIMDTypes, int4); 741 static if (is(double2)) 742 SIMDTypes = AliasSeq!(SIMDTypes, double2); 743 static if (is(void16)) 744 SIMDTypes = AliasSeq!(SIMDTypes, void16); 745 } 746 747 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 748 { 749 foreach (T; AliasSeq!(byte, short, int, long)) 750 { 751 enum E : Q!T { a = Q!T.init } 752 753 static assert( isSignedInteger!(Q!T)); 754 static assert(!isSignedInteger!E); 755 static assert(!isSignedInteger!(AliasThis!(Q!T))); 756 } 757 758 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, 759 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 760 int[], ubyte[8], dchar[], void[], long*)) 761 { 762 enum E : Q!T { a = Q!T.init } 763 764 static assert(!isSignedInteger!(Q!T)); 765 static assert(!isSignedInteger!E); 766 static assert(!isSignedInteger!(AliasThis!(Q!T))); 767 } 768 } 769 } 770 771 /++ 772 Whether the given type is one of the built-in unsigned integer types, 773 ignoring all qualifiers. 774 775 $(TABLE 776 $(TR $(TH Integer Types)) 777 $(TR $(TD ubyte)) 778 $(TR $(TD ushort)) 779 $(TR $(TD uint)) 780 $(TR $(TD ulong)) 781 ) 782 783 Note that this does not include implicit conversions or enum types. The 784 type itself must be one of the built-in unsigned integer types. 785 786 This trait does have some similarities with $(D __traits(isUnsigned, T)), 787 but $(D isUnsigned) accepts a $(I lot) more types than isUnsignedInteger 788 does. isUnsignedInteger is specifically for testing for the built-in 789 unsigned integer types, whereas $(D isUnsigned) tests for a whole set of 790 types that are unsigned and vaguely integer-like (including $(D bool), the 791 three built-in character types, and some of the vector types from 792 core.simd). So, for most code, isUnsignedInteger is going to be more 793 appropriate, but obviously, it depends on what the code is trying to do. 794 795 See also: 796 $(DDSUBLINK spec/traits, isUnsigned, $(D __traits(isUnsigned, T))) 797 $(LREF isFloatingPoint) 798 $(LREF isInteger) 799 $(LREF isSignedInteger) 800 $(LREF isNumeric) 801 +/ 802 enum isUnsignedInteger(T) = is(immutable T == immutable ubyte) || 803 is(immutable T == immutable ushort) || 804 is(immutable T == immutable uint) || 805 is(immutable T == immutable ulong); 806 807 /// 808 @safe unittest 809 { 810 // Some types which are unsigned integer types. 811 static assert( isUnsignedInteger!ubyte); 812 static assert( isUnsignedInteger!ushort); 813 static assert( isUnsignedInteger!uint); 814 static assert( isUnsignedInteger!ulong); 815 816 static assert( isUnsignedInteger!(const ubyte)); 817 static assert( isUnsignedInteger!(immutable ushort)); 818 static assert( isUnsignedInteger!(inout uint)); 819 static assert( isUnsignedInteger!(shared uint)); 820 static assert( isUnsignedInteger!(const shared ulong)); 821 822 static assert( isUnsignedInteger!(typeof(42u))); 823 static assert( isUnsignedInteger!(typeof(1234567890UL))); 824 825 uint u; 826 static assert( isUnsignedInteger!(typeof(u))); 827 828 // Some types which aren't unsigned integer types. 829 static assert(!isUnsignedInteger!byte); 830 static assert(!isUnsignedInteger!short); 831 static assert(!isUnsignedInteger!int); 832 static assert(!isUnsignedInteger!long); 833 834 static assert(!isUnsignedInteger!bool); 835 static assert(!isUnsignedInteger!char); 836 static assert(!isUnsignedInteger!wchar); 837 static assert(!isUnsignedInteger!dchar); 838 static assert(!isUnsignedInteger!(int[])); 839 static assert(!isUnsignedInteger!(ubyte[4])); 840 static assert(!isUnsignedInteger!(int*)); 841 static assert(!isUnsignedInteger!double); 842 static assert(!isUnsignedInteger!string); 843 844 static struct S 845 { 846 uint u; 847 } 848 static assert(!isUnsignedInteger!S); 849 850 // The struct itself isn't considered an unsigned integer, 851 // but its member variable is when checked directly. 852 static assert( isUnsignedInteger!(typeof(S.u))); 853 854 enum E : uint 855 { 856 a = 42 857 } 858 859 // Enums do not count. 860 static assert(!isUnsignedInteger!E); 861 862 static struct AliasThis 863 { 864 uint u; 865 alias this = u; 866 } 867 868 // Other implicit conversions do not count. 869 static assert(!isUnsignedInteger!AliasThis); 870 } 871 872 @safe unittest 873 { 874 import phobos.sys.meta : Alias, AliasSeq; 875 876 static struct AliasThis(T) 877 { 878 T member; 879 alias this = member; 880 } 881 882 // The actual core.simd types available vary from system to system, so we 883 // have to be a bit creative here. The reason that we're testing these types 884 // is because __traits(isIntegral, T) and __traits(isUnsigned, T) accept 885 // them, but isUnsignedInteger is not supposed to. 886 template SIMDTypes() 887 { 888 import core.simd; 889 890 alias SIMDTypes = AliasSeq!(); 891 static if (is(ubyte16)) 892 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 893 static if (is(int4)) 894 SIMDTypes = AliasSeq!(SIMDTypes, int4); 895 static if (is(double2)) 896 SIMDTypes = AliasSeq!(SIMDTypes, double2); 897 static if (is(void16)) 898 SIMDTypes = AliasSeq!(SIMDTypes, void16); 899 } 900 901 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 902 { 903 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong)) 904 { 905 enum E : Q!T { a = Q!T.init } 906 907 static assert( isUnsignedInteger!(Q!T)); 908 static assert(!isUnsignedInteger!E); 909 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 910 } 911 912 foreach (T; AliasSeq!(byte, short, int, long, 913 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 914 int[], ubyte[8], dchar[], void[], long*)) 915 { 916 enum E : Q!T { a = Q!T.init } 917 918 static assert(!isUnsignedInteger!(Q!T)); 919 static assert(!isUnsignedInteger!E); 920 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 921 } 922 } 923 } 924 925 /++ 926 Whether the given type is one of the built-in floating-point types, ignoring 927 all qualifiers. 928 929 $(TABLE 930 $(TR $(TH Floating-Point Types)) 931 $(TR $(TD float)) 932 $(TR $(TD double)) 933 $(TR $(TD real)) 934 ) 935 936 Note that this does not include implicit conversions or enum types. The 937 type itself must be one of the built-in floating-point types. 938 939 This trait does have some similarities with $(D __traits(isFloating, T)), 940 but $(D isFloating) accepts more types than isFloatingPoint does. 941 isFloatingPoint is specifically for testing for the built-in floating-point 942 types, whereas $(D isFloating) tests for a whole set of types that are 943 vaguely float-like (including enums with a base type which is a 944 floating-point type and some of the vector types from core.simd). So, for 945 most code, isFloatingPoint is going to be more appropriate, but obviously, 946 it depends on what the code is trying to do. 947 948 See also: 949 $(DDSUBLINK spec/traits, isFloating, $(D __traits(isFloating, T))) 950 $(LREF isInteger) 951 $(LREF isSignedInteger) 952 $(LREF isNumeric) 953 $(LREF isUnsignedInteger) 954 +/ 955 enum isFloatingPoint(T) = is(immutable T == immutable float) || 956 is(immutable T == immutable double) || 957 is(immutable T == immutable real); 958 959 /// 960 @safe unittest 961 { 962 // Some types which are floating-point types. 963 static assert( isFloatingPoint!float); 964 static assert( isFloatingPoint!double); 965 static assert( isFloatingPoint!real); 966 967 static assert( isFloatingPoint!(const float)); 968 static assert( isFloatingPoint!(immutable float)); 969 static assert( isFloatingPoint!(inout double)); 970 static assert( isFloatingPoint!(shared double)); 971 static assert( isFloatingPoint!(const shared real)); 972 973 static assert( isFloatingPoint!(typeof(42.0))); 974 static assert( isFloatingPoint!(typeof(42f))); 975 static assert( isFloatingPoint!(typeof(1e5))); 976 static assert( isFloatingPoint!(typeof(97.4L))); 977 978 double d; 979 static assert( isFloatingPoint!(typeof(d))); 980 981 // Some types which aren't floating-point types. 982 static assert(!isFloatingPoint!bool); 983 static assert(!isFloatingPoint!char); 984 static assert(!isFloatingPoint!dchar); 985 static assert(!isFloatingPoint!int); 986 static assert(!isFloatingPoint!long); 987 static assert(!isFloatingPoint!(float[])); 988 static assert(!isFloatingPoint!(double[4])); 989 static assert(!isFloatingPoint!(real*)); 990 static assert(!isFloatingPoint!string); 991 992 static struct S 993 { 994 double d; 995 } 996 static assert(!isFloatingPoint!S); 997 998 // The struct itself isn't considered a floating-point type, 999 // but its member variable is when checked directly. 1000 static assert( isFloatingPoint!(typeof(S.d))); 1001 1002 enum E : double 1003 { 1004 a = 12.34 1005 } 1006 1007 // Enums do not count. 1008 static assert(!isFloatingPoint!E); 1009 1010 static struct AliasThis 1011 { 1012 double d; 1013 alias this = d; 1014 } 1015 1016 // Other implicit conversions do not count. 1017 static assert(!isFloatingPoint!AliasThis); 1018 } 1019 1020 @safe unittest 1021 { 1022 import phobos.sys.meta : Alias, AliasSeq; 1023 1024 static struct AliasThis(T) 1025 { 1026 T member; 1027 alias this = member; 1028 } 1029 1030 // The actual core.simd types available vary from system to system, so we 1031 // have to be a bit creative here. The reason that we're testing these types 1032 // is because __traits(isFloating, T) accepts them, but isFloatingPoint is 1033 // not supposed to. 1034 template SIMDTypes() 1035 { 1036 import core.simd; 1037 1038 alias SIMDTypes = AliasSeq!(); 1039 static if (is(int4)) 1040 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1041 static if (is(double2)) 1042 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1043 static if (is(void16)) 1044 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1045 } 1046 1047 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1048 { 1049 foreach (T; AliasSeq!(float, double, real)) 1050 { 1051 enum E : Q!T { a = Q!T.init } 1052 1053 static assert( isFloatingPoint!(Q!T)); 1054 static assert(!isFloatingPoint!E); 1055 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1056 } 1057 1058 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, ubyte, short, ushort, 1059 int, uint, long, ulong, SIMDTypes!(), 1060 int[], float[8], real[], void[], double*)) 1061 { 1062 enum E : Q!T { a = Q!T.init } 1063 1064 static assert(!isFloatingPoint!(Q!T)); 1065 static assert(!isFloatingPoint!E); 1066 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1067 } 1068 } 1069 } 1070 1071 /++ 1072 Whether the given type is one of the built-in numeric types, ignoring all 1073 qualifiers. It's equivalent to $(D isInteger!T || isFloatingPoint!T), but 1074 it only involves a single template instantation instead of two. 1075 1076 $(TABLE 1077 $(TR $(TH Numeric Types)) 1078 $(TR $(TD byte)) 1079 $(TR $(TD ubyte)) 1080 $(TR $(TD short)) 1081 $(TR $(TD ushort)) 1082 $(TR $(TD int)) 1083 $(TR $(TD uint)) 1084 $(TR $(TD long)) 1085 $(TR $(TD ulong)) 1086 $(TR $(TD float)) 1087 $(TR $(TD double)) 1088 $(TR $(TD real)) 1089 ) 1090 1091 Note that this does not include implicit conversions or enum types. The 1092 type itself must be one of the built-in numeric types. 1093 1094 See_Also: 1095 $(LREF isFloatingPoint) 1096 $(LREF isInteger) 1097 $(LREF isSignedInteger) 1098 $(LREF isUnsignedInteger) 1099 +/ 1100 enum isNumeric(T) = is(immutable T == immutable byte) || 1101 is(immutable T == immutable ubyte) || 1102 is(immutable T == immutable short) || 1103 is(immutable T == immutable ushort) || 1104 is(immutable T == immutable int) || 1105 is(immutable T == immutable uint) || 1106 is(immutable T == immutable long) || 1107 is(immutable T == immutable ulong) || 1108 is(immutable T == immutable float) || 1109 is(immutable T == immutable double) || 1110 is(immutable T == immutable real); 1111 1112 /// 1113 @safe unittest 1114 { 1115 // Some types which are numeric types. 1116 static assert( isNumeric!byte); 1117 static assert( isNumeric!ubyte); 1118 static assert( isNumeric!short); 1119 static assert( isNumeric!ushort); 1120 static assert( isNumeric!int); 1121 static assert( isNumeric!uint); 1122 static assert( isNumeric!long); 1123 static assert( isNumeric!ulong); 1124 static assert( isNumeric!float); 1125 static assert( isNumeric!double); 1126 static assert( isNumeric!real); 1127 1128 static assert( isNumeric!(const short)); 1129 static assert( isNumeric!(immutable int)); 1130 static assert( isNumeric!(inout uint)); 1131 static assert( isNumeric!(shared long)); 1132 static assert( isNumeric!(const shared real)); 1133 1134 static assert( isNumeric!(typeof(42))); 1135 static assert( isNumeric!(typeof(1234657890L))); 1136 static assert( isNumeric!(typeof(42.0))); 1137 static assert( isNumeric!(typeof(42f))); 1138 static assert( isNumeric!(typeof(1e5))); 1139 static assert( isNumeric!(typeof(97.4L))); 1140 1141 int i; 1142 static assert( isNumeric!(typeof(i))); 1143 1144 // Some types which aren't numeric types. 1145 static assert(!isNumeric!bool); 1146 static assert(!isNumeric!char); 1147 static assert(!isNumeric!dchar); 1148 static assert(!isNumeric!(int[])); 1149 static assert(!isNumeric!(double[4])); 1150 static assert(!isNumeric!(real*)); 1151 static assert(!isNumeric!string); 1152 1153 static struct S 1154 { 1155 int i; 1156 } 1157 static assert(!isNumeric!S); 1158 1159 // The struct itself isn't considered a numeric type, 1160 // but its member variable is when checked directly. 1161 static assert( isNumeric!(typeof(S.i))); 1162 1163 enum E : int 1164 { 1165 a = 42 1166 } 1167 1168 // Enums do not count. 1169 static assert(!isNumeric!E); 1170 1171 static struct AliasThis 1172 { 1173 int i; 1174 alias this = i; 1175 } 1176 1177 // Other implicit conversions do not count. 1178 static assert(!isNumeric!AliasThis); 1179 } 1180 1181 @safe unittest 1182 { 1183 import phobos.sys.meta : Alias, AliasSeq; 1184 1185 static struct AliasThis(T) 1186 { 1187 T member; 1188 alias this = member; 1189 } 1190 1191 // The actual core.simd types available vary from system to system, so we 1192 // have to be a bit creative here. The reason that we're testing these types 1193 // is because __traits(isInteger, T) and __traits(isFloating, T) accept 1194 // them, but isNumeric is not supposed to. 1195 template SIMDTypes() 1196 { 1197 import core.simd; 1198 1199 alias SIMDTypes = AliasSeq!(); 1200 static if (is(int4)) 1201 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1202 static if (is(double2)) 1203 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1204 static if (is(void16)) 1205 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1206 } 1207 1208 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1209 { 1210 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real)) 1211 { 1212 enum E : Q!T { a = Q!T.init } 1213 1214 static assert( isNumeric!(Q!T)); 1215 static assert(!isNumeric!E); 1216 static assert(!isNumeric!(AliasThis!(Q!T))); 1217 } 1218 1219 foreach (T; AliasSeq!(bool, char, wchar, dchar, SIMDTypes!(), 1220 int[], float[8], real[], void[], double*)) 1221 { 1222 enum E : Q!T { a = Q!T.init } 1223 1224 static assert(!isNumeric!(Q!T)); 1225 static assert(!isNumeric!E); 1226 static assert(!isNumeric!(AliasThis!(Q!T))); 1227 } 1228 } 1229 } 1230 1231 /++ 1232 Whether the given type is a pointer. 1233 1234 Note that this does not include implicit conversions or enum types. The 1235 type itself must be a pointer. 1236 1237 Also, remember that unlike C/C++, D's arrays are not pointers. Rather, a 1238 dynamic array in D is a slice of memory which has a member which is a 1239 pointer to its first element and another member which is the length of the 1240 array as $(D size_t). So, a dynamic array / slice has a $(D ptr) member 1241 which is a pointer, but the dynamic array itself is not a pointer. 1242 1243 See_Also: 1244 $(LREF isDynamicArray) 1245 +/ 1246 enum isPointer(T) = is(T == U*, U); 1247 1248 /// 1249 @system unittest 1250 { 1251 // Some types which are pointers. 1252 static assert( isPointer!(bool*)); 1253 static assert( isPointer!(int*)); 1254 static assert( isPointer!(int**)); 1255 static assert( isPointer!(real*)); 1256 static assert( isPointer!(string*)); 1257 1258 static assert( isPointer!(const int*)); 1259 static assert( isPointer!(immutable int*)); 1260 static assert( isPointer!(inout int*)); 1261 static assert( isPointer!(shared int*)); 1262 static assert( isPointer!(const shared int*)); 1263 1264 static assert( isPointer!(typeof("foobar".ptr))); 1265 1266 int* ptr; 1267 static assert( isPointer!(typeof(ptr))); 1268 1269 int i; 1270 static assert( isPointer!(typeof(&i))); 1271 1272 // Some types which aren't pointers. 1273 static assert(!isPointer!bool); 1274 static assert(!isPointer!int); 1275 static assert(!isPointer!dchar); 1276 static assert(!isPointer!(int[])); 1277 static assert(!isPointer!(double[4])); 1278 static assert(!isPointer!string); 1279 1280 static struct S 1281 { 1282 int* ptr; 1283 } 1284 static assert(!isPointer!S); 1285 1286 // The struct itself isn't considered a numeric type, 1287 // but its member variable is when checked directly. 1288 static assert( isPointer!(typeof(S.ptr))); 1289 1290 enum E : immutable(char*) 1291 { 1292 a = "foobar".ptr 1293 } 1294 1295 // Enums do not count. 1296 static assert(!isPointer!E); 1297 1298 static struct AliasThis 1299 { 1300 int* ptr; 1301 alias this = ptr; 1302 } 1303 1304 // Other implicit conversions do not count. 1305 static assert(!isPointer!AliasThis); 1306 } 1307 1308 @safe unittest 1309 { 1310 import phobos.sys.meta : Alias, AliasSeq; 1311 1312 static struct AliasThis(T) 1313 { 1314 T member; 1315 alias this = member; 1316 } 1317 1318 static struct S 1319 { 1320 int i; 1321 } 1322 1323 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1324 { 1325 foreach (T; AliasSeq!(long*, S*, S**, S***, double[]*)) 1326 { 1327 enum E : Q!T { a = Q!T.init } 1328 1329 static assert( isPointer!(Q!T)); 1330 static assert(!isPointer!E); 1331 static assert(!isPointer!(AliasThis!(Q!T))); 1332 } 1333 1334 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, int, uint, long, 1335 int[], float[8], real[], void[])) 1336 { 1337 enum E : Q!T { a = Q!T.init } 1338 1339 static assert(!isPointer!(Q!T)); 1340 static assert(!isPointer!E); 1341 static assert(!isPointer!(AliasThis!(Q!T))); 1342 } 1343 } 1344 } 1345 1346 /++ 1347 Evaluates to $(D true) if the given type or symbol is an instantiation of 1348 the given template. 1349 1350 The overload which takes $(D T) operates on types and indicates whether an 1351 aggregate type (i.e. struct, class, interface, or union) is an 1352 instantiation of the given template. 1353 1354 The overload which takes $(D Symbol) operates on function templates, 1355 because unlike with aggregate types, the type of a function does not retain 1356 the fact that it was instantiated from a template. So, for functions, it's 1357 necessary to pass the function itself as a symbol rather than pass the type 1358 of the function. 1359 1360 The overload which takes $(D Symbol) also works with templates which are 1361 not types or functions. 1362 1363 The single-argument overload makes it so that it can be partially 1364 instantiated with the first argument, which will often be necessary with 1365 template predicates. 1366 +/ 1367 template isInstantiationOf(alias Template, T) 1368 if (__traits(isTemplate, Template)) 1369 { 1370 enum isInstantiationOf = is(T == Template!Args, Args...); 1371 } 1372 1373 /++ Ditto +/ 1374 template isInstantiationOf(alias Template, alias Symbol) 1375 if (__traits(isTemplate, Template)) 1376 { 1377 enum impl(alias T : Template!Args, Args...) = true; 1378 enum impl(alias T) = false; 1379 enum isInstantiationOf = impl!Symbol; 1380 } 1381 1382 /++ Ditto +/ 1383 template isInstantiationOf(alias Template) 1384 if (__traits(isTemplate, Template)) 1385 { 1386 enum isInstantiationOf(T) = is(T == Template!Args, Args...); 1387 1388 template isInstantiationOf(alias Symbol) 1389 { 1390 enum impl(alias T : Template!Args, Args...) = true; 1391 enum impl(alias T) = false; 1392 enum isInstantiationOf = impl!Symbol; 1393 } 1394 } 1395 1396 /// Examples of templated types. 1397 @safe unittest 1398 { 1399 static struct S(T) {} 1400 static class C(T) {} 1401 1402 static assert( isInstantiationOf!(S, S!int)); 1403 static assert( isInstantiationOf!(S, S!int)); 1404 static assert( isInstantiationOf!(S, S!string)); 1405 static assert( isInstantiationOf!(S, const S!string)); 1406 static assert( isInstantiationOf!(S, shared S!string)); 1407 static assert(!isInstantiationOf!(S, int)); 1408 static assert(!isInstantiationOf!(S, C!int)); 1409 static assert(!isInstantiationOf!(S, C!string)); 1410 static assert(!isInstantiationOf!(S, C!(S!int))); 1411 1412 static assert( isInstantiationOf!(C, C!int)); 1413 static assert( isInstantiationOf!(C, C!string)); 1414 static assert( isInstantiationOf!(C, const C!string)); 1415 static assert( isInstantiationOf!(C, shared C!string)); 1416 static assert(!isInstantiationOf!(C, int)); 1417 static assert(!isInstantiationOf!(C, S!int)); 1418 static assert(!isInstantiationOf!(C, S!string)); 1419 static assert(!isInstantiationOf!(C, S!(C!int))); 1420 1421 static struct Variadic(T...) {} 1422 1423 static assert( isInstantiationOf!(Variadic, Variadic!())); 1424 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1425 static assert( isInstantiationOf!(Variadic, Variadic!(int, string))); 1426 static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int))); 1427 static assert( isInstantiationOf!(Variadic, const Variadic!(int, short))); 1428 static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short))); 1429 static assert(!isInstantiationOf!(Variadic, int)); 1430 static assert(!isInstantiationOf!(Variadic, S!int)); 1431 static assert(!isInstantiationOf!(Variadic, C!int)); 1432 1433 static struct ValueArg(int i) {} 1434 static assert( isInstantiationOf!(ValueArg, ValueArg!42)); 1435 static assert( isInstantiationOf!(ValueArg, ValueArg!256)); 1436 static assert( isInstantiationOf!(ValueArg, const ValueArg!1024)); 1437 static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024)); 1438 static assert(!isInstantiationOf!(ValueArg, int)); 1439 static assert(!isInstantiationOf!(ValueArg, S!int)); 1440 1441 int i; 1442 1443 static struct AliasArg(alias Symbol) {} 1444 static assert( isInstantiationOf!(AliasArg, AliasArg!42)); 1445 static assert( isInstantiationOf!(AliasArg, AliasArg!int)); 1446 static assert( isInstantiationOf!(AliasArg, AliasArg!i)); 1447 static assert( isInstantiationOf!(AliasArg, const AliasArg!i)); 1448 static assert( isInstantiationOf!(AliasArg, shared AliasArg!i)); 1449 static assert(!isInstantiationOf!(AliasArg, int)); 1450 static assert(!isInstantiationOf!(AliasArg, S!int)); 1451 1452 // An uninstantiated template is not an instance of any template, 1453 // not even itself. 1454 static assert(!isInstantiationOf!(S, S)); 1455 static assert(!isInstantiationOf!(S, C)); 1456 static assert(!isInstantiationOf!(C, C)); 1457 static assert(!isInstantiationOf!(C, S)); 1458 1459 // Variables of a templated type are not considered instantiations of that 1460 // type. For templated types, the overload which takes a type must be used. 1461 S!int s; 1462 C!string c; 1463 static assert(!isInstantiationOf!(S, s)); 1464 static assert(!isInstantiationOf!(C, c)); 1465 } 1466 1467 // Examples of templated functions. 1468 @safe unittest 1469 { 1470 static int foo(T...)() { return 42; } 1471 static void bar(T...)(T var) {} 1472 static void baz(T)(T var) {} 1473 static bool frobozz(alias pred)(int) { return true; } 1474 1475 static assert( isInstantiationOf!(foo, foo!int)); 1476 static assert( isInstantiationOf!(foo, foo!string)); 1477 static assert( isInstantiationOf!(foo, foo!(int, string))); 1478 static assert(!isInstantiationOf!(foo, bar!int)); 1479 static assert(!isInstantiationOf!(foo, bar!string)); 1480 static assert(!isInstantiationOf!(foo, bar!(int, string))); 1481 1482 static assert( isInstantiationOf!(bar, bar!int)); 1483 static assert( isInstantiationOf!(bar, bar!string)); 1484 static assert( isInstantiationOf!(bar, bar!(int, string))); 1485 static assert(!isInstantiationOf!(bar, foo!int)); 1486 static assert(!isInstantiationOf!(bar, foo!string)); 1487 static assert(!isInstantiationOf!(bar, foo!(int, string))); 1488 1489 static assert( isInstantiationOf!(baz, baz!int)); 1490 static assert( isInstantiationOf!(baz, baz!string)); 1491 static assert(!isInstantiationOf!(baz, foo!(int, string))); 1492 1493 static assert( isInstantiationOf!(frobozz, frobozz!(a => a))); 1494 static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2))); 1495 static assert(!isInstantiationOf!(frobozz, baz!int)); 1496 1497 // Unfortunately, the function type is not considered an instantiation of 1498 // the template, because that information is not part of the type, unlike 1499 // with templated structs or classes. 1500 static assert(!isInstantiationOf!(foo, typeof(foo!int))); 1501 static assert(!isInstantiationOf!(bar, typeof(bar!int))); 1502 } 1503 1504 // Examples of templates which aren't types or functions. 1505 @safe unittest 1506 { 1507 template SingleArg(T) {} 1508 template Variadic(T...) {} 1509 template ValueArg(string s) {} 1510 template Alias(alias symbol) {} 1511 1512 static assert( isInstantiationOf!(SingleArg, SingleArg!int)); 1513 static assert( isInstantiationOf!(SingleArg, SingleArg!string)); 1514 static assert(!isInstantiationOf!(SingleArg, int)); 1515 static assert(!isInstantiationOf!(SingleArg, Variadic!int)); 1516 1517 static assert( isInstantiationOf!(Variadic, Variadic!())); 1518 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1519 static assert( isInstantiationOf!(Variadic, Variadic!string)); 1520 static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long))); 1521 static assert(!isInstantiationOf!(Variadic, int)); 1522 static assert(!isInstantiationOf!(Variadic, SingleArg!int)); 1523 1524 static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang")); 1525 static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar")); 1526 static assert(!isInstantiationOf!(ValueArg, string)); 1527 static assert(!isInstantiationOf!(ValueArg, Variadic!string)); 1528 1529 int i; 1530 1531 static assert( isInstantiationOf!(Alias, Alias!int)); 1532 static assert( isInstantiationOf!(Alias, Alias!42)); 1533 static assert( isInstantiationOf!(Alias, Alias!i)); 1534 static assert(!isInstantiationOf!(Alias, int)); 1535 static assert(!isInstantiationOf!(Alias, SingleArg!int)); 1536 } 1537 1538 /// Examples of partial instantation. 1539 @safe unittest 1540 { 1541 static struct SingleArg(T) {} 1542 static struct Variadic(T...) {} 1543 1544 alias isSingleArg = isInstantiationOf!SingleArg; 1545 alias isVariadic = isInstantiationOf!Variadic; 1546 1547 static assert( isSingleArg!(SingleArg!int)); 1548 static assert( isSingleArg!(const SingleArg!int)); 1549 static assert(!isSingleArg!int); 1550 static assert(!isSingleArg!(Variadic!int)); 1551 1552 static assert( isVariadic!(Variadic!())); 1553 static assert( isVariadic!(Variadic!int)); 1554 static assert( isVariadic!(shared Variadic!int)); 1555 static assert( isVariadic!(Variadic!(int, string))); 1556 static assert(!isVariadic!int); 1557 static assert(!isVariadic!(SingleArg!int)); 1558 1559 T foo(T)(T t) { return t; } 1560 T likeFoo(T)(T t) { return t; } 1561 bool bar(alias pred)(int i) { return pred(i); } 1562 1563 alias isFoo = isInstantiationOf!foo; 1564 alias isBar = isInstantiationOf!bar; 1565 1566 static assert( isFoo!(foo!int)); 1567 static assert( isFoo!(foo!string)); 1568 static assert(!isFoo!int); 1569 static assert(!isFoo!(likeFoo!int)); 1570 static assert(!isFoo!(bar!(a => true))); 1571 1572 static assert( isBar!(bar!(a => true))); 1573 static assert( isBar!(bar!(a => a > 2))); 1574 static assert(!isBar!int); 1575 static assert(!isBar!(foo!int)); 1576 static assert(!isBar!(likeFoo!int)); 1577 } 1578 1579 /++ 1580 Evaluates to an $(D AliasSeq) containing the members of an enum type. 1581 1582 The elements of the $(D AliasSeq) are in the same order as they are in the 1583 enum declaration. 1584 1585 An enum can have multiple members with the same value, so if code needs the 1586 enum values to be unique (e.g. if it's generating a switch statement from 1587 them), then $(REF Unique, phobos, sys, meta) can be used to filter out the 1588 duplicate values - e.g. $(D Unique!(isEqual, EnumMembers!E)). 1589 +/ 1590 template EnumMembers(E) 1591 if (is(E == enum)) 1592 { 1593 import phobos.sys.meta : AliasSeq; 1594 1595 alias EnumMembers = AliasSeq!(); 1596 static foreach (member; __traits(allMembers, E)) 1597 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, member)); 1598 } 1599 1600 /// Create an array of enum values. 1601 @safe unittest 1602 { 1603 enum Sqrts : real 1604 { 1605 one = 1, 1606 two = 1.41421, 1607 three = 1.73205 1608 } 1609 auto sqrts = [EnumMembers!Sqrts]; 1610 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]); 1611 } 1612 1613 /++ 1614 A generic function $(D rank(v)) in the following example uses this template 1615 for finding a member $(D e) in an enum type $(D E). 1616 +/ 1617 @safe unittest 1618 { 1619 // Returns i if e is the i-th member of E. 1620 static size_t rank(E)(E e) 1621 if (is(E == enum)) 1622 { 1623 static foreach (i, member; EnumMembers!E) 1624 { 1625 if (e == member) 1626 return i; 1627 } 1628 assert(0, "Not an enum member"); 1629 } 1630 1631 enum Mode 1632 { 1633 read = 1, 1634 write = 2, 1635 map = 4 1636 } 1637 assert(rank(Mode.read) == 0); 1638 assert(rank(Mode.write) == 1); 1639 assert(rank(Mode.map) == 2); 1640 } 1641 1642 /// Use EnumMembers to generate a switch statement using static foreach. 1643 @safe unittest 1644 { 1645 static class Foo 1646 { 1647 string calledMethod; 1648 void foo() @safe { calledMethod = "foo"; } 1649 void bar() @safe { calledMethod = "bar"; } 1650 void baz() @safe { calledMethod = "baz"; } 1651 } 1652 1653 enum FuncName : string { foo = "foo", bar = "bar", baz = "baz" } 1654 1655 auto foo = new Foo; 1656 1657 s: final switch (FuncName.bar) 1658 { 1659 static foreach (member; EnumMembers!FuncName) 1660 { 1661 // Generate a case for each enum value. 1662 case member: 1663 { 1664 // Call foo.{enum value}(). 1665 __traits(getMember, foo, member)(); 1666 break s; 1667 } 1668 } 1669 } 1670 1671 // Since we passed FuncName.bar to the switch statement, the bar member 1672 // function was called. 1673 assert(foo.calledMethod == "bar"); 1674 } 1675 1676 @safe unittest 1677 { 1678 { 1679 enum A { a } 1680 static assert([EnumMembers!A] == [A.a]); 1681 enum B { a, b, c, d, e } 1682 static assert([EnumMembers!B] == [B.a, B.b, B.c, B.d, B.e]); 1683 } 1684 { 1685 enum A : string { a = "alpha", b = "beta" } 1686 static assert([EnumMembers!A] == [A.a, A.b]); 1687 1688 static struct S 1689 { 1690 int value; 1691 int opCmp(S rhs) const nothrow { return value - rhs.value; } 1692 } 1693 enum B : S { a = S(1), b = S(2), c = S(3) } 1694 static assert([EnumMembers!B] == [B.a, B.b, B.c]); 1695 } 1696 { 1697 enum A { a = 0, b = 0, c = 1, d = 1, e } 1698 static assert([EnumMembers!A] == [A.a, A.b, A.c, A.d, A.e]); 1699 } 1700 { 1701 enum E { member, a = 0, b = 0 } 1702 1703 static assert(__traits(isSame, EnumMembers!E[0], E.member)); 1704 static assert(__traits(isSame, EnumMembers!E[1], E.a)); 1705 static assert(__traits(isSame, EnumMembers!E[2], E.b)); 1706 1707 static assert(__traits(identifier, EnumMembers!E[0]) == "member"); 1708 static assert(__traits(identifier, EnumMembers!E[1]) == "a"); 1709 static assert(__traits(identifier, EnumMembers!E[2]) == "b"); 1710 } 1711 } 1712 1713 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums 1714 @safe unittest 1715 { 1716 static string genEnum() 1717 { 1718 string result = "enum TLAs {"; 1719 foreach (c0; '0' .. '2' + 1) 1720 { 1721 foreach (c1; '0' .. '9' + 1) 1722 { 1723 foreach (c2; '0' .. '9' + 1) 1724 { 1725 foreach (c3; '0' .. '9' + 1) 1726 { 1727 result ~= '_'; 1728 result ~= c0; 1729 result ~= c1; 1730 result ~= c2; 1731 result ~= c3; 1732 result ~= ','; 1733 } 1734 } 1735 } 1736 } 1737 result ~= '}'; 1738 return result; 1739 } 1740 mixin(genEnum); 1741 static assert(EnumMembers!TLAs[0] == TLAs._0000); 1742 static assert(EnumMembers!TLAs[$ - 1] == TLAs._2999); 1743 } 1744 1745 /++ 1746 Whether the type $(D From) is implicitly convertible to the type $(D To). 1747 1748 Note that template constraints should be very careful about when they test 1749 for implicit conversions and in general should prefer to either test for an 1750 exact set of types or for types which compile with a particular piece of 1751 code rather than being designed to accept any type which implicitly converts 1752 to a particular type. 1753 1754 This is because having a type pass a template constraint based on an 1755 implicit conversion but then not have the implicit conversion actually take 1756 place (which it won't unless the template does something to force it 1757 internally) can lead to either compilation errors or subtle behavioral 1758 differences - and even when the conversion is done explicitly within a 1759 templated function, since it's not done at the call site, it can still lead 1760 to subtle bugs in some cases (e.g. if slicing a static array is involved). 1761 1762 For situations where code needs to verify that a type is implicitly 1763 convertible based solely on its qualifiers, $(LREF isQualifierConvertible) 1764 would be a more appropriate choice than isImplicitlyConvertible. 1765 1766 Given how trivial the $(D is) expression for isImplicitlyConvertible is - 1767 $(D is(To : From)) - this trait is provided primarily so that it can be 1768 used in conjunction with templates that use a template predicate (such as 1769 many of the templates in phobos.sys.meta). 1770 1771 The single-argument overload makes it so that it can be partially 1772 instantiated with the first argument, which will often be necessary with 1773 template predicates. 1774 1775 See_Also: 1776 $(DDSUBLINK dlang.org/spec/type, implicit-conversions, Spec on implicit conversions) 1777 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 1778 $(LREF isQualifierConvertible) 1779 +/ 1780 enum isImplicitlyConvertible(From, To) = is(From : To); 1781 1782 /++ Ditto +/ 1783 template isImplicitlyConvertible(From) 1784 { 1785 enum isImplicitlyConvertible(To) = is(From : To); 1786 } 1787 1788 /// 1789 @safe unittest 1790 { 1791 static assert( isImplicitlyConvertible!(byte, long)); 1792 static assert( isImplicitlyConvertible!(ushort, long)); 1793 static assert( isImplicitlyConvertible!(int, long)); 1794 static assert( isImplicitlyConvertible!(long, long)); 1795 static assert( isImplicitlyConvertible!(ulong, long)); 1796 1797 static assert( isImplicitlyConvertible!(ubyte, int)); 1798 static assert( isImplicitlyConvertible!(short, int)); 1799 static assert( isImplicitlyConvertible!(int, int)); 1800 static assert( isImplicitlyConvertible!(uint, int)); 1801 static assert(!isImplicitlyConvertible!(long, int)); 1802 static assert(!isImplicitlyConvertible!(ulong, int)); 1803 1804 static assert(!isImplicitlyConvertible!(int, string)); 1805 static assert(!isImplicitlyConvertible!(int, int[])); 1806 static assert(!isImplicitlyConvertible!(int, int*)); 1807 1808 static assert(!isImplicitlyConvertible!(string, int)); 1809 static assert(!isImplicitlyConvertible!(int[], int)); 1810 static assert(!isImplicitlyConvertible!(int*, int)); 1811 1812 // For better or worse, bool and the built-in character types will 1813 // implicitly convert to integer or floating-point types if the target type 1814 // is large enough. Sometimes, this is desirable, whereas at other times, 1815 // it can have very surprising results, so it's one reason why code should 1816 // be very careful when testing for implicit conversions. 1817 static assert( isImplicitlyConvertible!(bool, int)); 1818 static assert( isImplicitlyConvertible!(char, int)); 1819 static assert( isImplicitlyConvertible!(wchar, int)); 1820 static assert( isImplicitlyConvertible!(dchar, int)); 1821 1822 static assert( isImplicitlyConvertible!(bool, ubyte)); 1823 static assert( isImplicitlyConvertible!(char, ubyte)); 1824 static assert(!isImplicitlyConvertible!(wchar, ubyte)); 1825 static assert(!isImplicitlyConvertible!(dchar, ubyte)); 1826 1827 static assert( isImplicitlyConvertible!(bool, double)); 1828 static assert( isImplicitlyConvertible!(char, double)); 1829 static assert( isImplicitlyConvertible!(wchar, double)); 1830 static assert( isImplicitlyConvertible!(dchar, double)); 1831 1832 // Value types can be implicitly converted regardless of their qualifiers 1833 // thanks to the fact that they're copied. 1834 static assert( isImplicitlyConvertible!(int, int)); 1835 static assert( isImplicitlyConvertible!(const int, int)); 1836 static assert( isImplicitlyConvertible!(immutable int, int)); 1837 static assert( isImplicitlyConvertible!(inout int, int)); 1838 1839 static assert( isImplicitlyConvertible!(int, const int)); 1840 static assert( isImplicitlyConvertible!(int, immutable int)); 1841 static assert( isImplicitlyConvertible!(int, inout int)); 1842 1843 // Reference types are far more restrictive about which implicit conversions 1844 // they allow, because qualifiers in D are transitive. 1845 static assert( isImplicitlyConvertible!(int*, int*)); 1846 static assert(!isImplicitlyConvertible!(const int*, int*)); 1847 static assert(!isImplicitlyConvertible!(immutable int*, int*)); 1848 1849 static assert( isImplicitlyConvertible!(int*, const int*)); 1850 static assert( isImplicitlyConvertible!(const int*, const int*)); 1851 static assert( isImplicitlyConvertible!(immutable int*, const int*)); 1852 1853 static assert(!isImplicitlyConvertible!(int*, immutable int*)); 1854 static assert(!isImplicitlyConvertible!(const int*, immutable int*)); 1855 static assert( isImplicitlyConvertible!(immutable int*, immutable int*)); 1856 1857 // Note that inout gets a bit weird, since it's only used with function 1858 // parameters, and it's a stand-in for whatever mutability qualifiers the 1859 // type actually has. So, a function parameter that's inout accepts any 1860 // mutability, but you can't actually implicitly convert to inout, because 1861 // it's unknown within the function what the actual mutability of the type 1862 // is. It will differ depending on the function arguments of a specific 1863 // call to that function, so the same code has to work with all combinations 1864 // of mutability qualifiers. 1865 static assert(!isImplicitlyConvertible!(int*, inout int*)); 1866 static assert(!isImplicitlyConvertible!(const int*, inout int*)); 1867 static assert(!isImplicitlyConvertible!(immutable int*, inout int*)); 1868 static assert( isImplicitlyConvertible!(inout int*, inout int*)); 1869 1870 static assert(!isImplicitlyConvertible!(inout int*, int*)); 1871 static assert( isImplicitlyConvertible!(inout int*, const int*)); 1872 static assert(!isImplicitlyConvertible!(inout int*, immutable int*)); 1873 1874 // Enums implicitly convert to their base type. 1875 enum E : int 1876 { 1877 a = 42 1878 } 1879 static assert( isImplicitlyConvertible!(E, int)); 1880 static assert( isImplicitlyConvertible!(E, long)); 1881 static assert(!isImplicitlyConvertible!(E, int[])); 1882 1883 // Structs only implicit convert to another type via declaring an 1884 // alias this. 1885 static struct S 1886 { 1887 int i; 1888 } 1889 static assert(!isImplicitlyConvertible!(S, int)); 1890 static assert(!isImplicitlyConvertible!(S, long)); 1891 static assert(!isImplicitlyConvertible!(S, string)); 1892 1893 static struct AliasThis 1894 { 1895 int i; 1896 alias this = i; 1897 } 1898 static assert( isImplicitlyConvertible!(AliasThis, int)); 1899 static assert( isImplicitlyConvertible!(AliasThis, long)); 1900 static assert(!isImplicitlyConvertible!(AliasThis, string)); 1901 1902 static struct AliasThis2 1903 { 1904 AliasThis at; 1905 alias this = at; 1906 } 1907 static assert( isImplicitlyConvertible!(AliasThis2, AliasThis)); 1908 static assert( isImplicitlyConvertible!(AliasThis2, int)); 1909 static assert( isImplicitlyConvertible!(AliasThis2, long)); 1910 static assert(!isImplicitlyConvertible!(AliasThis2, string)); 1911 1912 static struct AliasThis3 1913 { 1914 AliasThis2 at; 1915 alias this = at; 1916 } 1917 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2)); 1918 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis)); 1919 static assert( isImplicitlyConvertible!(AliasThis3, int)); 1920 static assert( isImplicitlyConvertible!(AliasThis3, long)); 1921 static assert(!isImplicitlyConvertible!(AliasThis3, string)); 1922 1923 // D does not support implicit conversions via construction. 1924 static struct Cons 1925 { 1926 this(int i) 1927 { 1928 this.i = i; 1929 } 1930 1931 int i; 1932 } 1933 static assert(!isImplicitlyConvertible!(int, Cons)); 1934 1935 // Classes support implicit conversion based on their class and 1936 // interface hierarchies. 1937 static interface I1 {} 1938 static class Base : I1 {} 1939 1940 static interface I2 {} 1941 static class Foo : Base, I2 {} 1942 1943 static class Bar : Base {} 1944 1945 static assert( isImplicitlyConvertible!(Base, Base)); 1946 static assert(!isImplicitlyConvertible!(Base, Foo)); 1947 static assert(!isImplicitlyConvertible!(Base, Bar)); 1948 static assert( isImplicitlyConvertible!(Base, I1)); 1949 static assert(!isImplicitlyConvertible!(Base, I2)); 1950 1951 static assert( isImplicitlyConvertible!(Foo, Base)); 1952 static assert( isImplicitlyConvertible!(Foo, Foo)); 1953 static assert(!isImplicitlyConvertible!(Foo, Bar)); 1954 static assert( isImplicitlyConvertible!(Foo, I1)); 1955 static assert( isImplicitlyConvertible!(Foo, I2)); 1956 1957 static assert( isImplicitlyConvertible!(Bar, Base)); 1958 static assert(!isImplicitlyConvertible!(Bar, Foo)); 1959 static assert( isImplicitlyConvertible!(Bar, Bar)); 1960 static assert( isImplicitlyConvertible!(Bar, I1)); 1961 static assert(!isImplicitlyConvertible!(Bar, I2)); 1962 1963 static assert(!isImplicitlyConvertible!(I1, Base)); 1964 static assert(!isImplicitlyConvertible!(I1, Foo)); 1965 static assert(!isImplicitlyConvertible!(I1, Bar)); 1966 static assert( isImplicitlyConvertible!(I1, I1)); 1967 static assert(!isImplicitlyConvertible!(I1, I2)); 1968 1969 static assert(!isImplicitlyConvertible!(I2, Base)); 1970 static assert(!isImplicitlyConvertible!(I2, Foo)); 1971 static assert(!isImplicitlyConvertible!(I2, Bar)); 1972 static assert(!isImplicitlyConvertible!(I2, I1)); 1973 static assert( isImplicitlyConvertible!(I2, I2)); 1974 1975 // Note that arrays are not implicitly convertible even when their elements 1976 // are implicitly convertible. 1977 static assert(!isImplicitlyConvertible!(ubyte[], uint[])); 1978 static assert(!isImplicitlyConvertible!(Foo[], Base[])); 1979 static assert(!isImplicitlyConvertible!(Bar[], Base[])); 1980 1981 // However, like with pointers, dynamic arrays are convertible based on 1982 // constness. 1983 static assert( isImplicitlyConvertible!(Base[], const Base[])); 1984 static assert( isImplicitlyConvertible!(Base[], const(Base)[])); 1985 static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[])); 1986 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 1987 static assert( isImplicitlyConvertible!(const Base[], const Base[])); 1988 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 1989 } 1990 1991 /++ 1992 isImplicitlyConvertible can be used with partial instantiation so that it 1993 can be passed to a template which takes a unary predicate. 1994 +/ 1995 @safe unittest 1996 { 1997 import phobos.sys.meta : AliasSeq, all, indexOf; 1998 1999 // byte is implicitly convertible to byte, short, int, and long. 2000 static assert(all!(isImplicitlyConvertible!byte, short, int, long)); 2001 2002 // const(char)[] at index 2 is the first type in the AliasSeq which string 2003 // can be implicitly converted to. 2004 alias Types = AliasSeq!(int, char[], const(char)[], string, int*); 2005 static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2); 2006 } 2007 2008 /++ 2009 Whether $(D From) is 2010 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) 2011 to $(D To). 2012 2013 This is testing whether $(D From) and $(D To) are the same type - minus the 2014 qualifiers - and whether the qualifiers on $(D From) can be implicitly 2015 converted to the qualifiers on $(D To). No other implicit conversions are 2016 taken into account. 2017 2018 For instance, $(D const int*) is not implicitly convertible to $(D int*), 2019 because that would violate $(D const). That means that $(D const) is not 2020 qualifier convertible to mutable. And as such, $(I any) $(D const) type 2021 is not qualifier convertible to a mutable type even if it's implicitly 2022 convertible. E.G. $(D const int) is implicitly convertible to $(D int), 2023 because it can be copied to avoid violating $(D const), but it's still not 2024 qualifier convertible, because $(D const) types in general cannot be 2025 implicitly converted to mutable. 2026 2027 The exact types being tested matter, because they need to be the same 2028 (minus the qualifiers) in order to be considered convertible, but beyond 2029 that, all that matters for the conversion is whether those qualifers would 2030 be convertible regardless of which types they were on. So, if you're having 2031 trouble picturing whether $(D From) would be qualifier convertible to 2032 $(D To), then consider which conversions would be allowed from $(D From[]) 2033 to $(D To[]) (and remember that dynamic arrays are only implicitly 2034 convertible based on their qualifers). 2035 2036 The $(DDSUBLINK spec/const3, implicit_qualifier_conversions, spec) provides 2037 a table of which qualifiers can be implcitly converted to which other 2038 qualifers (and of course, there a bunch of examples below). 2039 2040 So, isQualifierConvertible can be used in a case like 2041 $(D isQualifierConvertible!(ReturnType!(typeof(foo(bar))), const char), 2042 which would be testing that the return type of $(D foo(bar)) was $(D char), 2043 $(D const char), or $(D immutable char) (since those are the only types 2044 which are qualifier convertible to $(D const char)). 2045 2046 This is in contrast to 2047 $(D isImplicitlyConvertible!(ReturnType!(typeof(foo(bar))), const char), 2048 which would be $(D true) for $(I any) type which was implicitly convertible 2049 to $(D const char) rather than just $(D char), $(D const char), and 2050 $(D immutable char). 2051 2052 The single-argument overload makes it so that it can be partially 2053 instantiated with the first argument, which will often be necessary with 2054 template predicates. 2055 2056 See_Also: 2057 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 2058 $(LREF isImplicitlyConvertible) 2059 +/ 2060 enum isQualifierConvertible(From, To) = is(immutable From == immutable To) && is(From* : To*); 2061 2062 /++ Ditto +/ 2063 template isQualifierConvertible(From) 2064 { 2065 enum isQualifierConvertible(To) = is(immutable From == immutable To) && is(From* : To*); 2066 } 2067 2068 /// 2069 @safe unittest 2070 { 2071 // i.e. char* -> const char* 2072 static assert( isQualifierConvertible!(char, const char)); 2073 2074 // i.e. const char* -> char* 2075 static assert(!isQualifierConvertible!(const char, char)); 2076 2077 static assert( isQualifierConvertible!(int, int)); 2078 static assert( isQualifierConvertible!(int, const int)); 2079 static assert(!isQualifierConvertible!(int, immutable int)); 2080 2081 static assert(!isQualifierConvertible!(const int, int)); 2082 static assert( isQualifierConvertible!(const int, const int)); 2083 static assert(!isQualifierConvertible!(const int, immutable int)); 2084 2085 static assert(!isQualifierConvertible!(immutable int, int)); 2086 static assert( isQualifierConvertible!(immutable int, const int)); 2087 static assert( isQualifierConvertible!(immutable int, immutable int)); 2088 2089 // Note that inout gets a bit weird, since it's only used with function 2090 // parameters, and it's a stand-in for whatever mutability qualifiers the 2091 // type actually has. So, a function parameter that's inout accepts any 2092 // mutability, but you can't actually implicitly convert to inout, because 2093 // it's unknown within the function what the actual mutability of the type 2094 // is. It will differ depending on the function arguments of a specific 2095 // call to that function, so the same code has to work with all combinations 2096 // of mutability qualifiers. 2097 static assert(!isQualifierConvertible!(int, inout int)); 2098 static assert(!isQualifierConvertible!(const int, inout int)); 2099 static assert(!isQualifierConvertible!(immutable int, inout int)); 2100 static assert( isQualifierConvertible!(inout int, inout int)); 2101 2102 static assert(!isQualifierConvertible!(inout int, int)); 2103 static assert( isQualifierConvertible!(inout int, const int)); 2104 static assert(!isQualifierConvertible!(inout int, immutable int)); 2105 2106 // shared is of course also a qualifier. 2107 static assert(!isQualifierConvertible!(int, shared int)); 2108 static assert(!isQualifierConvertible!(int, const shared int)); 2109 static assert(!isQualifierConvertible!(const int, shared int)); 2110 static assert(!isQualifierConvertible!(const int, const shared int)); 2111 static assert(!isQualifierConvertible!(immutable int, shared int)); 2112 static assert( isQualifierConvertible!(immutable int, const shared int)); 2113 2114 static assert(!isQualifierConvertible!(shared int, int)); 2115 static assert(!isQualifierConvertible!(shared int, const int)); 2116 static assert(!isQualifierConvertible!(shared int, immutable int)); 2117 static assert( isQualifierConvertible!(shared int, shared int)); 2118 static assert( isQualifierConvertible!(shared int, const shared int)); 2119 2120 static assert(!isQualifierConvertible!(const shared int, int)); 2121 static assert(!isQualifierConvertible!(const shared int, const int)); 2122 static assert(!isQualifierConvertible!(const shared int, immutable int)); 2123 static assert(!isQualifierConvertible!(const shared int, shared int)); 2124 static assert( isQualifierConvertible!(const shared int, const shared int)); 2125 2126 // Implicit conversions don't count unless they're based purely on 2127 // qualifiers. 2128 enum E : int 2129 { 2130 a = 1 2131 } 2132 2133 static assert(!isQualifierConvertible!(E, int)); 2134 static assert(!isQualifierConvertible!(E, const int)); 2135 static assert( isQualifierConvertible!(E, E)); 2136 static assert( isQualifierConvertible!(E, const E)); 2137 static assert(!isQualifierConvertible!(E, immutable E)); 2138 2139 static struct AliasThis 2140 { 2141 int i; 2142 alias this = i; 2143 } 2144 2145 static assert(!isQualifierConvertible!(AliasThis, int)); 2146 static assert(!isQualifierConvertible!(AliasThis, const int)); 2147 static assert( isQualifierConvertible!(AliasThis, AliasThis)); 2148 static assert( isQualifierConvertible!(AliasThis, const AliasThis)); 2149 static assert(!isQualifierConvertible!(AliasThis, immutable AliasThis)); 2150 2151 // The qualifiers are irrelevant if the types aren't the same when 2152 // stripped of all qualifers. 2153 static assert(!isQualifierConvertible!(int, long)); 2154 static assert(!isQualifierConvertible!(int, const long)); 2155 static assert(!isQualifierConvertible!(string, const(ubyte)[])); 2156 } 2157 2158 /++ 2159 isQualifierConvertible can be used with partial instantiation so that it 2160 can be passed to a template which takes a unary predicate. 2161 +/ 2162 @safe unittest 2163 { 2164 import phobos.sys.meta : AliasSeq, all, indexOf; 2165 2166 // byte is qualifier convertible to byte and const byte. 2167 static assert(all!(isQualifierConvertible!byte, byte, const byte)); 2168 2169 // const(char[]) at index 2 is the first type in the AliasSeq which string 2170 // is qualifier convertible to. 2171 alias Types = AliasSeq!(int, char[], const(char[]), string, int*); 2172 static assert(indexOf!(isQualifierConvertible!string, Types) == 2); 2173 } 2174 2175 @safe unittest 2176 { 2177 import phobos.sys.meta : AliasSeq; 2178 2179 alias Types = AliasSeq!(int, const int, shared int, inout int, const shared int, 2180 const inout int, inout shared int, const inout shared int, immutable int); 2181 2182 // https://dlang.org/spec/const3.html#implicit_qualifier_conversions 2183 enum _ = 0; 2184 static immutable bool[Types.length][Types.length] conversions = [ 2185 // m c s i cs ci is cis im 2186 [1, 1, _, _, _, _, _, _, _], // mutable 2187 [_, 1, _, _, _, _, _, _, _], // const 2188 [_, _, 1, _, 1, _, _, _, _], // shared 2189 [_, 1, _, 1, _, 1, _, _, _], // inout 2190 [_, _, _, _, 1, _, _, _, _], // const shared 2191 [_, 1, _, _, _, 1, _, _, _], // const inout 2192 [_, _, _, _, 1, _, 1, 1, _], // inout shared 2193 [_, _, _, _, 1, _, _, 1, _], // const inout shared 2194 [_, 1, _, _, 1, 1, _, 1, 1], // immutable 2195 ]; 2196 2197 foreach (i, From; Types) 2198 { 2199 foreach (j, To; Types) 2200 { 2201 static assert(isQualifierConvertible!(From, To) == conversions[i][j], 2202 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`" ~ 2203 " should be `" ~ (conversions[i][j] ? "true`" : "false`")); 2204 } 2205 } 2206 } 2207 2208 /++ 2209 Whether the given values are equal per $(D ==). 2210 2211 All this does is $(D lhs == rhs) but in an eponymous template, so most code 2212 shouldn't use it. It's intended to be used in conjunction with templates 2213 that take a template predicate - such as those in phobos.sys.meta. 2214 2215 The single-argument overload makes it so that it can be partially 2216 instantiated with the first argument, which will often be necessary with 2217 template predicates. 2218 2219 Note that in most cases, even when comparing values at compile time, using 2220 isEqual makes no sense, because you can use CTFE to just compare two values 2221 (or expressions which evaluate to values), but in rare cases where you need 2222 to compare symbols in an $(D AliasSeq) by value with a template predicate 2223 while still leaving them as symbols in an $(D AliasSeq), then isEqual would 2224 be needed. 2225 2226 A prime example of this would be $(D Unique!(isEqual, EnumMembers!MyEnum)), 2227 which results in an $(D AliasSeq) containing the list of members of 2228 $(D MyEnum) but without any duplicate values (e.g. to use when doing code 2229 generation to create a final switch). 2230 2231 Alternatively, code such as $(D [EnumMembers!MyEnum].sort().unique()) could 2232 be used to get a dynamic array of the enum members with no duplicate values 2233 via CTFE, thus avoiding the need for template predicates or anything from 2234 phobos.sys.meta. However, you then have a dynamic array of enum values 2235 rather than an $(D AliasSeq) of symbols for those enum members, which 2236 affects what you can do with type introspection. So, which approach is 2237 better depends on what the code needs to do with the enum members. 2238 2239 In general, however, if code doesn't need an $(D AliasSeq), and an array of 2240 values will do the trick, then it's more efficient to operate on an array of 2241 values with CTFE and avoid using isEqual or other templates to operate on 2242 the values as an $(D AliasSeq). 2243 2244 See_Also: 2245 $(LREF isSameSymbol) 2246 $(LREF isSameType) 2247 +/ 2248 enum isEqual(alias lhs, alias rhs) = lhs == rhs; 2249 2250 /++ Ditto +/ 2251 template isEqual(alias lhs) 2252 { 2253 enum isEqual(alias rhs) = lhs == rhs; 2254 } 2255 2256 /// It acts just like ==, but it's a template. 2257 @safe unittest 2258 { 2259 enum a = 42; 2260 2261 static assert( isEqual!(a, 42)); 2262 static assert( isEqual!(20, 10 + 10)); 2263 2264 static assert(!isEqual!(a, 120)); 2265 static assert(!isEqual!(77, 19 * 7 + 2)); 2266 2267 // b cannot be read at compile time, so it won't work with isEqual. 2268 int b = 99; 2269 static assert(!__traits(compiles, isEqual!(b, 99))); 2270 } 2271 2272 /++ 2273 Comparing some of the differences between an $(D AliasSeq) of enum members 2274 and an array of enum values created from an $(D AliasSeq) of enum members. 2275 +/ 2276 @safe unittest 2277 { 2278 import phobos.sys.meta : AliasSeq, Unique; 2279 2280 enum E 2281 { 2282 a = 0, 2283 b = 22, 2284 c = 33, 2285 d = 0, 2286 e = 256, 2287 f = 33, 2288 g = 7 2289 } 2290 2291 alias uniqueMembers = Unique!(isEqual, EnumMembers!E); 2292 static assert(uniqueMembers.length == 5); 2293 2294 static assert(__traits(isSame, uniqueMembers[0], E.a)); 2295 static assert(__traits(isSame, uniqueMembers[1], E.b)); 2296 static assert(__traits(isSame, uniqueMembers[2], E.c)); 2297 static assert(__traits(isSame, uniqueMembers[3], E.e)); 2298 static assert(__traits(isSame, uniqueMembers[4], E.g)); 2299 2300 static assert(__traits(identifier, uniqueMembers[0]) == "a"); 2301 static assert(__traits(identifier, uniqueMembers[1]) == "b"); 2302 static assert(__traits(identifier, uniqueMembers[2]) == "c"); 2303 static assert(__traits(identifier, uniqueMembers[3]) == "e"); 2304 static assert(__traits(identifier, uniqueMembers[4]) == "g"); 2305 2306 // Same value but different symbol. 2307 static assert(uniqueMembers[0] == E.d); 2308 static assert(!__traits(isSame, uniqueMembers[0], E.d)); 2309 2310 // is expressions compare types, not symbols or values, and these AliasSeqs 2311 // contain the list of symbols for the enum members, not types, so the is 2312 // expression evaluates to false even though the symbols are the same. 2313 static assert(!is(uniqueMembers == AliasSeq!(E.a, E.b, E.c, E.e, E.g))); 2314 2315 // Once the members are converted to an array, the types are the same, and 2316 // the values are the same, but the symbols are not the same. Instead of 2317 // being the symbols E.a, E.b, etc., they're just values with the type E 2318 // which match the values of E.a, E.b, etc. 2319 enum arr = [uniqueMembers]; 2320 static assert(is(typeof(arr) == E[])); 2321 2322 static assert(arr == [E.a, E.b, E.c, E.e, E.g]); 2323 static assert(arr == [E.d, E.b, E.f, E.e, E.g]); 2324 2325 static assert(!__traits(isSame, arr[0], E.a)); 2326 static assert(!__traits(isSame, arr[1], E.b)); 2327 static assert(!__traits(isSame, arr[2], E.c)); 2328 static assert(!__traits(isSame, arr[3], E.e)); 2329 static assert(!__traits(isSame, arr[4], E.g)); 2330 2331 // Since arr[0] is just a value of type E, it's no longer the symbol, E.a, 2332 // even though its type is E, and its value is the same as that of E.a. And 2333 // unlike the actual members of an enum, an element of an array does not 2334 // have an identifier, so __traits(identifier, ...) doesn't work with it. 2335 static assert(!__traits(compiles, __traits(identifier, arr[0]))); 2336 2337 // Similarly, once an enum member from the AliasSeq is assigned to a 2338 // variable, __traits(identifer, ...) operates on the variable, not the 2339 // symbol from the AliasSeq or the value of the variable. 2340 auto var = uniqueMembers[0]; 2341 static assert(__traits(identifier, var) == "var"); 2342 2343 // The same with a manifest constant. 2344 enum constant = uniqueMembers[0]; 2345 static assert(__traits(identifier, constant) == "constant"); 2346 } 2347 2348 /++ 2349 Whether the given symbols are the same symbol. 2350 2351 All this does is $(D __traits(isSame, lhs, rhs)), so most code shouldn't 2352 use it. It's intended to be used in conjunction with templates that take a 2353 template predicate - such as those in phobos.sys.meta. 2354 2355 The single-argument overload makes it so that it can be partially 2356 instantiated with the first argument, which will often be necessary with 2357 template predicates. 2358 2359 See_Also: 2360 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, lhs, rhs))) 2361 $(LREF isEqual) 2362 $(LREF isSameType) 2363 +/ 2364 enum isSameSymbol(alias lhs, alias rhs) = __traits(isSame, lhs, rhs); 2365 2366 /++ Ditto +/ 2367 template isSameSymbol(alias lhs) 2368 { 2369 enum isSameSymbol(alias rhs) = __traits(isSame, lhs, rhs); 2370 } 2371 2372 /// 2373 @safe unittest 2374 { 2375 int i; 2376 int j; 2377 real r; 2378 2379 static assert( isSameSymbol!(i, i)); 2380 static assert(!isSameSymbol!(i, j)); 2381 static assert(!isSameSymbol!(i, r)); 2382 2383 static assert(!isSameSymbol!(j, i)); 2384 static assert( isSameSymbol!(j, j)); 2385 static assert(!isSameSymbol!(j, r)); 2386 2387 static assert(!isSameSymbol!(r, i)); 2388 static assert(!isSameSymbol!(r, j)); 2389 static assert( isSameSymbol!(r, r)); 2390 2391 auto foo() { return 0; } 2392 auto bar() { return 0; } 2393 2394 static assert( isSameSymbol!(foo, foo)); 2395 static assert(!isSameSymbol!(foo, bar)); 2396 static assert(!isSameSymbol!(foo, i)); 2397 2398 static assert(!isSameSymbol!(bar, foo)); 2399 static assert( isSameSymbol!(bar, bar)); 2400 static assert(!isSameSymbol!(bar, i)); 2401 2402 // Types are symbols too. However, in most cases, they should be compared 2403 // as types, not symbols (be it with is expressions or with isSameType), 2404 // because the results aren't consistent between scalar types and 2405 // user-defined types with regards to type qualifiers when they're compared 2406 // as symbols. 2407 static assert( isSameSymbol!(double, double)); 2408 static assert(!isSameSymbol!(double, const double)); 2409 static assert(!isSameSymbol!(double, int)); 2410 static assert( isSameSymbol!(Object, Object)); 2411 static assert( isSameSymbol!(Object, const Object)); 2412 2413 static assert(!isSameSymbol!(i, int)); 2414 static assert( isSameSymbol!(typeof(i), int)); 2415 2416 // Lambdas can be compared with __traits(isSame, ...), 2417 // so they can be compared with isSameSymbol. 2418 static assert( isSameSymbol!(a => a + 42, a => a + 42)); 2419 static assert(!isSameSymbol!(a => a + 42, a => a + 99)); 2420 2421 // Partial instantiation allows it to be used with templates that expect 2422 // a predicate that takes only a single argument. 2423 import phobos.sys.meta : AliasSeq, indexOf; 2424 alias Types = AliasSeq!(i, j, r, int, long, foo); 2425 static assert(indexOf!(isSameSymbol!j, Types) == 1); 2426 static assert(indexOf!(isSameSymbol!int, Types) == 3); 2427 static assert(indexOf!(isSameSymbol!bar, Types) == -1); 2428 } 2429 2430 /++ 2431 Whether the given types are the same type. 2432 2433 All this does is $(D is(T == U)), so most code shouldn't use it. It's 2434 intended to be used in conjunction with templates that take a template 2435 predicate - such as those in phobos.sys.meta. 2436 2437 The single-argument overload makes it so that it can be partially 2438 instantiated with the first argument, which will often be necessary with 2439 template predicates. 2440 2441 See_Also: 2442 $(LREF isEqual) 2443 $(LREF isSameSymbol) 2444 +/ 2445 enum isSameType(T, U) = is(T == U); 2446 2447 /++ Ditto +/ 2448 template isSameType(T) 2449 { 2450 enum isSameType(U) = is(T == U); 2451 } 2452 2453 /// 2454 @safe unittest 2455 { 2456 static assert( isSameType!(long, long)); 2457 static assert(!isSameType!(long, const long)); 2458 static assert(!isSameType!(long, string)); 2459 static assert( isSameType!(string, string)); 2460 2461 int i; 2462 real r; 2463 static assert( isSameType!(int, typeof(i))); 2464 static assert(!isSameType!(int, typeof(r))); 2465 2466 static assert(!isSameType!(real, typeof(i))); 2467 static assert( isSameType!(real, typeof(r))); 2468 2469 // Partial instantiation allows it to be used with templates that expect 2470 // a predicate that takes only a single argument. 2471 import phobos.sys.meta : AliasSeq, indexOf; 2472 alias Types = AliasSeq!(float, string, int, double); 2473 static assert(indexOf!(isSameType!int, Types) == 2); 2474 } 2475 2476 /++ 2477 Evaluates to an $(D AliasSeq) of the names (as $(D string)s) of the member 2478 variables of an aggregate type (i.e. a struct, class, interface, or union). 2479 2480 These are fields which take up memory space within an instance of the type 2481 (i.e. not enums / manifest constants, since they don't take up memory 2482 space, and not static member variables, since they don't take up memory 2483 space within an instance). 2484 2485 Hidden fields (like the virtual function table pointer or the context 2486 pointer for nested types) are not included. 2487 2488 For classes, only the direct member variables are included and not those 2489 of any base classes. 2490 2491 For interfaces, the result of FieldNames is always empty, because 2492 interfaces cannot have member variables. However, because interfaces are 2493 aggregate types, they work with FieldNames for consistency so that code 2494 that's written to work on aggregate types doesn't have to worry about 2495 whether it's dealing with an interface. 2496 2497 See_Also: 2498 $(LREF FieldSymbols) 2499 $(LREF FieldTypes) 2500 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 2501 +/ 2502 template FieldNames(T) 2503 if (isAggregateType!T) 2504 { 2505 import phobos.sys.meta : AliasSeq; 2506 2507 static if (is(T == struct) && __traits(isNested, T)) 2508 private alias Fields = AliasSeq!(T.tupleof[0 .. $ - 1]); 2509 else 2510 private alias Fields = T.tupleof; 2511 2512 alias FieldNames = AliasSeq!(); 2513 static foreach (Field; Fields) 2514 FieldNames = AliasSeq!(FieldNames, Field.stringof); 2515 } 2516 2517 /// 2518 @safe unittest 2519 { 2520 import phobos.sys.meta : AliasSeq; 2521 2522 struct S 2523 { 2524 int x; 2525 float y; 2526 } 2527 static assert(FieldNames!S == AliasSeq!("x", "y")); 2528 2529 // Since the AliasSeq contains values, all of which are of the same type, 2530 // it can be used to create a dynamic array, which would be more 2531 // efficient than operating on an AliasSeq in the cases where an 2532 // AliasSeq is not necessary. 2533 static assert([FieldNames!S] == ["x", "y"]); 2534 2535 class C 2536 { 2537 // static variables are not included. 2538 static int var; 2539 2540 // Manifest constants are not included. 2541 enum lang = "dlang"; 2542 2543 // Functions are not included, even if they're @property functions. 2544 @property int foo() { return 42; } 2545 2546 string s; 2547 int i; 2548 int[] arr; 2549 } 2550 static assert(FieldNames!C == AliasSeq!("s", "i", "arr")); 2551 2552 static assert([FieldNames!C] == ["s", "i", "arr"]); 2553 2554 // Only direct member variables are included. Member variables from any base 2555 // classes are not. 2556 class D : C 2557 { 2558 real r; 2559 } 2560 static assert(FieldNames!D == AliasSeq!"r"); 2561 2562 static assert([FieldNames!D] == ["r"]); 2563 2564 // FieldNames will always be empty for an interface, since it's not legal 2565 // for interfaces to have member variables. 2566 interface I 2567 { 2568 } 2569 static assert(FieldNames!I.length == 0); 2570 2571 union U 2572 { 2573 int i; 2574 double d; 2575 long l; 2576 S s; 2577 } 2578 static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s")); 2579 2580 static assert([FieldNames!U] == ["i", "d", "l", "s"]);; 2581 2582 // FieldNames only operates on aggregate types. 2583 static assert(!__traits(compiles, FieldNames!int)); 2584 static assert(!__traits(compiles, FieldNames!(S*))); 2585 static assert(!__traits(compiles, FieldNames!(C[]))); 2586 } 2587 2588 @safe unittest 2589 { 2590 import phobos.sys.meta : AliasSeq; 2591 2592 { 2593 static struct S0 {} 2594 static assert(FieldNames!S0.length == 0); 2595 2596 static struct S1 { int a; } 2597 static assert(FieldNames!S1 == AliasSeq!"a"); 2598 2599 static struct S2 { int a; string b; } 2600 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 2601 2602 static struct S3 { int a; string b; real c; } 2603 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 2604 } 2605 { 2606 int i; 2607 struct S0 { void foo() { i = 0; }} 2608 static assert(FieldNames!S0.length == 0); 2609 static assert(__traits(isNested, S0)); 2610 2611 struct S1 { int a; void foo() { i = 0; } } 2612 static assert(FieldNames!S1 == AliasSeq!"a"); 2613 static assert(__traits(isNested, S1)); 2614 2615 struct S2 { int a; string b; void foo() { i = 0; } } 2616 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 2617 static assert(__traits(isNested, S2)); 2618 2619 struct S3 { int a; string b; real c; void foo() { i = 0; } } 2620 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 2621 static assert(__traits(isNested, S3)); 2622 } 2623 { 2624 static class C0 {} 2625 static assert(FieldNames!C0.length == 0); 2626 2627 static class C1 { int a; } 2628 static assert(FieldNames!C1 == AliasSeq!"a"); 2629 2630 static class C2 { int a; string b; } 2631 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 2632 2633 static class C3 { int a; string b; real c; } 2634 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 2635 2636 static class D0 : C3 {} 2637 static assert(FieldNames!D0.length == 0); 2638 2639 static class D1 : C3 { bool x; } 2640 static assert(FieldNames!D1 == AliasSeq!"x"); 2641 2642 static class D2 : C3 { bool x; int* y; } 2643 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 2644 2645 static class D3 : C3 { bool x; int* y; short[] z; } 2646 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 2647 } 2648 { 2649 int i; 2650 class C0 { void foo() { i = 0; }} 2651 static assert(FieldNames!C0.length == 0); 2652 static assert(__traits(isNested, C0)); 2653 2654 class C1 { int a; void foo() { i = 0; } } 2655 static assert(FieldNames!C1 == AliasSeq!"a"); 2656 static assert(__traits(isNested, C1)); 2657 2658 class C2 { int a; string b; void foo() { i = 0; } } 2659 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 2660 static assert(__traits(isNested, C2)); 2661 2662 class C3 { int a; string b; real c; void foo() { i = 0; } } 2663 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 2664 static assert(__traits(isNested, C3)); 2665 2666 class D0 : C3 {} 2667 static assert(FieldNames!D0.length == 0); 2668 static assert(__traits(isNested, D0)); 2669 2670 class D1 : C3 { bool x; } 2671 static assert(FieldNames!D1 == AliasSeq!"x"); 2672 static assert(__traits(isNested, D1)); 2673 2674 class D2 : C3 { bool x; int* y; } 2675 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 2676 static assert(__traits(isNested, D2)); 2677 2678 class D3 : C3 { bool x; int* y; short[] z; } 2679 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 2680 static assert(__traits(isNested, D3)); 2681 } 2682 { 2683 static union U0 {} 2684 static assert(FieldNames!U0.length == 0); 2685 2686 static union U1 { int a; } 2687 static assert(FieldNames!U1 == AliasSeq!"a"); 2688 2689 static union U2 { int a; string b; } 2690 static assert(FieldNames!U2 == AliasSeq!("a", "b")); 2691 2692 static union U3 { int a; string b; real c; } 2693 static assert(FieldNames!U3 == AliasSeq!("a", "b", "c")); 2694 } 2695 { 2696 static struct S 2697 { 2698 enum e = 42; 2699 static str = "foobar"; 2700 2701 string name() { return "foo"; } 2702 2703 int[] arr; 2704 2705 struct Inner1 { int i; } 2706 2707 static struct Inner2 { long gnol; } 2708 2709 union { int a; string b; } 2710 2711 alias Foo = Inner1; 2712 } 2713 2714 static assert(FieldNames!S == AliasSeq!("arr", "a", "b")); 2715 static assert(FieldNames!(const S) == AliasSeq!("arr", "a", "b")); 2716 static assert(FieldNames!(S.Inner1) == AliasSeq!"i"); 2717 static assert(FieldNames!(S.Inner2) == AliasSeq!"gnol"); 2718 } 2719 } 2720 2721 /++ 2722 Evaluates to an $(D AliasSeq) of the symbols for the member variables of an 2723 aggregate type (i.e. a struct, class, interface, or union). 2724 2725 These are fields which take up memory space within an instance of the type 2726 (i.e. not enums / manifest constants, since they don't take up memory 2727 space, and not static member variables, since they don't take up memory 2728 space within an instance). 2729 2730 Hidden fields (like the virtual function table pointer or the context 2731 pointer for nested types) are not included. 2732 2733 For classes, only the direct member variables are included and not those 2734 of any base classes. 2735 2736 For interfaces, the result of FieldSymbols is always empty, because 2737 interfaces cannot have member variables. However, because interfaces are 2738 aggregate types, they work with FieldSymbols for consistency so that code 2739 that's written to work on aggregate types doesn't have to worry about 2740 whether it's dealing with an interface. 2741 2742 In most cases, $(D FieldSymbols!T) has the same result as $(D T.tupleof). 2743 The difference is that for nested structs with a context pointer, 2744 $(D T.tupleof) includes the context pointer, whereas $(D FieldSymbols!T) 2745 does not. For non-nested structs, and for classes, interfaces, and unions, 2746 $(D FieldSymbols!T) and $(D T.tupleof) are the same. 2747 2748 So, for most cases, $(D T.tupleof) is sufficient and avoids instantiating 2749 an additional template, but FieldSymbols is provided so that the code that 2750 needs to avoid including context pointers in the list of fields can do so 2751 without the programmer having to figure how to do that correctly. It also 2752 provides a template that's equivalent to what $(LREF FieldNames) and 2753 $(LREF FieldTypes) do in terms of which fields it gives (the difference of 2754 course then being whether you get the symbols, names, or types for the 2755 fields), whereas the behavior for $(D tupleof) is subtly different. 2756 2757 See_Also: 2758 $(LREF FieldNames) 2759 $(LREF FieldTypes) 2760 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 2761 $(DDSUBLINK spec/traits, isNested, $(D __traits(isNested, ...))). 2762 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, ...))). 2763 +/ 2764 template FieldSymbols(T) 2765 if (isAggregateType!T) 2766 { 2767 static if (is(T == struct) && __traits(isNested, T)) 2768 { 2769 import phobos.sys.meta : AliasSeq; 2770 alias FieldSymbols = AliasSeq!(T.tupleof[0 .. $ - 1]); 2771 } 2772 else 2773 alias FieldSymbols = T.tupleof; 2774 } 2775 2776 /// 2777 @safe unittest 2778 { 2779 import phobos.sys.meta : AliasSeq; 2780 2781 struct S 2782 { 2783 int x; 2784 float y; 2785 } 2786 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.x, S.y))); 2787 2788 // FieldSymbols!S and S.tupleof are the same, because S is not nested. 2789 static assert(__traits(isSame, FieldSymbols!S, S.tupleof)); 2790 2791 // Note that type qualifiers _should_ be passed on to the result, but due 2792 // to https://issues.dlang.org/show_bug.cgi?id=24516, they aren't. 2793 // FieldTypes does not have this problem, because it aliases the types 2794 // rather than the symbols, so if you need the types from the symbols, you 2795 // should use either FieldTypes or tupleof until the compiler bug has been 2796 // fixed (and if you use tupleof, you need to avoid aliasing the result 2797 // before getting the types from it). 2798 static assert(is(typeof(FieldSymbols!S[0]) == int)); 2799 2800 // These currently fail when they shouldn't: 2801 //static assert(is(typeof(FieldSymbols!(const S)[0]) == const int)); 2802 //static assert(is(typeof(FieldSymbols!(shared S)[0]) == shared int)); 2803 2804 class C 2805 { 2806 // static variables are not included. 2807 static int var; 2808 2809 // Manifest constants are not included. 2810 enum lang = "dlang"; 2811 2812 // Functions are not included, even if they're @property functions. 2813 @property int foo() { return 42; } 2814 2815 string s; 2816 int i; 2817 int[] arr; 2818 } 2819 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.s, C.i, C.arr))); 2820 2821 // FieldSymbols!C and C.tupleof have the same symbols, because they are 2822 // always the same for classes. 2823 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 2824 2825 // Only direct member variables are included. Member variables from any base 2826 // classes are not. 2827 class D : C 2828 { 2829 real r; 2830 } 2831 static assert(__traits(isSame, FieldSymbols!D, AliasSeq!(D.r))); 2832 static assert(__traits(isSame, FieldSymbols!D, D.tupleof)); 2833 2834 // FieldSymbols will always be empty for an interface, since it's not legal 2835 // for interfaces to have member variables. 2836 interface I 2837 { 2838 } 2839 static assert(FieldSymbols!I.length == 0); 2840 static assert(I.tupleof.length == 0); 2841 2842 union U 2843 { 2844 int i; 2845 double d; 2846 long l; 2847 S s; 2848 } 2849 static assert(__traits(isSame, FieldSymbols!U, AliasSeq!(U.i, U.d, U.l, U.s))); 2850 2851 // FieldSymbols!C and C.tupleof have the same symbols, because they are 2852 // always the same for unions. 2853 static assert(__traits(isSame, FieldSymbols!U, U.tupleof)); 2854 2855 // FieldSymbols only operates on aggregate types. 2856 static assert(!__traits(compiles, FieldSymbols!int)); 2857 static assert(!__traits(compiles, FieldSymbols!(S*))); 2858 static assert(!__traits(compiles, FieldSymbols!(C[]))); 2859 } 2860 2861 /// Some examples with nested types. 2862 @safe unittest 2863 { 2864 import phobos.sys.meta : AliasSeq; 2865 2866 int outside; 2867 2868 struct S 2869 { 2870 long l; 2871 string s; 2872 2873 void foo() { outside = 2; } 2874 } 2875 static assert(__traits(isNested, S)); 2876 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.l, S.s))); 2877 2878 // FieldSymbols!S and S.tupleof are not the same, because S is nested, and 2879 // the context pointer to the outer scope is included in S.tupleof, whereas 2880 // it is excluded from FieldSymbols!S. 2881 static assert(__traits(isSame, S.tupleof[0 .. $ - 1], AliasSeq!(S.l, S.s))); 2882 static assert(S.tupleof[$ - 1].stringof == "this"); 2883 2884 class C 2885 { 2886 bool b; 2887 int* ptr; 2888 2889 void foo() { outside = 7; } 2890 } 2891 static assert(__traits(isNested, C)); 2892 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.b, C.ptr))); 2893 2894 // FieldSymbols!C and C.tupleof have the same symbols, because they are 2895 // always the same for classes. No context pointer is provided as part of 2896 // tupleof for nested classes. 2897 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 2898 2899 // __traits(isNested, ...) is never true for interfaces or unions, since 2900 // they cannot have a context pointer to an outer scope. So, tupleof and 2901 // FieldSymbols will always be the same for interfaces and unions. 2902 } 2903 2904 @safe unittest 2905 { 2906 import phobos.sys.meta : AliasSeq; 2907 2908 { 2909 static struct S0 {} 2910 static assert(FieldSymbols!S0.length == 0); 2911 2912 static struct S1 { int a; } 2913 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 2914 2915 static struct S2 { int a; string b; } 2916 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 2917 2918 static struct S3 { int a; string b; real c; } 2919 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 2920 } 2921 { 2922 int i; 2923 struct S0 { void foo() { i = 0; }} 2924 static assert(FieldSymbols!S0.length == 0); 2925 static assert(__traits(isNested, S0)); 2926 2927 struct S1 { int a; void foo() { i = 0; } } 2928 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 2929 static assert(__traits(isNested, S1)); 2930 2931 struct S2 { int a; string b; void foo() { i = 0; } } 2932 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 2933 static assert(__traits(isNested, S2)); 2934 2935 struct S3 { int a; string b; real c; void foo() { i = 0; } } 2936 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 2937 static assert(__traits(isNested, S3)); 2938 } 2939 { 2940 static class C0 {} 2941 static assert(FieldSymbols!C0.length == 0); 2942 2943 static class C1 { int a; } 2944 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 2945 2946 static class C2 { int a; string b; } 2947 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 2948 2949 static class C3 { int a; string b; real c; } 2950 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 2951 2952 static class D0 : C3 {} 2953 static assert(FieldSymbols!D0.length == 0); 2954 2955 static class D1 : C3 { bool x; } 2956 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 2957 2958 static class D2 : C3 { bool x; int* y; } 2959 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 2960 2961 static class D3 : C3 { bool x; int* y; short[] z; } 2962 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 2963 } 2964 { 2965 int i; 2966 class C0 { void foo() { i = 0; }} 2967 static assert(FieldSymbols!C0.length == 0); 2968 static assert(__traits(isNested, C0)); 2969 2970 class C1 { int a; void foo() { i = 0; } } 2971 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 2972 static assert(__traits(isNested, C1)); 2973 2974 class C2 { int a; string b; void foo() { i = 0; } } 2975 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 2976 static assert(__traits(isNested, C2)); 2977 2978 class C3 { int a; string b; real c; void foo() { i = 0; } } 2979 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 2980 static assert(__traits(isNested, C3)); 2981 2982 class D0 : C3 {} 2983 static assert(FieldSymbols!D0.length == 0); 2984 static assert(__traits(isNested, D0)); 2985 2986 class D1 : C3 { bool x; } 2987 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 2988 static assert(__traits(isNested, D1)); 2989 2990 class D2 : C3 { bool x; int* y; } 2991 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 2992 static assert(__traits(isNested, D2)); 2993 2994 class D3 : C3 { bool x; int* y; short[] z; } 2995 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 2996 static assert(__traits(isNested, D3)); 2997 } 2998 { 2999 static union U0 {} 3000 static assert(FieldSymbols!U0.length == 0); 3001 3002 static union U1 { int a; } 3003 static assert(__traits(isSame, FieldSymbols!U1, AliasSeq!(U1.a))); 3004 3005 static union U2 { int a; string b; } 3006 static assert(__traits(isSame, FieldSymbols!U2, AliasSeq!(U2.a, U2.b))); 3007 3008 static union U3 { int a; string b; real c; } 3009 static assert(__traits(isSame, FieldSymbols!U3, AliasSeq!(U3.a, U3.b, U3.c))); 3010 } 3011 { 3012 static struct S 3013 { 3014 enum e = 42; 3015 static str = "foobar"; 3016 3017 string name() { return "foo"; } 3018 3019 int[] arr; 3020 3021 struct Inner1 { int i; } 3022 3023 static struct Inner2 { long gnol; } 3024 3025 union { int a; string b; } 3026 3027 alias Foo = Inner1; 3028 } 3029 3030 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.arr, S.a, S.b))); 3031 static assert(__traits(isSame, FieldSymbols!(const S), AliasSeq!(S.arr, S.a, S.b))); 3032 static assert(__traits(isSame, FieldSymbols!(S.Inner1), AliasSeq!(S.Inner1.i))); 3033 static assert(__traits(isSame, FieldSymbols!(S.Inner2), AliasSeq!(S.Inner2.gnol))); 3034 } 3035 } 3036 3037 /++ 3038 Evaluates to an $(D AliasSeq) of the types of the member variables of an 3039 aggregate type (i.e. a struct, class, interface, or union). 3040 3041 These are fields which take up memory space within an instance of the type 3042 (i.e. not enums / manifest constants, since they don't take up memory 3043 space, and not static member variables, since they don't take up memory 3044 space within an instance). 3045 3046 Hidden fields (like the virtual function table pointer or the context 3047 pointer for nested types) are not included. 3048 3049 For classes, only the direct member variables are included and not those 3050 of any base classes. 3051 3052 For interfaces, the result of FieldTypes is always empty, because 3053 interfaces cannot have member variables. However, because interfaces are 3054 aggregate types, they work with FieldTypes for consistency so that code 3055 that's written to work on aggregate types doesn't have to worry about 3056 whether it's dealing with an interface. 3057 3058 See_Also: 3059 $(LREF FieldNames) 3060 $(LREF FieldSymbols) 3061 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 3062 +/ 3063 template FieldTypes(T) 3064 if (isAggregateType!T) 3065 { 3066 static if (is(T == struct) && __traits(isNested, T)) 3067 alias FieldTypes = typeof(T.tupleof[0 .. $ - 1]); 3068 else 3069 alias FieldTypes = typeof(T.tupleof); 3070 } 3071 3072 /// 3073 @safe unittest 3074 { 3075 import phobos.sys.meta : AliasSeq; 3076 3077 struct S 3078 { 3079 int x; 3080 float y; 3081 } 3082 static assert(is(FieldTypes!S == AliasSeq!(int, float))); 3083 3084 // Type qualifers will be passed on to the result. 3085 static assert(is(FieldTypes!(const S) == AliasSeq!(const int, const float))); 3086 static assert(is(FieldTypes!(shared S) == AliasSeq!(shared int, shared float))); 3087 3088 class C 3089 { 3090 // static variables are not included. 3091 static int var; 3092 3093 // Manifest constants are not included. 3094 enum lang = "dlang"; 3095 3096 // Functions are not included, even if they're @property functions. 3097 @property int foo() { return 42; } 3098 3099 string s; 3100 int i; 3101 int[] arr; 3102 } 3103 static assert(is(FieldTypes!C == AliasSeq!(string, int, int[]))); 3104 3105 // Only direct member variables are included. Member variables from any base 3106 // classes are not. 3107 class D : C 3108 { 3109 real r; 3110 } 3111 static assert(is(FieldTypes!D == AliasSeq!real)); 3112 3113 // FieldTypes will always be empty for an interface, since it's not legal 3114 // for interfaces to have member variables. 3115 interface I 3116 { 3117 } 3118 static assert(FieldTypes!I.length == 0); 3119 3120 union U 3121 { 3122 int i; 3123 double d; 3124 long l; 3125 S s; 3126 } 3127 static assert(is(FieldTypes!U == AliasSeq!(int, double, long, S))); 3128 3129 // FieldTypes only operates on aggregate types. 3130 static assert(!__traits(compiles, FieldTypes!int)); 3131 static assert(!__traits(compiles, FieldTypes!(S*))); 3132 static assert(!__traits(compiles, FieldTypes!(C[]))); 3133 } 3134 3135 @safe unittest 3136 { 3137 import phobos.sys.meta : AliasSeq; 3138 3139 { 3140 static struct S0 {} 3141 static assert(FieldTypes!S0.length == 0); 3142 3143 static struct S1 { int a; } 3144 static assert(is(FieldTypes!S1 == AliasSeq!int)); 3145 3146 static struct S2 { int a; string b; } 3147 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 3148 3149 static struct S3 { int a; string b; real c; } 3150 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 3151 } 3152 { 3153 int i; 3154 struct S0 { void foo() { i = 0; }} 3155 static assert(FieldTypes!S0.length == 0); 3156 static assert(__traits(isNested, S0)); 3157 3158 struct S1 { int a; void foo() { i = 0; } } 3159 static assert(is(FieldTypes!S1 == AliasSeq!int)); 3160 static assert(__traits(isNested, S1)); 3161 3162 struct S2 { int a; string b; void foo() { i = 0; } } 3163 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 3164 static assert(__traits(isNested, S2)); 3165 3166 struct S3 { int a; string b; real c; void foo() { i = 0; } } 3167 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 3168 static assert(__traits(isNested, S3)); 3169 } 3170 { 3171 static class C0 {} 3172 static assert(FieldTypes!C0.length == 0); 3173 3174 static class C1 { int a; } 3175 static assert(is(FieldTypes!C1 == AliasSeq!int)); 3176 3177 static class C2 { int a; string b; } 3178 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 3179 3180 static class C3 { int a; string b; real c; } 3181 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 3182 3183 static class D0 : C3 {} 3184 static assert(FieldTypes!D0.length == 0); 3185 3186 static class D1 : C3 { bool x; } 3187 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 3188 3189 static class D2 : C3 { bool x; int* y; } 3190 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 3191 3192 static class D3 : C3 { bool x; int* y; short[] z; } 3193 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 3194 } 3195 { 3196 int i; 3197 class C0 { void foo() { i = 0; }} 3198 static assert(FieldTypes!C0.length == 0); 3199 static assert(__traits(isNested, C0)); 3200 3201 class C1 { int a; void foo() { i = 0; } } 3202 static assert(is(FieldTypes!C1 == AliasSeq!int)); 3203 static assert(__traits(isNested, C1)); 3204 3205 class C2 { int a; string b; void foo() { i = 0; } } 3206 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 3207 static assert(__traits(isNested, C2)); 3208 3209 class C3 { int a; string b; real c; void foo() { i = 0; } } 3210 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 3211 static assert(__traits(isNested, C3)); 3212 3213 class D0 : C3 {} 3214 static assert(FieldTypes!D0.length == 0); 3215 static assert(__traits(isNested, D0)); 3216 3217 class D1 : C3 { bool x; } 3218 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 3219 static assert(__traits(isNested, D1)); 3220 3221 class D2 : C3 { bool x; int* y; } 3222 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 3223 static assert(__traits(isNested, D2)); 3224 3225 class D3 : C3 { bool x; int* y; short[] z; } 3226 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 3227 static assert(__traits(isNested, D3)); 3228 } 3229 { 3230 static union U0 {} 3231 static assert(FieldTypes!U0.length == 0); 3232 3233 static union U1 { int a; } 3234 static assert(is(FieldTypes!U1 == AliasSeq!int)); 3235 3236 static union U2 { int a; string b; } 3237 static assert(is(FieldTypes!U2 == AliasSeq!(int, string))); 3238 3239 static union U3 { int a; string b; real c; } 3240 static assert(is(FieldTypes!U3 == AliasSeq!(int, string, real))); 3241 } 3242 { 3243 static struct S 3244 { 3245 enum e = 42; 3246 static str = "foobar"; 3247 3248 string name() { return "foo"; } 3249 3250 int[] arr; 3251 3252 struct Inner1 { int i; } 3253 3254 static struct Inner2 { long gnol; } 3255 3256 union { int a; string b; } 3257 3258 alias Foo = Inner1; 3259 } 3260 3261 static assert(is(FieldTypes!S == AliasSeq!(int[], int, string))); 3262 static assert(is(FieldTypes!(const S) == AliasSeq!(const(int[]), const int, const string))); 3263 static assert(is(FieldTypes!(S.Inner1) == AliasSeq!int)); 3264 static assert(is(FieldTypes!(S.Inner2) == AliasSeq!long)); 3265 } 3266 } 3267 3268 /++ 3269 Takes a type which is an associative array and evaluates to the type of the 3270 keys in that associative array. 3271 3272 See_Also: 3273 $(LREF ValueType) 3274 +/ 3275 alias KeyType(V : V[K], K) = K; 3276 3277 /// 3278 @safe unittest 3279 { 3280 static assert(is(KeyType!(int[string]) == string)); 3281 static assert(is(KeyType!(string[int]) == int)); 3282 3283 static assert(is(KeyType!(string[const int]) == const int)); 3284 static assert(is(KeyType!(const int[string]) == string)); 3285 3286 struct S 3287 { 3288 int i; 3289 } 3290 3291 string[S] aa1; 3292 static assert(is(KeyType!(typeof(aa1)) == S)); 3293 3294 S[string] aa2; 3295 static assert(is(KeyType!(typeof(aa2)) == string)); 3296 3297 KeyType!(typeof(aa1)) key1 = S(42); 3298 KeyType!(typeof(aa2)) key2 = "foo"; 3299 3300 // Key types with indirections have their inner layers treated as const 3301 // by the compiler, because the values of keys can't change, or the hash 3302 // value could change, putting the associative array in an invalid state. 3303 static assert(is(KeyType!(bool[string[]]) == const(string)[])); 3304 static assert(is(KeyType!(bool[int*]) == const(int)*)); 3305 3306 // If the given type is not an AA, then KeyType won't compile. 3307 static assert(!__traits(compiles, KeyType!int)); 3308 static assert(!__traits(compiles, KeyType!(int[]))); 3309 } 3310 3311 /++ 3312 Takes a type which is an associative array and evaluates to the type of the 3313 values in that associative array. 3314 3315 See_Also: 3316 $(LREF KeyType) 3317 +/ 3318 alias ValueType(V : V[K], K) = V; 3319 3320 /// 3321 @safe unittest 3322 { 3323 static assert(is(ValueType!(int[string]) == int)); 3324 static assert(is(ValueType!(string[int]) == string)); 3325 3326 static assert(is(ValueType!(string[const int]) == string)); 3327 static assert(is(ValueType!(const int[string]) == const int)); 3328 3329 struct S 3330 { 3331 int i; 3332 } 3333 3334 string[S] aa1; 3335 static assert(is(ValueType!(typeof(aa1)) == string)); 3336 3337 S[string] aa2; 3338 static assert(is(ValueType!(typeof(aa2)) == S)); 3339 3340 ValueType!(typeof(aa1)) value1 = "foo"; 3341 ValueType!(typeof(aa2)) value2 = S(42); 3342 3343 // If the given type is not an AA, then ValueType won't compile. 3344 static assert(!__traits(compiles, ValueType!int)); 3345 static assert(!__traits(compiles, ValueType!(int[]))); 3346 } 3347 3348 /++ 3349 Evaluates to the original / ultimate base type of an enum type - or for 3350 non-enum types, it evaluates to the type that it's given. 3351 3352 If the base type of the given enum type is not an enum, then the result of 3353 OriginalType is its direct base type. However, if the base type of the 3354 given enum is also an enum, then OriginalType gives the ultimate base type 3355 - that is, it keeps getting the base type for each succesive enum in the 3356 chain until it gets to a base type that isn't an enum, and that's the 3357 result. So, the result will never be an enum type. 3358 3359 If the given type has any qualifiers, the result will have those same 3360 qualifiers. 3361 +/ 3362 version (StdDdoc) template OriginalType(T) 3363 { 3364 import core.internal.traits : CoreOriginalType = OriginalType; 3365 alias OriginalType = CoreOriginalType!T; 3366 } 3367 else 3368 { 3369 import core.internal.traits : CoreOriginalType = OriginalType; 3370 alias OriginalType = CoreOriginalType; 3371 } 3372 3373 /// 3374 @safe unittest 3375 { 3376 enum E { a, b, c } 3377 static assert(is(OriginalType!E == int)); 3378 3379 enum F : E { x = E.a } 3380 static assert(is(OriginalType!F == int)); 3381 3382 enum G : F { y = F.x } 3383 static assert(is(OriginalType!G == int)); 3384 static assert(is(OriginalType!(const G) == const int)); 3385 static assert(is(OriginalType!(immutable G) == immutable int)); 3386 static assert(is(OriginalType!(shared G) == shared int)); 3387 3388 enum C : char { a = 'a', b = 'b' } 3389 static assert(is(OriginalType!C == char)); 3390 3391 enum D : string { d = "dlang" } 3392 static assert(is(OriginalType!D == string)); 3393 3394 static assert(is(OriginalType!int == int)); 3395 static assert(is(OriginalType!(const long) == const long)); 3396 static assert(is(OriginalType!string == string)); 3397 3398 // OriginalType gets the base type of enums and for all other types gives 3399 // the same type back. It does nothing special for other types - like 3400 // classes - where one could talk about the type having a base type. 3401 class Base {} 3402 class Derived : Base {} 3403 static assert(is(OriginalType!Base == Base)); 3404 static assert(is(OriginalType!Derived == Derived)); 3405 } 3406 3407 /++ 3408 Removes the outer layer of $(D const), $(D inout), or $(D immutable) 3409 from type $(D T). 3410 3411 If none of those qualifiers have been applied to the outer layer of 3412 type $(D T), then the result is $(D T). 3413 3414 For the built-in scalar types (that is $(D bool), the character types, and 3415 the numeric types), they only have one layer, so $(D const U) simply becomes 3416 $(D U). 3417 3418 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 3419 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 3420 goes from being fully $(D const) to being a mutable pointer to $(D const), 3421 and a dynamic array goes from being fully $(D const) to being a mutable 3422 dynamic array of $(D const) elements. And if there are multiple layers of 3423 pointers or arrays, it's just that outer layer which is affected - e.g. 3424 $(D const(U**)) would become $(D const(U*)*). 3425 3426 For user-defined types, the effect is that $(D const U) becomes $(D U), and 3427 how that affects member variables depends on the type of the member 3428 variable. If a member variable is explicitly marked with any mutability 3429 qualifiers, then it will continue to have those qualifiers even after 3430 Unconst has stripped all mutability qualifiers from the containing type. 3431 However, if a mutability qualifier was on the member variable only because 3432 the containing type had that qualifier, then when Unconst removes the 3433 qualifier from the containing type, it is removed from the member variable 3434 as well. 3435 3436 Also, Unconst has no effect on what a templated type is instantiated 3437 with, so if a templated type is instantiated with a template argument which 3438 has a mutability qualifier, the template instantiation will not change. 3439 +/ 3440 version (StdDdoc) template Unconst(T) 3441 { 3442 import core.internal.traits : CoreUnconst = Unconst; 3443 alias Unconst = CoreUnconst!T; 3444 } 3445 else 3446 { 3447 import core.internal.traits : CoreUnconst = Unconst; 3448 alias Unconst = CoreUnconst; 3449 } 3450 3451 /// 3452 @safe unittest 3453 { 3454 static assert(is(Unconst!( int) == int)); 3455 static assert(is(Unconst!( const int) == int)); 3456 static assert(is(Unconst!( inout int) == int)); 3457 static assert(is(Unconst!( inout const int) == int)); 3458 static assert(is(Unconst!(shared int) == shared int)); 3459 static assert(is(Unconst!(shared const int) == shared int)); 3460 static assert(is(Unconst!(shared inout int) == shared int)); 3461 static assert(is(Unconst!(shared inout const int) == shared int)); 3462 static assert(is(Unconst!( immutable int) == int)); 3463 3464 // Only the outer layer of immutable is removed. 3465 // immutable(int[]) -> immutable(int)[] 3466 alias ImmIntArr = immutable(int[]); 3467 static assert(is(Unconst!ImmIntArr == immutable(int)[])); 3468 3469 // Only the outer layer of const is removed. 3470 // immutable(int*) -> immutable(int)* 3471 alias ConstIntPtr = const(int*); 3472 static assert(is(Unconst!ConstIntPtr == const(int)*)); 3473 3474 // const(int)* -> const(int)* 3475 alias PtrToConstInt = const(int)*; 3476 static assert(is(Unconst!PtrToConstInt == const(int)*)); 3477 3478 static struct S 3479 { 3480 int* ptr; 3481 const int* cPtr; 3482 shared int* sPtr; 3483 } 3484 3485 const S s; 3486 static assert(is(typeof(s) == const S)); 3487 static assert(is(typeof(typeof(s).ptr) == const int*)); 3488 static assert(is(typeof(typeof(s).cPtr) == const int*)); 3489 static assert(is(typeof(typeof(s).sPtr) == const shared int*)); 3490 3491 // For user-defined types, all mutability qualifiers that are applied to 3492 // member variables only because the containing type has them are removed, 3493 // but the ones that are directly on those member variables remain. 3494 3495 // const S -> S 3496 static assert(is(Unconst!(typeof(s)) == S)); 3497 static assert(is(typeof(Unconst!(typeof(s)).ptr) == int*)); 3498 static assert(is(typeof(Unconst!(typeof(s)).cPtr) == const int*)); 3499 static assert(is(typeof(Unconst!(typeof(s)).sPtr) == shared int*)); 3500 3501 static struct Foo(T) 3502 { 3503 T* ptr; 3504 } 3505 3506 // The qualifier on the type is removed, but the qualifier on the template 3507 // argument is not. 3508 static assert(is(Unconst!(const(Foo!(const int))) == Foo!(const int))); 3509 static assert(is(Unconst!(Foo!(const int)) == Foo!(const int))); 3510 static assert(is(Unconst!(const(Foo!int)) == Foo!int)); 3511 } 3512 3513 /++ 3514 Removes the outer layer of $(D shared) from type $(D T). 3515 3516 If $(D shared) has not been applied to the outer layer of type $(D T), then 3517 the result is $(D T). 3518 3519 Note that while $(D immutable) is implicitly $(D shared), it is unaffected 3520 by Unshared. Only explicit $(D shared) is removed. 3521 3522 For the built-in scalar types (that is $(D bool), the character types, and 3523 the numeric types), they only have one layer, so $(D shared U) simply 3524 becomes $(D U). 3525 3526 Where the layers come in is pointers and arrays. $(D shared(U*)) becomes 3527 $(D shared(U)*), and $(D shared(U[])), becomes $(D shared(U)[]). So, a 3528 pointer goes from being fully $(D shared) to being a mutable pointer to 3529 $(D shared), and a dynamic array goes from being fully $(D shared) to being 3530 a mutable dynamic array of $(D shared) elements. And if there are multiple 3531 layers of pointers or arrays, it's just that outer layer which is affected 3532 - e.g. $(D shared(U**)) would become $(D shared(U*)*). 3533 3534 For user-defined types, the effect is that $(D shared U) becomes $(D U), 3535 and how that affects member variables depends on the type of the member 3536 variable. If a member variable is explicitly marked with $(D shared), then 3537 it will continue to be $(D shared) even after Unshared has stripped 3538 $(D shared) from the containing type. However, if $(D shared) was on the 3539 member variable only because the containing type was $(D shared), then when 3540 Unshared removes the qualifier from the containing type, it is removed from 3541 the member variable as well. 3542 3543 Also, Unshared has no effect on what a templated type is instantiated 3544 with, so if a templated type is instantiated with a template argument which 3545 has a type qualifier, the template instantiation will not change. 3546 +/ 3547 template Unshared(T) 3548 { 3549 static if (is(T == shared U, U)) 3550 alias Unshared = U; 3551 else 3552 alias Unshared = T; 3553 } 3554 3555 /// 3556 @safe unittest 3557 { 3558 static assert(is(Unshared!( int) == int)); 3559 static assert(is(Unshared!( const int) == const int)); 3560 static assert(is(Unshared!( inout int) == inout int)); 3561 static assert(is(Unshared!( inout const int) == inout const int)); 3562 static assert(is(Unshared!(shared int) == int)); 3563 static assert(is(Unshared!(shared const int) == const int)); 3564 static assert(is(Unshared!(shared inout int) == inout int)); 3565 static assert(is(Unshared!(shared inout const int) == inout const int)); 3566 static assert(is(Unshared!( immutable int) == immutable int)); 3567 3568 // Only the outer layer of shared is removed. 3569 // shared(int[]) -> shared(int)[] 3570 alias SharedIntArr = shared(int[]); 3571 static assert(is(Unshared!SharedIntArr == shared(int)[])); 3572 3573 // Only the outer layer of shared is removed. 3574 // shared(int*) -> shared(int)* 3575 alias SharedIntPtr = shared(int*); 3576 static assert(is(Unshared!SharedIntPtr == shared(int)*)); 3577 3578 // shared(int)* -> shared(int)* 3579 alias PtrToSharedInt = shared(int)*; 3580 static assert(is(Unshared!PtrToSharedInt == shared(int)*)); 3581 3582 // immutable is unaffected 3583 alias ImmutableArr = immutable(int[]); 3584 static assert(is(Unshared!ImmutableArr == immutable(int[]))); 3585 3586 static struct S 3587 { 3588 int* ptr; 3589 const int* cPtr; 3590 shared int* sPtr; 3591 } 3592 3593 shared S s; 3594 static assert(is(typeof(s) == shared S)); 3595 static assert(is(typeof(typeof(s).ptr) == shared int*)); 3596 static assert(is(typeof(typeof(s).cPtr) == const shared int*)); 3597 static assert(is(typeof(typeof(s).sPtr) == shared int*)); 3598 3599 // For user-defined types, if shared is applied to a member variable only 3600 // because the containing type is shared, then shared is removed from that 3601 // member variable, but if the member variable is directly marked as shared, 3602 // then it continues to be shared. 3603 3604 // shared S -> S 3605 static assert(is(Unshared!(typeof(s)) == S)); 3606 static assert(is(typeof(Unshared!(typeof(s)).ptr) == int*)); 3607 static assert(is(typeof(Unshared!(typeof(s)).cPtr) == const int*)); 3608 static assert(is(typeof(Unshared!(typeof(s)).sPtr) == shared int*)); 3609 3610 static struct Foo(T) 3611 { 3612 T* ptr; 3613 } 3614 3615 // The qualifier on the type is removed, but the qualifier on the template 3616 // argument is not. 3617 static assert(is(Unshared!(shared(Foo!(shared int))) == Foo!(shared int))); 3618 static assert(is(Unshared!(Foo!(shared int)) == Foo!(shared int))); 3619 static assert(is(Unshared!(shared(Foo!int)) == Foo!int)); 3620 } 3621 3622 /++ 3623 Removes the outer layer of all type qualifiers from type $(D T) - this 3624 includes $(D shared). 3625 3626 If no type qualifiers have been applied to the outer layer of type $(D T), 3627 then the result is $(D T). 3628 3629 For the built-in scalar types (that is $(D bool), the character types, and 3630 the numeric types), they only have one layer, so $(D const U) simply becomes 3631 $(D U). 3632 3633 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 3634 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 3635 goes from being fully $(D const) to being a mutable pointer to $(D const), 3636 and a dynamic array goes from being fully $(D const) to being a mutable 3637 dynamic array of $(D const) elements. And if there are multiple layers of 3638 pointers or arrays, it's just that outer layer which is affected - e.g. 3639 $(D shared(U**)) would become $(D shared(U*)*). 3640 3641 For user-defined types, the effect is that $(D const U) becomes $(D U), and 3642 how that affects member variables depends on the type of the member 3643 variable. If a member variable is explicitly marked with any qualifiers, 3644 then it will continue to have those qualifiers even after Unqualified has 3645 stripped all qualifiers from the containing type. However, if a qualifier 3646 was on the member variable only because the containing type had that 3647 qualifier, then when Unqualified removes the qualifier from the containing 3648 type, it is removed from the member variable as well. 3649 3650 Also, Unqualified has no effect on what a templated type is instantiated 3651 with, so if a templated type is instantiated with a template argument which 3652 has a type qualifier, the template instantiation will not change. 3653 3654 Note that in most cases, $(LREF Unconst) or $(LREF Unshared) should be used 3655 rather than Unqualified, because in most cases, code is not designed to 3656 work with $(D shared) and thus doing type checks which remove $(D shared) 3657 will allow $(D shared) types to pass template constraints when they won't 3658 actually work with the code. And when code is designed to work with 3659 $(D shared), it's often the case that the type checks need to take 3660 $(D const) into account in order to avoid accidentally mutating $(D const) 3661 data and violating the type system. 3662 3663 In particular, historically, a lot of D code has used 3664 $(REF Unqual, std, traits) (which is equivalent to phobos.sys.traits' 3665 Unqualified) when the programmer's intent was to remove $(D const), and 3666 $(D shared) wasn't actually considered at all. And in such cases, the code 3667 really should use $(LREF Unconst) instead. 3668 3669 But of course, if a template constraint or $(D static if) really needs to 3670 strip off both the mutability qualifiers and $(D shared) for what it's 3671 testing for, then that's what Unqualified is for. It's just that it's best 3672 practice to use $(LREF Unconst) when it's not clear that $(D shared) should 3673 be removed as well. 3674 +/ 3675 version (StdDdoc) template Unqualified(T) 3676 { 3677 import core.internal.traits : CoreUnqualified = Unqual; 3678 alias Unqualified = CoreUnqualified!(T); 3679 } 3680 else 3681 { 3682 import core.internal.traits : CoreUnqualified = Unqual; 3683 alias Unqualified = CoreUnqualified; 3684 } 3685 3686 /// 3687 @safe unittest 3688 { 3689 static assert(is(Unqualified!( int) == int)); 3690 static assert(is(Unqualified!( const int) == int)); 3691 static assert(is(Unqualified!( inout int) == int)); 3692 static assert(is(Unqualified!( inout const int) == int)); 3693 static assert(is(Unqualified!(shared int) == int)); 3694 static assert(is(Unqualified!(shared const int) == int)); 3695 static assert(is(Unqualified!(shared inout int) == int)); 3696 static assert(is(Unqualified!(shared inout const int) == int)); 3697 static assert(is(Unqualified!( immutable int) == int)); 3698 3699 // Only the outer layer of immutable is removed. 3700 // immutable(int[]) -> immutable(int)[] 3701 alias ImmIntArr = immutable(int[]); 3702 static assert(is(Unqualified!ImmIntArr == immutable(int)[])); 3703 3704 // Only the outer layer of const is removed. 3705 // const(int*) -> const(int)* 3706 alias ConstIntPtr = const(int*); 3707 static assert(is(Unqualified!ConstIntPtr == const(int)*)); 3708 3709 // const(int)* -> const(int)* 3710 alias PtrToConstInt = const(int)*; 3711 static assert(is(Unqualified!PtrToConstInt == const(int)*)); 3712 3713 // Only the outer layer of shared is removed. 3714 // shared(int*) -> shared(int)* 3715 alias SharedIntPtr = shared(int*); 3716 static assert(is(Unqualified!SharedIntPtr == shared(int)*)); 3717 3718 // shared(int)* -> shared(int)* 3719 alias PtrToSharedInt = shared(int)*; 3720 static assert(is(Unqualified!PtrToSharedInt == shared(int)*)); 3721 3722 // Both const and shared are removed from the outer layer. 3723 // shared const int[] -> shared(const(int))[] 3724 alias SharedConstIntArr = shared const(int[]); 3725 static assert(is(Unqualified!SharedConstIntArr == shared(const(int))[])); 3726 3727 static struct S 3728 { 3729 int* ptr; 3730 const int* cPtr; 3731 shared int* sPtr; 3732 } 3733 3734 shared const S s; 3735 static assert(is(typeof(s) == shared const S)); 3736 static assert(is(typeof(typeof(s).ptr) == shared const int*)); 3737 static assert(is(typeof(typeof(s).cPtr) == shared const int*)); 3738 static assert(is(typeof(typeof(s).sPtr) == shared const int*)); 3739 3740 // For user-defined types, all qualifiers that are applied to member 3741 // variables only because the containing type has them are removed, but the 3742 // ones that are directly on those member variables remain. 3743 3744 // shared const S -> S 3745 static assert(is(Unqualified!(typeof(s)) == S)); 3746 static assert(is(typeof(Unqualified!(typeof(s)).ptr) == int*)); 3747 static assert(is(typeof(Unqualified!(typeof(s)).cPtr) == const int*)); 3748 static assert(is(typeof(Unqualified!(typeof(s)).sPtr) == shared int*)); 3749 3750 static struct Foo(T) 3751 { 3752 T* ptr; 3753 } 3754 3755 // The qualifiers on the type are removed, but the qualifiers on the 3756 // template argument are not. 3757 static assert(is(Unqualified!(const(Foo!(const int))) == Foo!(const int))); 3758 static assert(is(Unqualified!(Foo!(const int)) == Foo!(const int))); 3759 static assert(is(Unqualified!(const(Foo!int)) == Foo!int)); 3760 } 3761 3762 /++ 3763 Applies $(D const) to the given type. 3764 3765 This is primarily useful in conjunction with templates that take a template 3766 predicate (such as many of the templates in phobos.sys.meta), since while in 3767 most cases, you can simply do $(D const T) or $(D const(T)) to make $(D T) 3768 $(D const), with something like $(REF Map, phobos, sys, meta), you need to 3769 pass a template to be applied. 3770 3771 See_Also: 3772 $(LREF ImmutableOf) 3773 $(LREF InoutOf) 3774 $(LREF SharedOf) 3775 +/ 3776 alias ConstOf(T) = const T; 3777 3778 /// 3779 @safe unittest 3780 { 3781 static assert(is(ConstOf!int == const int)); 3782 static assert(is(ConstOf!(const int) == const int)); 3783 static assert(is(ConstOf!(inout int) == inout const int)); 3784 static assert(is(ConstOf!(shared int) == const shared int)); 3785 3786 // Note that const has no effect on immutable. 3787 static assert(is(ConstOf!(immutable int) == immutable int)); 3788 3789 import phobos.sys.meta : AliasSeq, Map; 3790 3791 alias Types = AliasSeq!(int, long, 3792 bool*, ubyte[], 3793 string, immutable(string)); 3794 alias WithConst = Map!(ConstOf, Types); 3795 static assert(is(WithConst == 3796 AliasSeq!(const int, const long, 3797 const(bool*), const(ubyte[]), 3798 const(string), immutable(string)))); 3799 } 3800 3801 /++ 3802 Applies $(D immutable) to the given type. 3803 3804 This is primarily useful in conjunction with templates that take a template 3805 predicate (such as many of the templates in phobos.sys.meta), since while in 3806 most cases, you can simply do $(D immutable T) or $(D immutable(T)) to make 3807 $(D T) $(D immutable), with something like $(REF Map, phobos, sys, meta), 3808 you need to pass a template to be applied. 3809 3810 See_Also: 3811 $(LREF ConstOf) 3812 $(LREF InoutOf) 3813 $(LREF SharedOf) 3814 +/ 3815 alias ImmutableOf(T) = immutable T; 3816 3817 /// 3818 @safe unittest 3819 { 3820 static assert(is(ImmutableOf!int == immutable int)); 3821 3822 // Note that immutable overrides const and inout. 3823 static assert(is(ImmutableOf!(const int) == immutable int)); 3824 static assert(is(ImmutableOf!(inout int) == immutable int)); 3825 3826 // Note that immutable overrides shared, since immutable is implicitly 3827 // shared. 3828 static assert(is(ImmutableOf!(shared int) == immutable int)); 3829 3830 static assert(is(ImmutableOf!(immutable int) == immutable int)); 3831 3832 import phobos.sys.meta : AliasSeq, Map; 3833 3834 alias Types = AliasSeq!(int, long, 3835 bool*, ubyte[], 3836 string, immutable(string)); 3837 alias WithImmutable = Map!(ImmutableOf, Types); 3838 static assert(is(WithImmutable == 3839 AliasSeq!(immutable int, immutable long, 3840 immutable(bool*), immutable(ubyte[]), 3841 immutable(string), immutable(string)))); 3842 } 3843 3844 /++ 3845 Applies $(D inout) to the given type. 3846 3847 This is primarily useful in conjunction with templates that take a template 3848 predicate (such as many of the templates in phobos.sys.meta), since while in 3849 most cases, you can simply do $(D inout T) or $(D inout(T)) to make $(D T) 3850 $(D inout), with something like $(REF Map, phobos, sys, meta), you need to 3851 pass a template to be applied. 3852 3853 See_Also: 3854 $(LREF ConstOf) 3855 $(LREF ImmutableOf) 3856 $(LREF SharedOf) 3857 +/ 3858 alias InoutOf(T) = inout T; 3859 3860 /// 3861 @safe unittest 3862 { 3863 static assert(is(InoutOf!int == inout int)); 3864 static assert(is(InoutOf!(const int) == inout const int)); 3865 static assert(is(InoutOf!(inout int) == inout int)); 3866 static assert(is(InoutOf!(shared int) == inout shared int)); 3867 3868 // Note that inout has no effect on immutable. 3869 static assert(is(InoutOf!(immutable int) == immutable int)); 3870 3871 import phobos.sys.meta : AliasSeq, Map; 3872 3873 alias Types = AliasSeq!(int, long, 3874 bool*, ubyte[], 3875 string, immutable(string)); 3876 alias WithInout = Map!(InoutOf, Types); 3877 static assert(is(WithInout == 3878 AliasSeq!(inout int, inout long, 3879 inout(bool*), inout(ubyte[]), 3880 inout(string), immutable(string)))); 3881 } 3882 3883 /++ 3884 Applies $(D shared) to the given type. 3885 3886 This is primarily useful in conjunction with templates that take a template 3887 predicate (such as many of the templates in phobos.sys.meta), since while in 3888 most cases, you can simply do $(D shared T) or $(D shared(T)) to make $(D T) 3889 $(D shared), with something like $(REF Map, phobos, sys, meta), you need to 3890 pass a template to be applied. 3891 3892 See_Also: 3893 $(LREF ConstOf) 3894 $(LREF ImmutableOf) 3895 $(LREF InoutOf) 3896 +/ 3897 alias SharedOf(T) = shared T; 3898 3899 /// 3900 @safe unittest 3901 { 3902 static assert(is(SharedOf!int == shared int)); 3903 static assert(is(SharedOf!(const int) == const shared int)); 3904 static assert(is(SharedOf!(inout int) == inout shared int)); 3905 static assert(is(SharedOf!(shared int) == shared int)); 3906 3907 // Note that shared has no effect on immutable, since immutable is 3908 // implicitly shared. 3909 static assert(is(SharedOf!(immutable int) == immutable int)); 3910 3911 import phobos.sys.meta : AliasSeq, Map; 3912 3913 alias Types = AliasSeq!(int, long, 3914 bool*, ubyte[], 3915 string, immutable(string)); 3916 alias WithShared = Map!(SharedOf, Types); 3917 static assert(is(WithShared == 3918 AliasSeq!(shared int, shared long, 3919 shared(bool*), shared(ubyte[]), 3920 shared(string), immutable(string)))); 3921 } 3922 3923 // Needed for rvalueOf/lvalueOf because 3924 // "inout on return means inout must be on a parameter as well" 3925 private struct __InoutWorkaroundStruct {} 3926 3927 /++ 3928 Creates an lvalue or rvalue of type T to be used in conjunction with 3929 $(D is(typeof(...))) or 3930 $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))). 3931 3932 The idea is that some traits or other forms of conditional compilation need 3933 to verify that a particular piece of code compiles with an rvalue or an 3934 lvalue of a specific type, and these $(D @property) functions allow you to 3935 get an rvalue or lvalue of a specific type to use within an expression that 3936 is then tested to see whether it compiles. 3937 3938 They're $(D @property) functions so that using $(D typeof) on them gives 3939 the return type rather than the type of the function. 3940 3941 Note that these functions are $(I not) defined, so if they're actually used 3942 outside of type introspection, they'll result in linker errors. They're 3943 entirely for testing that a particular piece of code compiles with an rvalue 3944 or lvalue of the given type. 3945 3946 The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that 3947 these work when the given type has the $(D inout) qualifier, since the 3948 language requires that a function that returns an $(D inout) type also have 3949 an $(D inout) type as a parameter. It should just be ignored. 3950 +/ 3951 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 3952 3953 /++ Ditto +/ 3954 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 3955 3956 /// 3957 @safe unittest 3958 { 3959 static int foo(int); 3960 static assert(is(typeof(foo(lvalueOf!int)) == int)); 3961 static assert(is(typeof(foo(rvalueOf!int)) == int)); 3962 3963 static bool bar(ref int); 3964 static assert(is(typeof(bar(lvalueOf!int)) == bool)); 3965 static assert(!is(typeof(bar(rvalueOf!int)))); 3966 3967 static assert( is(typeof({ lvalueOf!int = 42; }))); 3968 static assert(!is(typeof({ rvalueOf!int = 42; }))); 3969 3970 static struct S {} 3971 static assert( is(typeof({ lvalueOf!S = S.init; }))); 3972 static assert(!is(typeof({ rvalueOf!S = S.init; }))); 3973 3974 static struct NoAssign 3975 { 3976 @disable void opAssign(ref NoAssign); 3977 } 3978 static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; }))); 3979 static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; }))); 3980 } 3981 3982 @system unittest 3983 { 3984 import phobos.sys.meta : AliasSeq; 3985 3986 void needLvalue(T)(ref T); 3987 static struct S {} 3988 int i; 3989 struct Nested { void f() { ++i; } } 3990 3991 static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object)) 3992 { 3993 static assert(!__traits(compiles, needLvalue(rvalueOf!T))); 3994 static assert( __traits(compiles, needLvalue(lvalueOf!T))); 3995 static assert(is(typeof(rvalueOf!T) == T)); 3996 static assert(is(typeof(lvalueOf!T) == T)); 3997 } 3998 3999 static assert(!__traits(compiles, rvalueOf!int = 1)); 4000 static assert( __traits(compiles, lvalueOf!byte = 127)); 4001 static assert(!__traits(compiles, lvalueOf!byte = 128)); 4002 }