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 $(LREF hasComplexAssignment) 82 $(LREF hasComplexCopying) 83 $(LREF hasComplexDestruction) 84 $(LREF hasIndirections) 85 )) 86 $(TR $(TD General Types) $(TD 87 $(LREF KeyType) 88 $(LREF OriginalType) 89 $(LREF ValueType) 90 )) 91 $(TR $(TD Traits for removing type qualfiers) $(TD 92 $(LREF Unconst) 93 $(LREF Unshared) 94 $(LREF Unqualified) 95 )) 96 $(TR $(TD Type Constructors) $(TD 97 $(LREF ConstOf) 98 $(LREF ImmutableOf) 99 $(LREF InoutOf) 100 $(LREF SharedOf) 101 )) 102 $(TR $(TD Misc) $(TD 103 $(LREF lvalueOf) 104 $(LREF rvalueOf) 105 )) 106 ) 107 108 Copyright: Copyright The D Language Foundation 2005 - 2024. 109 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 110 Authors: $(HTTP jmdavisprog.com, Jonathan M Davis) 111 $(HTTP digitalmars.com, Walter Bright), 112 Tomasz Stachowiak (`isExpressions`), 113 $(HTTP erdani.org, Andrei Alexandrescu), 114 Shin Fujishiro, 115 $(HTTP octarineparrot.com, Robert Clipsham), 116 $(HTTP klickverbot.at, David Nadlinger), 117 Kenji Hara, 118 Shoichi Kato 119 Source: $(PHOBOSSRC phobos/sys/traits) 120 +/ 121 module phobos.sys.traits; 122 123 /++ 124 Whether the given type is an "aggregate type" - i.e. a struct, class, 125 interface, or union. Enum types whose base type is an aggregate type are 126 also considered aggregate types. 127 +/ 128 template isAggregateType(T) 129 { 130 static if (is(T == enum)) 131 enum isAggregateType = isAggregateType!(OriginalType!T); 132 else 133 enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union); 134 } 135 136 /// 137 @safe unittest 138 { 139 struct S {} 140 class C {} 141 interface I {} 142 union U {} 143 144 static assert( isAggregateType!S); 145 static assert( isAggregateType!C); 146 static assert( isAggregateType!I); 147 static assert( isAggregateType!U); 148 static assert( isAggregateType!(const S)); 149 static assert( isAggregateType!(shared C)); 150 151 static assert(!isAggregateType!int); 152 static assert(!isAggregateType!string); 153 static assert(!isAggregateType!(S*)); 154 static assert(!isAggregateType!(C[])); 155 static assert(!isAggregateType!(I[string])); 156 157 enum ES : S { a = S.init } 158 enum EC : C { a = C.init } 159 enum EI : I { a = I.init } 160 enum EU : U { a = U.init } 161 162 static assert( isAggregateType!ES); 163 static assert( isAggregateType!EC); 164 static assert( isAggregateType!EI); 165 static assert( isAggregateType!EU); 166 static assert( isAggregateType!(const ES)); 167 static assert( isAggregateType!(const EC)); 168 } 169 170 /++ 171 Whether the given type is a dynamic array (or what is sometimes referred to 172 as a slice, since a dynamic array in D is a slice of memory). 173 174 Note that this does not include implicit conversions or enum types. The 175 type itself must be a dynamic array. 176 177 Remember that D's dynamic arrays are essentially: 178 --- 179 struct DynamicArray(T) 180 { 181 size_t length; 182 T* ptr; 183 } 184 --- 185 where $(D ptr) points to the first element in the array, and $(D length) is 186 the number of elements in the array. 187 188 A dynamic array is not a pointer (unlike arrays in C/C++), and its elements 189 do not live inside the dynamic array itself. The dynamic array is simply a 190 slice of memory and does not own or manage its own memory. It can be a 191 slice of any piece of memory, including GC-allocated memory, the stack, 192 malloc-ed memory, etc. (with what kind of memory it is of course being 193 determined by how the dynamic array was created in the first place) 194 - though if you do any operations on it which end up requiring allocation 195 (e.g. appending to it if it doesn't have the capacity to expand in-place, 196 which it won't if it isn't a slice of GC-allocated memory), then that 197 reallocation will result in the dynamic array being a slice of newly 198 allocated, GC-backed memory (regardless of what it was a slice of before), 199 since it's the GC that deals with those allocations. 200 201 As long as code just accesses the elements or members of the dynamic array 202 - or reduces its length so that it's a smaller slice - it will continue to 203 point to whatever block of memory it pointed to originally. And because the 204 GC makes sure that appending to a dynamic array does not stomp on the 205 memory of any other dynamic arrays, appending to a dynamic array will not 206 affect any other dynamic array which is a slice of that same block of 207 memory whether a reallocation occurs or not. 208 209 Regardless, since what allocated the memory that the dynamic array is a 210 slice of is irrevelant to the type of the dynamic array, whether a given 211 type is a dynamic array has nothing to do with the kind of memory that's 212 backing it. A dynamic array which is a slice of a static array of $(D int) 213 is the the same type as a dynamic array of $(D int) allocated with $(D new) 214 - i.e. both are $(D int[]). So, this trait will not tell you anything about 215 what kind of memory a dynamic array is a slice of. It just tells you 216 whether the type is a dynamic array or not. 217 218 If for some reason, it matters for a function what kind of memory backs one 219 of its parameters which is a dynamic array, or it needs to be made clear 220 whether the function will possibly cause that dynamic array to be 221 reallocated, then that needs to be indicated by the documentation and 222 cannot be enforced with a template constraint. A template constraint can 223 enforce that a type used with a template meets certain criteria (e.g. that 224 it's a dynamic array), but it cannot enforce anything about how the 225 template actually uses the type. 226 227 However, it $(D is) possible to enforce that a function doesn't use any 228 operations on a dynamic array which might cause it to be reallocated by 229 marking that function as $(D @nogc). 230 231 In most cases though, code can be written to not care what kind of memory 232 backs a dynamic array, because none of the operations on a dynamic array 233 actually care what kind of memory it's a slice of. It mostly just matters 234 when you need to track the lifetime of the memory, because it wasn't 235 allocated by the GC, or when it matters whether a dynamic array could be 236 reallocated or not (e.g. because the code needs to have that dynamic array 237 continue to point to the same block of memory). 238 239 See_Also: 240 $(LREF isPointer) 241 $(LREF isStaticArray) 242 $(DDSUBLINK spec/arrays, , The language spec for arrays) 243 +/ 244 enum isDynamicArray(T) = is(T == U[], U); 245 246 /// 247 @safe unittest 248 { 249 // Some types which are dynamic arrays. 250 static assert( isDynamicArray!(int[])); 251 static assert( isDynamicArray!(const int[])); 252 static assert( isDynamicArray!(inout int[])); 253 static assert( isDynamicArray!(shared(int)[])); 254 static assert( isDynamicArray!string); 255 256 static assert( isDynamicArray!(typeof([1, 2, 3]))); 257 static assert( isDynamicArray!(typeof("dlang"))); 258 259 int[] arr; 260 static assert( isDynamicArray!(typeof(arr))); 261 262 // Some types which aren't dynamic arrays. 263 static assert(!isDynamicArray!int); 264 static assert(!isDynamicArray!(int*)); 265 static assert(!isDynamicArray!real); 266 267 static struct S 268 { 269 int[] arr; 270 } 271 static assert(!isDynamicArray!S); 272 273 // The struct itself isn't considered a dynamic array, 274 // but its member variable is when checked directly. 275 static assert( isDynamicArray!(typeof(S.arr))); 276 277 // Static arrays. 278 static assert(!isDynamicArray!(int[5])); 279 static assert(!isDynamicArray!(const(int)[5])); 280 281 int[2] sArr = [42, 97]; 282 static assert(!isDynamicArray!(typeof(sArr))); 283 284 // While a static array is not a dynamic array, 285 // a slice of a static array is a dynamic array. 286 static assert( isDynamicArray!(typeof(sArr[]))); 287 288 // Dynamic array of static arrays. 289 static assert( isDynamicArray!(long[3][])); 290 291 // Static array of dynamic arrays. 292 static assert(!isDynamicArray!(long[][3])); 293 294 // Associative array. 295 static assert(!isDynamicArray!(int[string])); 296 297 // While typeof(null) gets treated as void[] in some contexts, it is 298 // distinct from void[] and is not considered to be a dynamic array. 299 static assert(!isDynamicArray!(typeof(null))); 300 301 // However, naturally, if null is cast to a dynamic array, it's a 302 // dynamic array, since the cast forces the type. 303 static assert( isDynamicArray!(typeof(cast(int[]) null))); 304 305 enum E : int[] 306 { 307 a = [1, 2, 3], 308 } 309 310 // Enums do not count. 311 static assert(!isDynamicArray!E); 312 313 static struct AliasThis 314 { 315 int[] arr; 316 alias this = arr; 317 } 318 319 // Other implicit conversions do not count. 320 static assert(!isDynamicArray!AliasThis); 321 } 322 323 @safe unittest 324 { 325 import phobos.sys.meta : Alias, AliasSeq; 326 327 static struct AliasThis(T) 328 { 329 T member; 330 alias this = member; 331 } 332 333 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 334 { 335 foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][])) 336 { 337 enum E : Q!T { a = Q!T.init } 338 339 static assert( isDynamicArray!(Q!T)); 340 static assert(!isDynamicArray!E); 341 static assert(!isDynamicArray!(AliasThis!(Q!T))); 342 } 343 344 foreach (T; AliasSeq!(int, int[51], int[][2], 345 char[][int][11], immutable char[13u], 346 const(real)[1], const(real)[1][1], void[0])) 347 { 348 enum E : Q!T { a = Q!T.init } 349 350 static assert(!isDynamicArray!(Q!T)); 351 static assert(!isDynamicArray!E); 352 static assert(!isDynamicArray!(AliasThis!(Q!T))); 353 } 354 } 355 } 356 357 /++ 358 Whether type $(D T) is a static array. 359 360 Note that this does not include implicit conversions or enum types. The 361 type itself must be a static array. This is in contrast to 362 $(D __traits(isStaticArray, T)) which is true for enums (but not for other 363 implict conversions to static arrays). 364 365 As explained in the module documentation, traits like this one are not true 366 for enums (unlike most of the $(D __traits) traits) in order to avoid 367 testing for implicit conversions by default with template constraints, 368 since that tends to lead to subtle bugs when the code isn't carefully 369 written to take implicit conversions into account. 370 371 See also: 372 $(DDSUBLINK spec/traits, isStaticArray, $(D __traits(isStaticArray, T))) 373 $(DDSUBLINK spec/arrays, , The language spec for arrays) 374 +/ 375 enum isStaticArray(T) = is(T == U[n], U, size_t n); 376 377 /// 378 @safe unittest 379 { 380 // Some types which are static arrays. 381 static assert( isStaticArray!(int[12])); 382 static assert( isStaticArray!(const int[42])); 383 static assert( isStaticArray!(inout int[0])); 384 static assert( isStaticArray!(shared(int)[907])); 385 static assert( isStaticArray!(immutable(char)[5])); 386 387 // D doesn't have static array literals, but you get the same effect 388 // by casting a dynamic array literal to a static array, and of course, 389 // the result is typed as a static array. 390 static assert( isStaticArray!(typeof(cast(int[3]) [1, 2, 3]))); 391 392 int[2] sArr = [1, 2]; 393 static assert( isStaticArray!(typeof(sArr))); 394 395 // Some types which are not static arrays. 396 static assert(!isStaticArray!int); 397 static assert(!isStaticArray!(int*)); 398 static assert(!isStaticArray!real); 399 400 static struct S 401 { 402 int[4] arr; 403 } 404 static assert(!isStaticArray!S); 405 406 // The struct itself isn't considered a static array, 407 // but its member variable is when checked directly. 408 static assert( isStaticArray!(typeof(S.arr))); 409 410 // Dynamic arrays. 411 static assert(!isStaticArray!(int[])); 412 static assert(!isStaticArray!(const(int)[])); 413 static assert(!isStaticArray!string); 414 415 int[] arr; 416 static assert(!isStaticArray!(typeof(arr))); 417 418 // A slice of a static array is of course not a static array, 419 // because it's a dynamic array. 420 static assert(!isStaticArray!(typeof(sArr[]))); 421 422 // Static array of dynamic arrays. 423 static assert( isStaticArray!(long[][3])); 424 425 // Dynamic array of static arrays. 426 static assert(!isStaticArray!(long[3][])); 427 428 // Associative array. 429 static assert(!isStaticArray!(int[string])); 430 431 // Of course, null is not considered to be a static array. 432 static assert(!isStaticArray!(typeof(null))); 433 434 enum E : int[3] 435 { 436 a = [1, 2, 3], 437 } 438 439 // Enums do not count. 440 static assert(!isStaticArray!E); 441 442 // This is where isStaticArray differs from __traits(isStaticArray, ...) 443 static assert( __traits(isStaticArray, E)); 444 445 static struct AliasThis 446 { 447 int[] arr; 448 alias this = arr; 449 } 450 451 // Other implicit conversions do not count. 452 static assert(!isStaticArray!AliasThis); 453 454 static assert(!__traits(isStaticArray, AliasThis)); 455 } 456 457 @safe unittest 458 { 459 import phobos.sys.meta : Alias, AliasSeq; 460 461 static struct AliasThis(T) 462 { 463 T member; 464 alias this = member; 465 } 466 467 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 468 { 469 foreach (T; AliasSeq!(int[51], int[][2], 470 char[][int][11], immutable char[13u], 471 const(real)[1], const(real)[1][1], void[0])) 472 { 473 enum E : Q!T { a = Q!T.init, } 474 475 static assert( isStaticArray!(Q!T)); 476 static assert(!isStaticArray!E); 477 static assert(!isStaticArray!(AliasThis!(Q!T))); 478 } 479 480 foreach (T; AliasSeq!(int, int[], char[], string, long[3][], double[string][])) 481 { 482 enum E : Q!T { a = Q!T.init, } 483 484 static assert(!isStaticArray!(Q!T)); 485 static assert(!isStaticArray!E); 486 static assert(!isStaticArray!(AliasThis!(Q!T))); 487 } 488 } 489 } 490 491 /++ 492 Whether the given type is one of the built-in integer types, ignoring all 493 qualifiers. 494 495 $(TABLE 496 $(TR $(TH Integer Types)) 497 $(TR $(TD byte)) 498 $(TR $(TD ubyte)) 499 $(TR $(TD short)) 500 $(TR $(TD ushort)) 501 $(TR $(TD int)) 502 $(TR $(TD uint)) 503 $(TR $(TD long)) 504 $(TR $(TD ulong)) 505 ) 506 507 Note that this does not include implicit conversions or enum types. The 508 type itself must be one of the built-in integer types. 509 510 This trait does have some similarities with $(D __traits(isIntegral, T)), 511 but $(D isIntegral) accepts a $(I lot) more types than isInteger does. 512 isInteger is specifically for testing for the built-in integer types, 513 whereas $(D isIntegral) tests for a whole set of types that are vaguely 514 integer-like (including $(D bool), the three built-in character types, and 515 some of the vector types from core.simd). So, for most code, isInteger is 516 going to be more appropriate, but obviously, it depends on what the code is 517 trying to do. 518 519 See also: 520 $(DDSUBLINK spec/traits, isIntegral, $(D __traits(isIntegral, T))) 521 $(LREF isFloatingPoint) 522 $(LREF isSignedInteger) 523 $(LREF isNumeric) 524 $(LREF isUnsignedInteger) 525 +/ 526 enum isInteger(T) = is(immutable T == immutable byte) || 527 is(immutable T == immutable ubyte) || 528 is(immutable T == immutable short) || 529 is(immutable T == immutable ushort) || 530 is(immutable T == immutable int) || 531 is(immutable T == immutable uint) || 532 is(immutable T == immutable long) || 533 is(immutable T == immutable ulong); 534 535 /// 536 @safe unittest 537 { 538 // Some types which are integer types. 539 static assert( isInteger!byte); 540 static assert( isInteger!ubyte); 541 static assert( isInteger!short); 542 static assert( isInteger!ushort); 543 static assert( isInteger!int); 544 static assert( isInteger!uint); 545 static assert( isInteger!long); 546 static assert( isInteger!ulong); 547 548 static assert( isInteger!(const ubyte)); 549 static assert( isInteger!(immutable short)); 550 static assert( isInteger!(inout int)); 551 static assert( isInteger!(shared uint)); 552 static assert( isInteger!(const shared ulong)); 553 554 static assert( isInteger!(typeof(42))); 555 static assert( isInteger!(typeof(1234567890L))); 556 557 int i; 558 static assert( isInteger!(typeof(i))); 559 560 // Some types which aren't integer types. 561 static assert(!isInteger!bool); 562 static assert(!isInteger!char); 563 static assert(!isInteger!wchar); 564 static assert(!isInteger!dchar); 565 static assert(!isInteger!(int[])); 566 static assert(!isInteger!(ubyte[4])); 567 static assert(!isInteger!(int*)); 568 static assert(!isInteger!double); 569 static assert(!isInteger!string); 570 571 static struct S 572 { 573 int i; 574 } 575 static assert(!isInteger!S); 576 577 // The struct itself isn't considered an integer, 578 // but its member variable is when checked directly. 579 static assert( isInteger!(typeof(S.i))); 580 581 enum E : int 582 { 583 a = 42 584 } 585 586 // Enums do not count. 587 static assert(!isInteger!E); 588 589 static struct AliasThis 590 { 591 int i; 592 alias this = i; 593 } 594 595 // Other implicit conversions do not count. 596 static assert(!isInteger!AliasThis); 597 } 598 599 @safe unittest 600 { 601 import phobos.sys.meta : Alias, AliasSeq; 602 603 static struct AliasThis(T) 604 { 605 T member; 606 alias this = member; 607 } 608 609 // The actual core.simd types available vary from system to system, so we 610 // have to be a bit creative here. The reason that we're testing these types 611 // is because __traits(isIntegral, T) accepts them, but isInteger is not 612 // supposed to. 613 template SIMDTypes() 614 { 615 import core.simd; 616 617 alias SIMDTypes = AliasSeq!(); 618 static if (is(ubyte16)) 619 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 620 static if (is(int4)) 621 SIMDTypes = AliasSeq!(SIMDTypes, int4); 622 static if (is(double2)) 623 SIMDTypes = AliasSeq!(SIMDTypes, double2); 624 static if (is(void16)) 625 SIMDTypes = AliasSeq!(SIMDTypes, void16); 626 } 627 628 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 629 { 630 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong)) 631 { 632 enum E : Q!T { a = Q!T.init } 633 634 static assert( isInteger!(Q!T)); 635 static assert(!isInteger!E); 636 static assert(!isInteger!(AliasThis!(Q!T))); 637 } 638 639 foreach (T; AliasSeq!(bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 640 int[], ubyte[8], dchar[], void[], long*)) 641 { 642 enum E : Q!T { a = Q!T.init } 643 644 static assert(!isInteger!(Q!T)); 645 static assert(!isInteger!E); 646 static assert(!isInteger!(AliasThis!(Q!T))); 647 } 648 } 649 } 650 651 /++ 652 Whether the given type is one of the built-in signed integer types, ignoring 653 all qualifiers. 654 655 $(TABLE 656 $(TR $(TH Signed Integer Types)) 657 $(TR $(TD byte)) 658 $(TR $(TD short)) 659 $(TR $(TD int)) 660 $(TR $(TD long)) 661 ) 662 663 Note that this does not include implicit conversions or enum types. The 664 type itself must be one of the built-in signed integer types. 665 666 See also: 667 $(LREF isFloatingPoint) 668 $(LREF isInteger) 669 $(LREF isNumeric) 670 $(LREF isUnsignedInteger) 671 +/ 672 enum isSignedInteger(T) = is(immutable T == immutable byte) || 673 is(immutable T == immutable short) || 674 is(immutable T == immutable int) || 675 is(immutable T == immutable long); 676 677 /// 678 @safe unittest 679 { 680 // Some types which are signed integer types. 681 static assert( isSignedInteger!byte); 682 static assert( isSignedInteger!short); 683 static assert( isSignedInteger!int); 684 static assert( isSignedInteger!long); 685 686 static assert( isSignedInteger!(const byte)); 687 static assert( isSignedInteger!(immutable short)); 688 static assert( isSignedInteger!(inout int)); 689 static assert( isSignedInteger!(shared int)); 690 static assert( isSignedInteger!(const shared long)); 691 692 static assert( isSignedInteger!(typeof(42))); 693 static assert( isSignedInteger!(typeof(1234567890L))); 694 695 int i; 696 static assert( isSignedInteger!(typeof(i))); 697 698 // Some types which aren't signed integer types. 699 static assert(!isSignedInteger!ubyte); 700 static assert(!isSignedInteger!ushort); 701 static assert(!isSignedInteger!uint); 702 static assert(!isSignedInteger!ulong); 703 704 static assert(!isSignedInteger!bool); 705 static assert(!isSignedInteger!char); 706 static assert(!isSignedInteger!wchar); 707 static assert(!isSignedInteger!dchar); 708 static assert(!isSignedInteger!(int[])); 709 static assert(!isSignedInteger!(ubyte[4])); 710 static assert(!isSignedInteger!(int*)); 711 static assert(!isSignedInteger!double); 712 static assert(!isSignedInteger!string); 713 714 static struct S 715 { 716 int i; 717 } 718 static assert(!isSignedInteger!S); 719 720 // The struct itself isn't considered a signed integer, 721 // but its member variable is when checked directly. 722 static assert( isSignedInteger!(typeof(S.i))); 723 724 enum E : int 725 { 726 a = 42 727 } 728 729 // Enums do not count. 730 static assert(!isSignedInteger!E); 731 732 static struct AliasThis 733 { 734 int i; 735 alias this = i; 736 } 737 738 // Other implicit conversions do not count. 739 static assert(!isSignedInteger!AliasThis); 740 } 741 742 @safe unittest 743 { 744 import phobos.sys.meta : Alias, AliasSeq; 745 746 static struct AliasThis(T) 747 { 748 T member; 749 alias this = member; 750 } 751 752 // The actual core.simd types available vary from system to system, so we 753 // have to be a bit creative here. The reason that we're testing these types 754 // is because __traits(isIntegral, T) accepts them, but isSignedInteger is 755 // not supposed to. 756 template SIMDTypes() 757 { 758 import core.simd; 759 760 alias SIMDTypes = AliasSeq!(); 761 static if (is(ubyte16)) 762 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 763 static if (is(int4)) 764 SIMDTypes = AliasSeq!(SIMDTypes, int4); 765 static if (is(double2)) 766 SIMDTypes = AliasSeq!(SIMDTypes, double2); 767 static if (is(void16)) 768 SIMDTypes = AliasSeq!(SIMDTypes, void16); 769 } 770 771 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 772 { 773 foreach (T; AliasSeq!(byte, short, int, long)) 774 { 775 enum E : Q!T { a = Q!T.init } 776 777 static assert( isSignedInteger!(Q!T)); 778 static assert(!isSignedInteger!E); 779 static assert(!isSignedInteger!(AliasThis!(Q!T))); 780 } 781 782 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, 783 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 784 int[], ubyte[8], dchar[], void[], long*)) 785 { 786 enum E : Q!T { a = Q!T.init } 787 788 static assert(!isSignedInteger!(Q!T)); 789 static assert(!isSignedInteger!E); 790 static assert(!isSignedInteger!(AliasThis!(Q!T))); 791 } 792 } 793 } 794 795 /++ 796 Whether the given type is one of the built-in unsigned integer types, 797 ignoring all qualifiers. 798 799 $(TABLE 800 $(TR $(TH Integer Types)) 801 $(TR $(TD ubyte)) 802 $(TR $(TD ushort)) 803 $(TR $(TD uint)) 804 $(TR $(TD ulong)) 805 ) 806 807 Note that this does not include implicit conversions or enum types. The 808 type itself must be one of the built-in unsigned integer types. 809 810 This trait does have some similarities with $(D __traits(isUnsigned, T)), 811 but $(D isUnsigned) accepts a $(I lot) more types than isUnsignedInteger 812 does. isUnsignedInteger is specifically for testing for the built-in 813 unsigned integer types, whereas $(D isUnsigned) tests for a whole set of 814 types that are unsigned and vaguely integer-like (including $(D bool), the 815 three built-in character types, and some of the vector types from 816 core.simd). So, for most code, isUnsignedInteger is going to be more 817 appropriate, but obviously, it depends on what the code is trying to do. 818 819 See also: 820 $(DDSUBLINK spec/traits, isUnsigned, $(D __traits(isUnsigned, T))) 821 $(LREF isFloatingPoint) 822 $(LREF isInteger) 823 $(LREF isSignedInteger) 824 $(LREF isNumeric) 825 +/ 826 enum isUnsignedInteger(T) = is(immutable T == immutable ubyte) || 827 is(immutable T == immutable ushort) || 828 is(immutable T == immutable uint) || 829 is(immutable T == immutable ulong); 830 831 /// 832 @safe unittest 833 { 834 // Some types which are unsigned integer types. 835 static assert( isUnsignedInteger!ubyte); 836 static assert( isUnsignedInteger!ushort); 837 static assert( isUnsignedInteger!uint); 838 static assert( isUnsignedInteger!ulong); 839 840 static assert( isUnsignedInteger!(const ubyte)); 841 static assert( isUnsignedInteger!(immutable ushort)); 842 static assert( isUnsignedInteger!(inout uint)); 843 static assert( isUnsignedInteger!(shared uint)); 844 static assert( isUnsignedInteger!(const shared ulong)); 845 846 static assert( isUnsignedInteger!(typeof(42u))); 847 static assert( isUnsignedInteger!(typeof(1234567890UL))); 848 849 uint u; 850 static assert( isUnsignedInteger!(typeof(u))); 851 852 // Some types which aren't unsigned integer types. 853 static assert(!isUnsignedInteger!byte); 854 static assert(!isUnsignedInteger!short); 855 static assert(!isUnsignedInteger!int); 856 static assert(!isUnsignedInteger!long); 857 858 static assert(!isUnsignedInteger!bool); 859 static assert(!isUnsignedInteger!char); 860 static assert(!isUnsignedInteger!wchar); 861 static assert(!isUnsignedInteger!dchar); 862 static assert(!isUnsignedInteger!(int[])); 863 static assert(!isUnsignedInteger!(ubyte[4])); 864 static assert(!isUnsignedInteger!(int*)); 865 static assert(!isUnsignedInteger!double); 866 static assert(!isUnsignedInteger!string); 867 868 static struct S 869 { 870 uint u; 871 } 872 static assert(!isUnsignedInteger!S); 873 874 // The struct itself isn't considered an unsigned integer, 875 // but its member variable is when checked directly. 876 static assert( isUnsignedInteger!(typeof(S.u))); 877 878 enum E : uint 879 { 880 a = 42 881 } 882 883 // Enums do not count. 884 static assert(!isUnsignedInteger!E); 885 886 static struct AliasThis 887 { 888 uint u; 889 alias this = u; 890 } 891 892 // Other implicit conversions do not count. 893 static assert(!isUnsignedInteger!AliasThis); 894 } 895 896 @safe unittest 897 { 898 import phobos.sys.meta : Alias, AliasSeq; 899 900 static struct AliasThis(T) 901 { 902 T member; 903 alias this = member; 904 } 905 906 // The actual core.simd types available vary from system to system, so we 907 // have to be a bit creative here. The reason that we're testing these types 908 // is because __traits(isIntegral, T) and __traits(isUnsigned, T) accept 909 // them, but isUnsignedInteger is not supposed to. 910 template SIMDTypes() 911 { 912 import core.simd; 913 914 alias SIMDTypes = AliasSeq!(); 915 static if (is(ubyte16)) 916 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 917 static if (is(int4)) 918 SIMDTypes = AliasSeq!(SIMDTypes, int4); 919 static if (is(double2)) 920 SIMDTypes = AliasSeq!(SIMDTypes, double2); 921 static if (is(void16)) 922 SIMDTypes = AliasSeq!(SIMDTypes, void16); 923 } 924 925 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 926 { 927 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong)) 928 { 929 enum E : Q!T { a = Q!T.init } 930 931 static assert( isUnsignedInteger!(Q!T)); 932 static assert(!isUnsignedInteger!E); 933 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 934 } 935 936 foreach (T; AliasSeq!(byte, short, int, long, 937 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 938 int[], ubyte[8], dchar[], void[], long*)) 939 { 940 enum E : Q!T { a = Q!T.init } 941 942 static assert(!isUnsignedInteger!(Q!T)); 943 static assert(!isUnsignedInteger!E); 944 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 945 } 946 } 947 } 948 949 /++ 950 Whether the given type is one of the built-in floating-point types, ignoring 951 all qualifiers. 952 953 $(TABLE 954 $(TR $(TH Floating-Point Types)) 955 $(TR $(TD float)) 956 $(TR $(TD double)) 957 $(TR $(TD real)) 958 ) 959 960 Note that this does not include implicit conversions or enum types. The 961 type itself must be one of the built-in floating-point types. 962 963 This trait does have some similarities with $(D __traits(isFloating, T)), 964 but $(D isFloating) accepts more types than isFloatingPoint does. 965 isFloatingPoint is specifically for testing for the built-in floating-point 966 types, whereas $(D isFloating) tests for a whole set of types that are 967 vaguely float-like (including enums with a base type which is a 968 floating-point type and some of the vector types from core.simd). So, for 969 most code, isFloatingPoint is going to be more appropriate, but obviously, 970 it depends on what the code is trying to do. 971 972 See also: 973 $(DDSUBLINK spec/traits, isFloating, $(D __traits(isFloating, T))) 974 $(LREF isInteger) 975 $(LREF isSignedInteger) 976 $(LREF isNumeric) 977 $(LREF isUnsignedInteger) 978 +/ 979 enum isFloatingPoint(T) = is(immutable T == immutable float) || 980 is(immutable T == immutable double) || 981 is(immutable T == immutable real); 982 983 /// 984 @safe unittest 985 { 986 // Some types which are floating-point types. 987 static assert( isFloatingPoint!float); 988 static assert( isFloatingPoint!double); 989 static assert( isFloatingPoint!real); 990 991 static assert( isFloatingPoint!(const float)); 992 static assert( isFloatingPoint!(immutable float)); 993 static assert( isFloatingPoint!(inout double)); 994 static assert( isFloatingPoint!(shared double)); 995 static assert( isFloatingPoint!(const shared real)); 996 997 static assert( isFloatingPoint!(typeof(42.0))); 998 static assert( isFloatingPoint!(typeof(42f))); 999 static assert( isFloatingPoint!(typeof(1e5))); 1000 static assert( isFloatingPoint!(typeof(97.4L))); 1001 1002 double d; 1003 static assert( isFloatingPoint!(typeof(d))); 1004 1005 // Some types which aren't floating-point types. 1006 static assert(!isFloatingPoint!bool); 1007 static assert(!isFloatingPoint!char); 1008 static assert(!isFloatingPoint!dchar); 1009 static assert(!isFloatingPoint!int); 1010 static assert(!isFloatingPoint!long); 1011 static assert(!isFloatingPoint!(float[])); 1012 static assert(!isFloatingPoint!(double[4])); 1013 static assert(!isFloatingPoint!(real*)); 1014 static assert(!isFloatingPoint!string); 1015 1016 static struct S 1017 { 1018 double d; 1019 } 1020 static assert(!isFloatingPoint!S); 1021 1022 // The struct itself isn't considered a floating-point type, 1023 // but its member variable is when checked directly. 1024 static assert( isFloatingPoint!(typeof(S.d))); 1025 1026 enum E : double 1027 { 1028 a = 12.34 1029 } 1030 1031 // Enums do not count. 1032 static assert(!isFloatingPoint!E); 1033 1034 static struct AliasThis 1035 { 1036 double d; 1037 alias this = d; 1038 } 1039 1040 // Other implicit conversions do not count. 1041 static assert(!isFloatingPoint!AliasThis); 1042 } 1043 1044 @safe unittest 1045 { 1046 import phobos.sys.meta : Alias, AliasSeq; 1047 1048 static struct AliasThis(T) 1049 { 1050 T member; 1051 alias this = member; 1052 } 1053 1054 // The actual core.simd types available vary from system to system, so we 1055 // have to be a bit creative here. The reason that we're testing these types 1056 // is because __traits(isFloating, T) accepts them, but isFloatingPoint is 1057 // not supposed to. 1058 template SIMDTypes() 1059 { 1060 import core.simd; 1061 1062 alias SIMDTypes = AliasSeq!(); 1063 static if (is(int4)) 1064 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1065 static if (is(double2)) 1066 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1067 static if (is(void16)) 1068 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1069 } 1070 1071 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1072 { 1073 foreach (T; AliasSeq!(float, double, real)) 1074 { 1075 enum E : Q!T { a = Q!T.init } 1076 1077 static assert( isFloatingPoint!(Q!T)); 1078 static assert(!isFloatingPoint!E); 1079 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1080 } 1081 1082 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, ubyte, short, ushort, 1083 int, uint, long, ulong, SIMDTypes!(), 1084 int[], float[8], real[], void[], double*)) 1085 { 1086 enum E : Q!T { a = Q!T.init } 1087 1088 static assert(!isFloatingPoint!(Q!T)); 1089 static assert(!isFloatingPoint!E); 1090 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1091 } 1092 } 1093 } 1094 1095 /++ 1096 Whether the given type is one of the built-in numeric types, ignoring all 1097 qualifiers. It's equivalent to $(D isInteger!T || isFloatingPoint!T), but 1098 it only involves a single template instantation instead of two. 1099 1100 $(TABLE 1101 $(TR $(TH Numeric Types)) 1102 $(TR $(TD byte)) 1103 $(TR $(TD ubyte)) 1104 $(TR $(TD short)) 1105 $(TR $(TD ushort)) 1106 $(TR $(TD int)) 1107 $(TR $(TD uint)) 1108 $(TR $(TD long)) 1109 $(TR $(TD ulong)) 1110 $(TR $(TD float)) 1111 $(TR $(TD double)) 1112 $(TR $(TD real)) 1113 ) 1114 1115 Note that this does not include implicit conversions or enum types. The 1116 type itself must be one of the built-in numeric types. 1117 1118 See_Also: 1119 $(LREF isFloatingPoint) 1120 $(LREF isInteger) 1121 $(LREF isSignedInteger) 1122 $(LREF isUnsignedInteger) 1123 +/ 1124 enum isNumeric(T) = is(immutable T == immutable byte) || 1125 is(immutable T == immutable ubyte) || 1126 is(immutable T == immutable short) || 1127 is(immutable T == immutable ushort) || 1128 is(immutable T == immutable int) || 1129 is(immutable T == immutable uint) || 1130 is(immutable T == immutable long) || 1131 is(immutable T == immutable ulong) || 1132 is(immutable T == immutable float) || 1133 is(immutable T == immutable double) || 1134 is(immutable T == immutable real); 1135 1136 /// 1137 @safe unittest 1138 { 1139 // Some types which are numeric types. 1140 static assert( isNumeric!byte); 1141 static assert( isNumeric!ubyte); 1142 static assert( isNumeric!short); 1143 static assert( isNumeric!ushort); 1144 static assert( isNumeric!int); 1145 static assert( isNumeric!uint); 1146 static assert( isNumeric!long); 1147 static assert( isNumeric!ulong); 1148 static assert( isNumeric!float); 1149 static assert( isNumeric!double); 1150 static assert( isNumeric!real); 1151 1152 static assert( isNumeric!(const short)); 1153 static assert( isNumeric!(immutable int)); 1154 static assert( isNumeric!(inout uint)); 1155 static assert( isNumeric!(shared long)); 1156 static assert( isNumeric!(const shared real)); 1157 1158 static assert( isNumeric!(typeof(42))); 1159 static assert( isNumeric!(typeof(1234657890L))); 1160 static assert( isNumeric!(typeof(42.0))); 1161 static assert( isNumeric!(typeof(42f))); 1162 static assert( isNumeric!(typeof(1e5))); 1163 static assert( isNumeric!(typeof(97.4L))); 1164 1165 int i; 1166 static assert( isNumeric!(typeof(i))); 1167 1168 // Some types which aren't numeric types. 1169 static assert(!isNumeric!bool); 1170 static assert(!isNumeric!char); 1171 static assert(!isNumeric!dchar); 1172 static assert(!isNumeric!(int[])); 1173 static assert(!isNumeric!(double[4])); 1174 static assert(!isNumeric!(real*)); 1175 static assert(!isNumeric!string); 1176 1177 static struct S 1178 { 1179 int i; 1180 } 1181 static assert(!isNumeric!S); 1182 1183 // The struct itself isn't considered a numeric type, 1184 // but its member variable is when checked directly. 1185 static assert( isNumeric!(typeof(S.i))); 1186 1187 enum E : int 1188 { 1189 a = 42 1190 } 1191 1192 // Enums do not count. 1193 static assert(!isNumeric!E); 1194 1195 static struct AliasThis 1196 { 1197 int i; 1198 alias this = i; 1199 } 1200 1201 // Other implicit conversions do not count. 1202 static assert(!isNumeric!AliasThis); 1203 } 1204 1205 @safe unittest 1206 { 1207 import phobos.sys.meta : Alias, AliasSeq; 1208 1209 static struct AliasThis(T) 1210 { 1211 T member; 1212 alias this = member; 1213 } 1214 1215 // The actual core.simd types available vary from system to system, so we 1216 // have to be a bit creative here. The reason that we're testing these types 1217 // is because __traits(isInteger, T) and __traits(isFloating, T) accept 1218 // them, but isNumeric is not supposed to. 1219 template SIMDTypes() 1220 { 1221 import core.simd; 1222 1223 alias SIMDTypes = AliasSeq!(); 1224 static if (is(int4)) 1225 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1226 static if (is(double2)) 1227 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1228 static if (is(void16)) 1229 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1230 } 1231 1232 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1233 { 1234 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real)) 1235 { 1236 enum E : Q!T { a = Q!T.init } 1237 1238 static assert( isNumeric!(Q!T)); 1239 static assert(!isNumeric!E); 1240 static assert(!isNumeric!(AliasThis!(Q!T))); 1241 } 1242 1243 foreach (T; AliasSeq!(bool, char, wchar, dchar, SIMDTypes!(), 1244 int[], float[8], real[], void[], double*)) 1245 { 1246 enum E : Q!T { a = Q!T.init } 1247 1248 static assert(!isNumeric!(Q!T)); 1249 static assert(!isNumeric!E); 1250 static assert(!isNumeric!(AliasThis!(Q!T))); 1251 } 1252 } 1253 } 1254 1255 /++ 1256 Whether the given type is a pointer. 1257 1258 Note that this does not include implicit conversions or enum types. The 1259 type itself must be a pointer. 1260 1261 Also, remember that unlike C/C++, D's arrays are not pointers. Rather, a 1262 dynamic array in D is a slice of memory which has a member which is a 1263 pointer to its first element and another member which is the length of the 1264 array as $(D size_t). So, a dynamic array / slice has a $(D ptr) member 1265 which is a pointer, but the dynamic array itself is not a pointer. 1266 1267 See_Also: 1268 $(LREF isDynamicArray) 1269 +/ 1270 enum isPointer(T) = is(T == U*, U); 1271 1272 /// 1273 @system unittest 1274 { 1275 // Some types which are pointers. 1276 static assert( isPointer!(bool*)); 1277 static assert( isPointer!(int*)); 1278 static assert( isPointer!(int**)); 1279 static assert( isPointer!(real*)); 1280 static assert( isPointer!(string*)); 1281 1282 static assert( isPointer!(const int*)); 1283 static assert( isPointer!(immutable int*)); 1284 static assert( isPointer!(inout int*)); 1285 static assert( isPointer!(shared int*)); 1286 static assert( isPointer!(const shared int*)); 1287 1288 static assert( isPointer!(typeof("foobar".ptr))); 1289 1290 int* ptr; 1291 static assert( isPointer!(typeof(ptr))); 1292 1293 int i; 1294 static assert( isPointer!(typeof(&i))); 1295 1296 // Some types which aren't pointers. 1297 static assert(!isPointer!bool); 1298 static assert(!isPointer!int); 1299 static assert(!isPointer!dchar); 1300 static assert(!isPointer!(int[])); 1301 static assert(!isPointer!(double[4])); 1302 static assert(!isPointer!string); 1303 1304 static struct S 1305 { 1306 int* ptr; 1307 } 1308 static assert(!isPointer!S); 1309 1310 // The struct itself isn't considered a numeric type, 1311 // but its member variable is when checked directly. 1312 static assert( isPointer!(typeof(S.ptr))); 1313 1314 enum E : immutable(char*) 1315 { 1316 a = "foobar".ptr 1317 } 1318 1319 // Enums do not count. 1320 static assert(!isPointer!E); 1321 1322 static struct AliasThis 1323 { 1324 int* ptr; 1325 alias this = ptr; 1326 } 1327 1328 // Other implicit conversions do not count. 1329 static assert(!isPointer!AliasThis); 1330 } 1331 1332 @safe unittest 1333 { 1334 import phobos.sys.meta : Alias, AliasSeq; 1335 1336 static struct AliasThis(T) 1337 { 1338 T member; 1339 alias this = member; 1340 } 1341 1342 static struct S 1343 { 1344 int i; 1345 } 1346 1347 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1348 { 1349 foreach (T; AliasSeq!(long*, S*, S**, S***, double[]*)) 1350 { 1351 enum E : Q!T { a = Q!T.init } 1352 1353 static assert( isPointer!(Q!T)); 1354 static assert(!isPointer!E); 1355 static assert(!isPointer!(AliasThis!(Q!T))); 1356 } 1357 1358 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, int, uint, long, 1359 int[], float[8], real[], void[])) 1360 { 1361 enum E : Q!T { a = Q!T.init } 1362 1363 static assert(!isPointer!(Q!T)); 1364 static assert(!isPointer!E); 1365 static assert(!isPointer!(AliasThis!(Q!T))); 1366 } 1367 } 1368 } 1369 1370 /++ 1371 Evaluates to $(D true) if the given type or symbol is an instantiation of 1372 the given template. 1373 1374 The overload which takes $(D T) operates on types and indicates whether an 1375 aggregate type (i.e. struct, class, interface, or union) is an 1376 instantiation of the given template. 1377 1378 The overload which takes $(D Symbol) operates on function templates, 1379 because unlike with aggregate types, the type of a function does not retain 1380 the fact that it was instantiated from a template. So, for functions, it's 1381 necessary to pass the function itself as a symbol rather than pass the type 1382 of the function. 1383 1384 The overload which takes $(D Symbol) also works with templates which are 1385 not types or functions. 1386 1387 The single-argument overload makes it so that it can be partially 1388 instantiated with the first argument, which will often be necessary with 1389 template predicates. 1390 +/ 1391 template isInstantiationOf(alias Template, T) 1392 if (__traits(isTemplate, Template)) 1393 { 1394 enum isInstantiationOf = is(T == Template!Args, Args...); 1395 } 1396 1397 /++ Ditto +/ 1398 template isInstantiationOf(alias Template, alias Symbol) 1399 if (__traits(isTemplate, Template)) 1400 { 1401 enum impl(alias T : Template!Args, Args...) = true; 1402 enum impl(alias T) = false; 1403 enum isInstantiationOf = impl!Symbol; 1404 } 1405 1406 /++ Ditto +/ 1407 template isInstantiationOf(alias Template) 1408 if (__traits(isTemplate, Template)) 1409 { 1410 enum isInstantiationOf(T) = is(T == Template!Args, Args...); 1411 1412 template isInstantiationOf(alias Symbol) 1413 { 1414 enum impl(alias T : Template!Args, Args...) = true; 1415 enum impl(alias T) = false; 1416 enum isInstantiationOf = impl!Symbol; 1417 } 1418 } 1419 1420 /// Examples of templated types. 1421 @safe unittest 1422 { 1423 static struct S(T) {} 1424 static class C(T) {} 1425 1426 static assert( isInstantiationOf!(S, S!int)); 1427 static assert( isInstantiationOf!(S, S!int)); 1428 static assert( isInstantiationOf!(S, S!string)); 1429 static assert( isInstantiationOf!(S, const S!string)); 1430 static assert( isInstantiationOf!(S, shared S!string)); 1431 static assert(!isInstantiationOf!(S, int)); 1432 static assert(!isInstantiationOf!(S, C!int)); 1433 static assert(!isInstantiationOf!(S, C!string)); 1434 static assert(!isInstantiationOf!(S, C!(S!int))); 1435 1436 static assert( isInstantiationOf!(C, C!int)); 1437 static assert( isInstantiationOf!(C, C!string)); 1438 static assert( isInstantiationOf!(C, const C!string)); 1439 static assert( isInstantiationOf!(C, shared C!string)); 1440 static assert(!isInstantiationOf!(C, int)); 1441 static assert(!isInstantiationOf!(C, S!int)); 1442 static assert(!isInstantiationOf!(C, S!string)); 1443 static assert(!isInstantiationOf!(C, S!(C!int))); 1444 1445 static struct Variadic(T...) {} 1446 1447 static assert( isInstantiationOf!(Variadic, Variadic!())); 1448 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1449 static assert( isInstantiationOf!(Variadic, Variadic!(int, string))); 1450 static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int))); 1451 static assert( isInstantiationOf!(Variadic, const Variadic!(int, short))); 1452 static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short))); 1453 static assert(!isInstantiationOf!(Variadic, int)); 1454 static assert(!isInstantiationOf!(Variadic, S!int)); 1455 static assert(!isInstantiationOf!(Variadic, C!int)); 1456 1457 static struct ValueArg(int i) {} 1458 static assert( isInstantiationOf!(ValueArg, ValueArg!42)); 1459 static assert( isInstantiationOf!(ValueArg, ValueArg!256)); 1460 static assert( isInstantiationOf!(ValueArg, const ValueArg!1024)); 1461 static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024)); 1462 static assert(!isInstantiationOf!(ValueArg, int)); 1463 static assert(!isInstantiationOf!(ValueArg, S!int)); 1464 1465 int i; 1466 1467 static struct AliasArg(alias Symbol) {} 1468 static assert( isInstantiationOf!(AliasArg, AliasArg!42)); 1469 static assert( isInstantiationOf!(AliasArg, AliasArg!int)); 1470 static assert( isInstantiationOf!(AliasArg, AliasArg!i)); 1471 static assert( isInstantiationOf!(AliasArg, const AliasArg!i)); 1472 static assert( isInstantiationOf!(AliasArg, shared AliasArg!i)); 1473 static assert(!isInstantiationOf!(AliasArg, int)); 1474 static assert(!isInstantiationOf!(AliasArg, S!int)); 1475 1476 // An uninstantiated template is not an instance of any template, 1477 // not even itself. 1478 static assert(!isInstantiationOf!(S, S)); 1479 static assert(!isInstantiationOf!(S, C)); 1480 static assert(!isInstantiationOf!(C, C)); 1481 static assert(!isInstantiationOf!(C, S)); 1482 1483 // Variables of a templated type are not considered instantiations of that 1484 // type. For templated types, the overload which takes a type must be used. 1485 S!int s; 1486 C!string c; 1487 static assert(!isInstantiationOf!(S, s)); 1488 static assert(!isInstantiationOf!(C, c)); 1489 } 1490 1491 // Examples of templated functions. 1492 @safe unittest 1493 { 1494 static int foo(T...)() { return 42; } 1495 static void bar(T...)(T var) {} 1496 static void baz(T)(T var) {} 1497 static bool frobozz(alias pred)(int) { return true; } 1498 1499 static assert( isInstantiationOf!(foo, foo!int)); 1500 static assert( isInstantiationOf!(foo, foo!string)); 1501 static assert( isInstantiationOf!(foo, foo!(int, string))); 1502 static assert(!isInstantiationOf!(foo, bar!int)); 1503 static assert(!isInstantiationOf!(foo, bar!string)); 1504 static assert(!isInstantiationOf!(foo, bar!(int, string))); 1505 1506 static assert( isInstantiationOf!(bar, bar!int)); 1507 static assert( isInstantiationOf!(bar, bar!string)); 1508 static assert( isInstantiationOf!(bar, bar!(int, string))); 1509 static assert(!isInstantiationOf!(bar, foo!int)); 1510 static assert(!isInstantiationOf!(bar, foo!string)); 1511 static assert(!isInstantiationOf!(bar, foo!(int, string))); 1512 1513 static assert( isInstantiationOf!(baz, baz!int)); 1514 static assert( isInstantiationOf!(baz, baz!string)); 1515 static assert(!isInstantiationOf!(baz, foo!(int, string))); 1516 1517 static assert( isInstantiationOf!(frobozz, frobozz!(a => a))); 1518 static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2))); 1519 static assert(!isInstantiationOf!(frobozz, baz!int)); 1520 1521 // Unfortunately, the function type is not considered an instantiation of 1522 // the template, because that information is not part of the type, unlike 1523 // with templated structs or classes. 1524 static assert(!isInstantiationOf!(foo, typeof(foo!int))); 1525 static assert(!isInstantiationOf!(bar, typeof(bar!int))); 1526 } 1527 1528 // Examples of templates which aren't types or functions. 1529 @safe unittest 1530 { 1531 template SingleArg(T) {} 1532 template Variadic(T...) {} 1533 template ValueArg(string s) {} 1534 template Alias(alias symbol) {} 1535 1536 static assert( isInstantiationOf!(SingleArg, SingleArg!int)); 1537 static assert( isInstantiationOf!(SingleArg, SingleArg!string)); 1538 static assert(!isInstantiationOf!(SingleArg, int)); 1539 static assert(!isInstantiationOf!(SingleArg, Variadic!int)); 1540 1541 static assert( isInstantiationOf!(Variadic, Variadic!())); 1542 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1543 static assert( isInstantiationOf!(Variadic, Variadic!string)); 1544 static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long))); 1545 static assert(!isInstantiationOf!(Variadic, int)); 1546 static assert(!isInstantiationOf!(Variadic, SingleArg!int)); 1547 1548 static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang")); 1549 static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar")); 1550 static assert(!isInstantiationOf!(ValueArg, string)); 1551 static assert(!isInstantiationOf!(ValueArg, Variadic!string)); 1552 1553 int i; 1554 1555 static assert( isInstantiationOf!(Alias, Alias!int)); 1556 static assert( isInstantiationOf!(Alias, Alias!42)); 1557 static assert( isInstantiationOf!(Alias, Alias!i)); 1558 static assert(!isInstantiationOf!(Alias, int)); 1559 static assert(!isInstantiationOf!(Alias, SingleArg!int)); 1560 } 1561 1562 /// Examples of partial instantation. 1563 @safe unittest 1564 { 1565 static struct SingleArg(T) {} 1566 static struct Variadic(T...) {} 1567 1568 alias isSingleArg = isInstantiationOf!SingleArg; 1569 alias isVariadic = isInstantiationOf!Variadic; 1570 1571 static assert( isSingleArg!(SingleArg!int)); 1572 static assert( isSingleArg!(const SingleArg!int)); 1573 static assert(!isSingleArg!int); 1574 static assert(!isSingleArg!(Variadic!int)); 1575 1576 static assert( isVariadic!(Variadic!())); 1577 static assert( isVariadic!(Variadic!int)); 1578 static assert( isVariadic!(shared Variadic!int)); 1579 static assert( isVariadic!(Variadic!(int, string))); 1580 static assert(!isVariadic!int); 1581 static assert(!isVariadic!(SingleArg!int)); 1582 1583 T foo(T)(T t) { return t; } 1584 T likeFoo(T)(T t) { return t; } 1585 bool bar(alias pred)(int i) { return pred(i); } 1586 1587 alias isFoo = isInstantiationOf!foo; 1588 alias isBar = isInstantiationOf!bar; 1589 1590 static assert( isFoo!(foo!int)); 1591 static assert( isFoo!(foo!string)); 1592 static assert(!isFoo!int); 1593 static assert(!isFoo!(likeFoo!int)); 1594 static assert(!isFoo!(bar!(a => true))); 1595 1596 static assert( isBar!(bar!(a => true))); 1597 static assert( isBar!(bar!(a => a > 2))); 1598 static assert(!isBar!int); 1599 static assert(!isBar!(foo!int)); 1600 static assert(!isBar!(likeFoo!int)); 1601 } 1602 1603 /++ 1604 Evaluates to an $(D AliasSeq) containing the members of an enum type. 1605 1606 The elements of the $(D AliasSeq) are in the same order as they are in the 1607 enum declaration. 1608 1609 An enum can have multiple members with the same value, so if code needs the 1610 enum values to be unique (e.g. if it's generating a switch statement from 1611 them), then $(REF Unique, phobos, sys, meta) can be used to filter out the 1612 duplicate values - e.g. $(D Unique!(isEqual, EnumMembers!E)). 1613 +/ 1614 template EnumMembers(E) 1615 if (is(E == enum)) 1616 { 1617 import phobos.sys.meta : AliasSeq; 1618 1619 alias EnumMembers = AliasSeq!(); 1620 static foreach (member; __traits(allMembers, E)) 1621 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, member)); 1622 } 1623 1624 /// Create an array of enum values. 1625 @safe unittest 1626 { 1627 enum Sqrts : real 1628 { 1629 one = 1, 1630 two = 1.41421, 1631 three = 1.73205 1632 } 1633 auto sqrts = [EnumMembers!Sqrts]; 1634 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]); 1635 } 1636 1637 /++ 1638 A generic function $(D rank(v)) in the following example uses this template 1639 for finding a member $(D e) in an enum type $(D E). 1640 +/ 1641 @safe unittest 1642 { 1643 // Returns i if e is the i-th member of E. 1644 static size_t rank(E)(E e) 1645 if (is(E == enum)) 1646 { 1647 static foreach (i, member; EnumMembers!E) 1648 { 1649 if (e == member) 1650 return i; 1651 } 1652 assert(0, "Not an enum member"); 1653 } 1654 1655 enum Mode 1656 { 1657 read = 1, 1658 write = 2, 1659 map = 4 1660 } 1661 assert(rank(Mode.read) == 0); 1662 assert(rank(Mode.write) == 1); 1663 assert(rank(Mode.map) == 2); 1664 } 1665 1666 /// Use EnumMembers to generate a switch statement using static foreach. 1667 @safe unittest 1668 { 1669 static class Foo 1670 { 1671 string calledMethod; 1672 void foo() @safe { calledMethod = "foo"; } 1673 void bar() @safe { calledMethod = "bar"; } 1674 void baz() @safe { calledMethod = "baz"; } 1675 } 1676 1677 enum FuncName : string { foo = "foo", bar = "bar", baz = "baz" } 1678 1679 auto foo = new Foo; 1680 1681 s: final switch (FuncName.bar) 1682 { 1683 static foreach (member; EnumMembers!FuncName) 1684 { 1685 // Generate a case for each enum value. 1686 case member: 1687 { 1688 // Call foo.{enum value}(). 1689 __traits(getMember, foo, member)(); 1690 break s; 1691 } 1692 } 1693 } 1694 1695 // Since we passed FuncName.bar to the switch statement, the bar member 1696 // function was called. 1697 assert(foo.calledMethod == "bar"); 1698 } 1699 1700 @safe unittest 1701 { 1702 { 1703 enum A { a } 1704 static assert([EnumMembers!A] == [A.a]); 1705 enum B { a, b, c, d, e } 1706 static assert([EnumMembers!B] == [B.a, B.b, B.c, B.d, B.e]); 1707 } 1708 { 1709 enum A : string { a = "alpha", b = "beta" } 1710 static assert([EnumMembers!A] == [A.a, A.b]); 1711 1712 static struct S 1713 { 1714 int value; 1715 int opCmp(S rhs) const nothrow { return value - rhs.value; } 1716 } 1717 enum B : S { a = S(1), b = S(2), c = S(3) } 1718 static assert([EnumMembers!B] == [B.a, B.b, B.c]); 1719 } 1720 { 1721 enum A { a = 0, b = 0, c = 1, d = 1, e } 1722 static assert([EnumMembers!A] == [A.a, A.b, A.c, A.d, A.e]); 1723 } 1724 { 1725 enum E { member, a = 0, b = 0 } 1726 1727 static assert(__traits(isSame, EnumMembers!E[0], E.member)); 1728 static assert(__traits(isSame, EnumMembers!E[1], E.a)); 1729 static assert(__traits(isSame, EnumMembers!E[2], E.b)); 1730 1731 static assert(__traits(identifier, EnumMembers!E[0]) == "member"); 1732 static assert(__traits(identifier, EnumMembers!E[1]) == "a"); 1733 static assert(__traits(identifier, EnumMembers!E[2]) == "b"); 1734 } 1735 } 1736 1737 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums 1738 @safe unittest 1739 { 1740 static string genEnum() 1741 { 1742 string result = "enum TLAs {"; 1743 foreach (c0; '0' .. '2' + 1) 1744 { 1745 foreach (c1; '0' .. '9' + 1) 1746 { 1747 foreach (c2; '0' .. '9' + 1) 1748 { 1749 foreach (c3; '0' .. '9' + 1) 1750 { 1751 result ~= '_'; 1752 result ~= c0; 1753 result ~= c1; 1754 result ~= c2; 1755 result ~= c3; 1756 result ~= ','; 1757 } 1758 } 1759 } 1760 } 1761 result ~= '}'; 1762 return result; 1763 } 1764 mixin(genEnum); 1765 static assert(EnumMembers!TLAs[0] == TLAs._0000); 1766 static assert(EnumMembers!TLAs[$ - 1] == TLAs._2999); 1767 } 1768 1769 /++ 1770 Whether the type $(D From) is implicitly convertible to the type $(D To). 1771 1772 Note that template constraints should be very careful about when they test 1773 for implicit conversions and in general should prefer to either test for an 1774 exact set of types or for types which compile with a particular piece of 1775 code rather than being designed to accept any type which implicitly converts 1776 to a particular type. 1777 1778 This is because having a type pass a template constraint based on an 1779 implicit conversion but then not have the implicit conversion actually take 1780 place (which it won't unless the template does something to force it 1781 internally) can lead to either compilation errors or subtle behavioral 1782 differences - and even when the conversion is done explicitly within a 1783 templated function, since it's not done at the call site, it can still lead 1784 to subtle bugs in some cases (e.g. if slicing a static array is involved). 1785 1786 For situations where code needs to verify that a type is implicitly 1787 convertible based solely on its qualifiers, $(LREF isQualifierConvertible) 1788 would be a more appropriate choice than isImplicitlyConvertible. 1789 1790 Given how trivial the $(D is) expression for isImplicitlyConvertible is - 1791 $(D is(To : From)) - this trait is provided primarily so that it can be 1792 used in conjunction with templates that use a template predicate (such as 1793 many of the templates in phobos.sys.meta). 1794 1795 The single-argument overload makes it so that it can be partially 1796 instantiated with the first argument, which will often be necessary with 1797 template predicates. 1798 1799 See_Also: 1800 $(DDSUBLINK dlang.org/spec/type, implicit-conversions, Spec on implicit conversions) 1801 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 1802 $(LREF isQualifierConvertible) 1803 +/ 1804 enum isImplicitlyConvertible(From, To) = is(From : To); 1805 1806 /++ Ditto +/ 1807 template isImplicitlyConvertible(From) 1808 { 1809 enum isImplicitlyConvertible(To) = is(From : To); 1810 } 1811 1812 /// 1813 @safe unittest 1814 { 1815 static assert( isImplicitlyConvertible!(byte, long)); 1816 static assert( isImplicitlyConvertible!(ushort, long)); 1817 static assert( isImplicitlyConvertible!(int, long)); 1818 static assert( isImplicitlyConvertible!(long, long)); 1819 static assert( isImplicitlyConvertible!(ulong, long)); 1820 1821 static assert( isImplicitlyConvertible!(ubyte, int)); 1822 static assert( isImplicitlyConvertible!(short, int)); 1823 static assert( isImplicitlyConvertible!(int, int)); 1824 static assert( isImplicitlyConvertible!(uint, int)); 1825 static assert(!isImplicitlyConvertible!(long, int)); 1826 static assert(!isImplicitlyConvertible!(ulong, int)); 1827 1828 static assert(!isImplicitlyConvertible!(int, string)); 1829 static assert(!isImplicitlyConvertible!(int, int[])); 1830 static assert(!isImplicitlyConvertible!(int, int*)); 1831 1832 static assert(!isImplicitlyConvertible!(string, int)); 1833 static assert(!isImplicitlyConvertible!(int[], int)); 1834 static assert(!isImplicitlyConvertible!(int*, int)); 1835 1836 // For better or worse, bool and the built-in character types will 1837 // implicitly convert to integer or floating-point types if the target type 1838 // is large enough. Sometimes, this is desirable, whereas at other times, 1839 // it can have very surprising results, so it's one reason why code should 1840 // be very careful when testing for implicit conversions. 1841 static assert( isImplicitlyConvertible!(bool, int)); 1842 static assert( isImplicitlyConvertible!(char, int)); 1843 static assert( isImplicitlyConvertible!(wchar, int)); 1844 static assert( isImplicitlyConvertible!(dchar, int)); 1845 1846 static assert( isImplicitlyConvertible!(bool, ubyte)); 1847 static assert( isImplicitlyConvertible!(char, ubyte)); 1848 static assert(!isImplicitlyConvertible!(wchar, ubyte)); 1849 static assert(!isImplicitlyConvertible!(dchar, ubyte)); 1850 1851 static assert( isImplicitlyConvertible!(bool, double)); 1852 static assert( isImplicitlyConvertible!(char, double)); 1853 static assert( isImplicitlyConvertible!(wchar, double)); 1854 static assert( isImplicitlyConvertible!(dchar, double)); 1855 1856 // Value types can be implicitly converted regardless of their qualifiers 1857 // thanks to the fact that they're copied. 1858 static assert( isImplicitlyConvertible!(int, int)); 1859 static assert( isImplicitlyConvertible!(const int, int)); 1860 static assert( isImplicitlyConvertible!(immutable int, int)); 1861 static assert( isImplicitlyConvertible!(inout int, int)); 1862 1863 static assert( isImplicitlyConvertible!(int, const int)); 1864 static assert( isImplicitlyConvertible!(int, immutable int)); 1865 static assert( isImplicitlyConvertible!(int, inout int)); 1866 1867 // Reference types are far more restrictive about which implicit conversions 1868 // they allow, because qualifiers in D are transitive. 1869 static assert( isImplicitlyConvertible!(int*, int*)); 1870 static assert(!isImplicitlyConvertible!(const int*, int*)); 1871 static assert(!isImplicitlyConvertible!(immutable int*, int*)); 1872 1873 static assert( isImplicitlyConvertible!(int*, const int*)); 1874 static assert( isImplicitlyConvertible!(const int*, const int*)); 1875 static assert( isImplicitlyConvertible!(immutable int*, const int*)); 1876 1877 static assert(!isImplicitlyConvertible!(int*, immutable int*)); 1878 static assert(!isImplicitlyConvertible!(const int*, immutable int*)); 1879 static assert( isImplicitlyConvertible!(immutable int*, immutable int*)); 1880 1881 // Note that inout gets a bit weird, since it's only used with function 1882 // parameters, and it's a stand-in for whatever mutability qualifiers the 1883 // type actually has. So, a function parameter that's inout accepts any 1884 // mutability, but you can't actually implicitly convert to inout, because 1885 // it's unknown within the function what the actual mutability of the type 1886 // is. It will differ depending on the function arguments of a specific 1887 // call to that function, so the same code has to work with all combinations 1888 // of mutability qualifiers. 1889 static assert(!isImplicitlyConvertible!(int*, inout int*)); 1890 static assert(!isImplicitlyConvertible!(const int*, inout int*)); 1891 static assert(!isImplicitlyConvertible!(immutable int*, inout int*)); 1892 static assert( isImplicitlyConvertible!(inout int*, inout int*)); 1893 1894 static assert(!isImplicitlyConvertible!(inout int*, int*)); 1895 static assert( isImplicitlyConvertible!(inout int*, const int*)); 1896 static assert(!isImplicitlyConvertible!(inout int*, immutable int*)); 1897 1898 // Enums implicitly convert to their base type. 1899 enum E : int 1900 { 1901 a = 42 1902 } 1903 static assert( isImplicitlyConvertible!(E, int)); 1904 static assert( isImplicitlyConvertible!(E, long)); 1905 static assert(!isImplicitlyConvertible!(E, int[])); 1906 1907 // Structs only implicit convert to another type via declaring an 1908 // alias this. 1909 static struct S 1910 { 1911 int i; 1912 } 1913 static assert(!isImplicitlyConvertible!(S, int)); 1914 static assert(!isImplicitlyConvertible!(S, long)); 1915 static assert(!isImplicitlyConvertible!(S, string)); 1916 1917 static struct AliasThis 1918 { 1919 int i; 1920 alias this = i; 1921 } 1922 static assert( isImplicitlyConvertible!(AliasThis, int)); 1923 static assert( isImplicitlyConvertible!(AliasThis, long)); 1924 static assert(!isImplicitlyConvertible!(AliasThis, string)); 1925 1926 static struct AliasThis2 1927 { 1928 AliasThis at; 1929 alias this = at; 1930 } 1931 static assert( isImplicitlyConvertible!(AliasThis2, AliasThis)); 1932 static assert( isImplicitlyConvertible!(AliasThis2, int)); 1933 static assert( isImplicitlyConvertible!(AliasThis2, long)); 1934 static assert(!isImplicitlyConvertible!(AliasThis2, string)); 1935 1936 static struct AliasThis3 1937 { 1938 AliasThis2 at; 1939 alias this = at; 1940 } 1941 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2)); 1942 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis)); 1943 static assert( isImplicitlyConvertible!(AliasThis3, int)); 1944 static assert( isImplicitlyConvertible!(AliasThis3, long)); 1945 static assert(!isImplicitlyConvertible!(AliasThis3, string)); 1946 1947 // D does not support implicit conversions via construction. 1948 static struct Cons 1949 { 1950 this(int i) 1951 { 1952 this.i = i; 1953 } 1954 1955 int i; 1956 } 1957 static assert(!isImplicitlyConvertible!(int, Cons)); 1958 1959 // Classes support implicit conversion based on their class and 1960 // interface hierarchies. 1961 static interface I1 {} 1962 static class Base : I1 {} 1963 1964 static interface I2 {} 1965 static class Foo : Base, I2 {} 1966 1967 static class Bar : Base {} 1968 1969 static assert( isImplicitlyConvertible!(Base, Base)); 1970 static assert(!isImplicitlyConvertible!(Base, Foo)); 1971 static assert(!isImplicitlyConvertible!(Base, Bar)); 1972 static assert( isImplicitlyConvertible!(Base, I1)); 1973 static assert(!isImplicitlyConvertible!(Base, I2)); 1974 1975 static assert( isImplicitlyConvertible!(Foo, Base)); 1976 static assert( isImplicitlyConvertible!(Foo, Foo)); 1977 static assert(!isImplicitlyConvertible!(Foo, Bar)); 1978 static assert( isImplicitlyConvertible!(Foo, I1)); 1979 static assert( isImplicitlyConvertible!(Foo, I2)); 1980 1981 static assert( isImplicitlyConvertible!(Bar, Base)); 1982 static assert(!isImplicitlyConvertible!(Bar, Foo)); 1983 static assert( isImplicitlyConvertible!(Bar, Bar)); 1984 static assert( isImplicitlyConvertible!(Bar, I1)); 1985 static assert(!isImplicitlyConvertible!(Bar, I2)); 1986 1987 static assert(!isImplicitlyConvertible!(I1, Base)); 1988 static assert(!isImplicitlyConvertible!(I1, Foo)); 1989 static assert(!isImplicitlyConvertible!(I1, Bar)); 1990 static assert( isImplicitlyConvertible!(I1, I1)); 1991 static assert(!isImplicitlyConvertible!(I1, I2)); 1992 1993 static assert(!isImplicitlyConvertible!(I2, Base)); 1994 static assert(!isImplicitlyConvertible!(I2, Foo)); 1995 static assert(!isImplicitlyConvertible!(I2, Bar)); 1996 static assert(!isImplicitlyConvertible!(I2, I1)); 1997 static assert( isImplicitlyConvertible!(I2, I2)); 1998 1999 // Note that arrays are not implicitly convertible even when their elements 2000 // are implicitly convertible. 2001 static assert(!isImplicitlyConvertible!(ubyte[], uint[])); 2002 static assert(!isImplicitlyConvertible!(Foo[], Base[])); 2003 static assert(!isImplicitlyConvertible!(Bar[], Base[])); 2004 2005 // However, like with pointers, dynamic arrays are convertible based on 2006 // constness. 2007 static assert( isImplicitlyConvertible!(Base[], const Base[])); 2008 static assert( isImplicitlyConvertible!(Base[], const(Base)[])); 2009 static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[])); 2010 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 2011 static assert( isImplicitlyConvertible!(const Base[], const Base[])); 2012 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 2013 } 2014 2015 /++ 2016 isImplicitlyConvertible can be used with partial instantiation so that it 2017 can be passed to a template which takes a unary predicate. 2018 +/ 2019 @safe unittest 2020 { 2021 import phobos.sys.meta : AliasSeq, all, indexOf; 2022 2023 // byte is implicitly convertible to byte, short, int, and long. 2024 static assert(all!(isImplicitlyConvertible!byte, short, int, long)); 2025 2026 // const(char)[] at index 2 is the first type in the AliasSeq which string 2027 // can be implicitly converted to. 2028 alias Types = AliasSeq!(int, char[], const(char)[], string, int*); 2029 static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2); 2030 } 2031 2032 /++ 2033 Whether $(D From) is 2034 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) 2035 to $(D To). 2036 2037 This is testing whether $(D From) and $(D To) are the same type - minus the 2038 qualifiers - and whether the qualifiers on $(D From) can be implicitly 2039 converted to the qualifiers on $(D To). No other implicit conversions are 2040 taken into account. 2041 2042 For instance, $(D const int*) is not implicitly convertible to $(D int*), 2043 because that would violate $(D const). That means that $(D const) is not 2044 qualifier convertible to mutable. And as such, $(I any) $(D const) type 2045 is not qualifier convertible to a mutable type even if it's implicitly 2046 convertible. E.G. $(D const int) is implicitly convertible to $(D int), 2047 because it can be copied to avoid violating $(D const), but it's still not 2048 qualifier convertible, because $(D const) types in general cannot be 2049 implicitly converted to mutable. 2050 2051 The exact types being tested matter, because they need to be the same 2052 (minus the qualifiers) in order to be considered convertible, but beyond 2053 that, all that matters for the conversion is whether those qualifers would 2054 be convertible regardless of which types they were on. So, if you're having 2055 trouble picturing whether $(D From) would be qualifier convertible to 2056 $(D To), then consider which conversions would be allowed from $(D From[]) 2057 to $(D To[]) (and remember that dynamic arrays are only implicitly 2058 convertible based on their qualifers). 2059 2060 The $(DDSUBLINK spec/const3, implicit_qualifier_conversions, spec) provides 2061 a table of which qualifiers can be implcitly converted to which other 2062 qualifers (and of course, there a bunch of examples below). 2063 2064 So, isQualifierConvertible can be used in a case like 2065 $(D isQualifierConvertible!(ReturnType!(typeof(foo(bar))), const char), 2066 which would be testing that the return type of $(D foo(bar)) was $(D char), 2067 $(D const char), or $(D immutable char) (since those are the only types 2068 which are qualifier convertible to $(D const char)). 2069 2070 This is in contrast to 2071 $(D isImplicitlyConvertible!(ReturnType!(typeof(foo(bar))), const char), 2072 which would be $(D true) for $(I any) type which was implicitly convertible 2073 to $(D const char) rather than just $(D char), $(D const char), and 2074 $(D immutable char). 2075 2076 The single-argument overload makes it so that it can be partially 2077 instantiated with the first argument, which will often be necessary with 2078 template predicates. 2079 2080 See_Also: 2081 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 2082 $(LREF isImplicitlyConvertible) 2083 +/ 2084 enum isQualifierConvertible(From, To) = is(immutable From == immutable To) && is(From* : To*); 2085 2086 /++ Ditto +/ 2087 template isQualifierConvertible(From) 2088 { 2089 enum isQualifierConvertible(To) = is(immutable From == immutable To) && is(From* : To*); 2090 } 2091 2092 /// 2093 @safe unittest 2094 { 2095 // i.e. char* -> const char* 2096 static assert( isQualifierConvertible!(char, const char)); 2097 2098 // i.e. const char* -> char* 2099 static assert(!isQualifierConvertible!(const char, char)); 2100 2101 static assert( isQualifierConvertible!(int, int)); 2102 static assert( isQualifierConvertible!(int, const int)); 2103 static assert(!isQualifierConvertible!(int, immutable int)); 2104 2105 static assert(!isQualifierConvertible!(const int, int)); 2106 static assert( isQualifierConvertible!(const int, const int)); 2107 static assert(!isQualifierConvertible!(const int, immutable int)); 2108 2109 static assert(!isQualifierConvertible!(immutable int, int)); 2110 static assert( isQualifierConvertible!(immutable int, const int)); 2111 static assert( isQualifierConvertible!(immutable int, immutable int)); 2112 2113 // Note that inout gets a bit weird, since it's only used with function 2114 // parameters, and it's a stand-in for whatever mutability qualifiers the 2115 // type actually has. So, a function parameter that's inout accepts any 2116 // mutability, but you can't actually implicitly convert to inout, because 2117 // it's unknown within the function what the actual mutability of the type 2118 // is. It will differ depending on the function arguments of a specific 2119 // call to that function, so the same code has to work with all combinations 2120 // of mutability qualifiers. 2121 static assert(!isQualifierConvertible!(int, inout int)); 2122 static assert(!isQualifierConvertible!(const int, inout int)); 2123 static assert(!isQualifierConvertible!(immutable int, inout int)); 2124 static assert( isQualifierConvertible!(inout int, inout int)); 2125 2126 static assert(!isQualifierConvertible!(inout int, int)); 2127 static assert( isQualifierConvertible!(inout int, const int)); 2128 static assert(!isQualifierConvertible!(inout int, immutable int)); 2129 2130 // shared is of course also a qualifier. 2131 static assert(!isQualifierConvertible!(int, shared int)); 2132 static assert(!isQualifierConvertible!(int, const shared int)); 2133 static assert(!isQualifierConvertible!(const int, shared int)); 2134 static assert(!isQualifierConvertible!(const int, const shared int)); 2135 static assert(!isQualifierConvertible!(immutable int, shared int)); 2136 static assert( isQualifierConvertible!(immutable int, const shared int)); 2137 2138 static assert(!isQualifierConvertible!(shared int, int)); 2139 static assert(!isQualifierConvertible!(shared int, const int)); 2140 static assert(!isQualifierConvertible!(shared int, immutable int)); 2141 static assert( isQualifierConvertible!(shared int, shared int)); 2142 static assert( isQualifierConvertible!(shared int, const shared int)); 2143 2144 static assert(!isQualifierConvertible!(const shared int, int)); 2145 static assert(!isQualifierConvertible!(const shared int, const int)); 2146 static assert(!isQualifierConvertible!(const shared int, immutable int)); 2147 static assert(!isQualifierConvertible!(const shared int, shared int)); 2148 static assert( isQualifierConvertible!(const shared int, const shared int)); 2149 2150 // Implicit conversions don't count unless they're based purely on 2151 // qualifiers. 2152 enum E : int 2153 { 2154 a = 1 2155 } 2156 2157 static assert(!isQualifierConvertible!(E, int)); 2158 static assert(!isQualifierConvertible!(E, const int)); 2159 static assert( isQualifierConvertible!(E, E)); 2160 static assert( isQualifierConvertible!(E, const E)); 2161 static assert(!isQualifierConvertible!(E, immutable E)); 2162 2163 static struct AliasThis 2164 { 2165 int i; 2166 alias this = i; 2167 } 2168 2169 static assert(!isQualifierConvertible!(AliasThis, int)); 2170 static assert(!isQualifierConvertible!(AliasThis, const int)); 2171 static assert( isQualifierConvertible!(AliasThis, AliasThis)); 2172 static assert( isQualifierConvertible!(AliasThis, const AliasThis)); 2173 static assert(!isQualifierConvertible!(AliasThis, immutable AliasThis)); 2174 2175 // The qualifiers are irrelevant if the types aren't the same when 2176 // stripped of all qualifers. 2177 static assert(!isQualifierConvertible!(int, long)); 2178 static assert(!isQualifierConvertible!(int, const long)); 2179 static assert(!isQualifierConvertible!(string, const(ubyte)[])); 2180 } 2181 2182 /++ 2183 isQualifierConvertible can be used with partial instantiation so that it 2184 can be passed to a template which takes a unary predicate. 2185 +/ 2186 @safe unittest 2187 { 2188 import phobos.sys.meta : AliasSeq, all, indexOf; 2189 2190 // byte is qualifier convertible to byte and const byte. 2191 static assert(all!(isQualifierConvertible!byte, byte, const byte)); 2192 2193 // const(char[]) at index 2 is the first type in the AliasSeq which string 2194 // is qualifier convertible to. 2195 alias Types = AliasSeq!(int, char[], const(char[]), string, int*); 2196 static assert(indexOf!(isQualifierConvertible!string, Types) == 2); 2197 } 2198 2199 @safe unittest 2200 { 2201 import phobos.sys.meta : AliasSeq; 2202 2203 alias Types = AliasSeq!(int, const int, shared int, inout int, const shared int, 2204 const inout int, inout shared int, const inout shared int, immutable int); 2205 2206 // https://dlang.org/spec/const3.html#implicit_qualifier_conversions 2207 enum _ = 0; 2208 static immutable bool[Types.length][Types.length] conversions = [ 2209 // m c s i cs ci is cis im 2210 [1, 1, _, _, _, _, _, _, _], // mutable 2211 [_, 1, _, _, _, _, _, _, _], // const 2212 [_, _, 1, _, 1, _, _, _, _], // shared 2213 [_, 1, _, 1, _, 1, _, _, _], // inout 2214 [_, _, _, _, 1, _, _, _, _], // const shared 2215 [_, 1, _, _, _, 1, _, _, _], // const inout 2216 [_, _, _, _, 1, _, 1, 1, _], // inout shared 2217 [_, _, _, _, 1, _, _, 1, _], // const inout shared 2218 [_, 1, _, _, 1, 1, _, 1, 1], // immutable 2219 ]; 2220 2221 foreach (i, From; Types) 2222 { 2223 foreach (j, To; Types) 2224 { 2225 static assert(isQualifierConvertible!(From, To) == conversions[i][j], 2226 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`" ~ 2227 " should be `" ~ (conversions[i][j] ? "true`" : "false`")); 2228 } 2229 } 2230 } 2231 2232 /++ 2233 Whether the given values are equal per $(D ==). 2234 2235 All this does is $(D lhs == rhs) but in an eponymous template, so most code 2236 shouldn't use it. It's intended to be used in conjunction with templates 2237 that take a template predicate - such as those in phobos.sys.meta. 2238 2239 The single-argument overload makes it so that it can be partially 2240 instantiated with the first argument, which will often be necessary with 2241 template predicates. 2242 2243 Note that in most cases, even when comparing values at compile time, using 2244 isEqual makes no sense, because you can use CTFE to just compare two values 2245 (or expressions which evaluate to values), but in rare cases where you need 2246 to compare symbols in an $(D AliasSeq) by value with a template predicate 2247 while still leaving them as symbols in an $(D AliasSeq), then isEqual would 2248 be needed. 2249 2250 A prime example of this would be $(D Unique!(isEqual, EnumMembers!MyEnum)), 2251 which results in an $(D AliasSeq) containing the list of members of 2252 $(D MyEnum) but without any duplicate values (e.g. to use when doing code 2253 generation to create a final switch). 2254 2255 Alternatively, code such as $(D [EnumMembers!MyEnum].sort().unique()) could 2256 be used to get a dynamic array of the enum members with no duplicate values 2257 via CTFE, thus avoiding the need for template predicates or anything from 2258 phobos.sys.meta. However, you then have a dynamic array of enum values 2259 rather than an $(D AliasSeq) of symbols for those enum members, which 2260 affects what you can do with type introspection. So, which approach is 2261 better depends on what the code needs to do with the enum members. 2262 2263 In general, however, if code doesn't need an $(D AliasSeq), and an array of 2264 values will do the trick, then it's more efficient to operate on an array of 2265 values with CTFE and avoid using isEqual or other templates to operate on 2266 the values as an $(D AliasSeq). 2267 2268 See_Also: 2269 $(LREF isSameSymbol) 2270 $(LREF isSameType) 2271 +/ 2272 enum isEqual(alias lhs, alias rhs) = lhs == rhs; 2273 2274 /++ Ditto +/ 2275 template isEqual(alias lhs) 2276 { 2277 enum isEqual(alias rhs) = lhs == rhs; 2278 } 2279 2280 /// It acts just like ==, but it's a template. 2281 @safe unittest 2282 { 2283 enum a = 42; 2284 2285 static assert( isEqual!(a, 42)); 2286 static assert( isEqual!(20, 10 + 10)); 2287 2288 static assert(!isEqual!(a, 120)); 2289 static assert(!isEqual!(77, 19 * 7 + 2)); 2290 2291 // b cannot be read at compile time, so it won't work with isEqual. 2292 int b = 99; 2293 static assert(!__traits(compiles, isEqual!(b, 99))); 2294 } 2295 2296 /++ 2297 Comparing some of the differences between an $(D AliasSeq) of enum members 2298 and an array of enum values created from an $(D AliasSeq) of enum members. 2299 +/ 2300 @safe unittest 2301 { 2302 import phobos.sys.meta : AliasSeq, Unique; 2303 2304 enum E 2305 { 2306 a = 0, 2307 b = 22, 2308 c = 33, 2309 d = 0, 2310 e = 256, 2311 f = 33, 2312 g = 7 2313 } 2314 2315 alias uniqueMembers = Unique!(isEqual, EnumMembers!E); 2316 static assert(uniqueMembers.length == 5); 2317 2318 static assert(__traits(isSame, uniqueMembers[0], E.a)); 2319 static assert(__traits(isSame, uniqueMembers[1], E.b)); 2320 static assert(__traits(isSame, uniqueMembers[2], E.c)); 2321 static assert(__traits(isSame, uniqueMembers[3], E.e)); 2322 static assert(__traits(isSame, uniqueMembers[4], E.g)); 2323 2324 static assert(__traits(identifier, uniqueMembers[0]) == "a"); 2325 static assert(__traits(identifier, uniqueMembers[1]) == "b"); 2326 static assert(__traits(identifier, uniqueMembers[2]) == "c"); 2327 static assert(__traits(identifier, uniqueMembers[3]) == "e"); 2328 static assert(__traits(identifier, uniqueMembers[4]) == "g"); 2329 2330 // Same value but different symbol. 2331 static assert(uniqueMembers[0] == E.d); 2332 static assert(!__traits(isSame, uniqueMembers[0], E.d)); 2333 2334 // is expressions compare types, not symbols or values, and these AliasSeqs 2335 // contain the list of symbols for the enum members, not types, so the is 2336 // expression evaluates to false even though the symbols are the same. 2337 static assert(!is(uniqueMembers == AliasSeq!(E.a, E.b, E.c, E.e, E.g))); 2338 2339 // Once the members are converted to an array, the types are the same, and 2340 // the values are the same, but the symbols are not the same. Instead of 2341 // being the symbols E.a, E.b, etc., they're just values with the type E 2342 // which match the values of E.a, E.b, etc. 2343 enum arr = [uniqueMembers]; 2344 static assert(is(typeof(arr) == E[])); 2345 2346 static assert(arr == [E.a, E.b, E.c, E.e, E.g]); 2347 static assert(arr == [E.d, E.b, E.f, E.e, E.g]); 2348 2349 static assert(!__traits(isSame, arr[0], E.a)); 2350 static assert(!__traits(isSame, arr[1], E.b)); 2351 static assert(!__traits(isSame, arr[2], E.c)); 2352 static assert(!__traits(isSame, arr[3], E.e)); 2353 static assert(!__traits(isSame, arr[4], E.g)); 2354 2355 // Since arr[0] is just a value of type E, it's no longer the symbol, E.a, 2356 // even though its type is E, and its value is the same as that of E.a. And 2357 // unlike the actual members of an enum, an element of an array does not 2358 // have an identifier, so __traits(identifier, ...) doesn't work with it. 2359 static assert(!__traits(compiles, __traits(identifier, arr[0]))); 2360 2361 // Similarly, once an enum member from the AliasSeq is assigned to a 2362 // variable, __traits(identifer, ...) operates on the variable, not the 2363 // symbol from the AliasSeq or the value of the variable. 2364 auto var = uniqueMembers[0]; 2365 static assert(__traits(identifier, var) == "var"); 2366 2367 // The same with a manifest constant. 2368 enum constant = uniqueMembers[0]; 2369 static assert(__traits(identifier, constant) == "constant"); 2370 } 2371 2372 /++ 2373 Whether the given symbols are the same symbol. 2374 2375 All this does is $(D __traits(isSame, lhs, rhs)), so most code shouldn't 2376 use it. It's intended to be used in conjunction with templates that take a 2377 template predicate - such as those in phobos.sys.meta. 2378 2379 The single-argument overload makes it so that it can be partially 2380 instantiated with the first argument, which will often be necessary with 2381 template predicates. 2382 2383 See_Also: 2384 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, lhs, rhs))) 2385 $(LREF isEqual) 2386 $(LREF isSameType) 2387 +/ 2388 enum isSameSymbol(alias lhs, alias rhs) = __traits(isSame, lhs, rhs); 2389 2390 /++ Ditto +/ 2391 template isSameSymbol(alias lhs) 2392 { 2393 enum isSameSymbol(alias rhs) = __traits(isSame, lhs, rhs); 2394 } 2395 2396 /// 2397 @safe unittest 2398 { 2399 int i; 2400 int j; 2401 real r; 2402 2403 static assert( isSameSymbol!(i, i)); 2404 static assert(!isSameSymbol!(i, j)); 2405 static assert(!isSameSymbol!(i, r)); 2406 2407 static assert(!isSameSymbol!(j, i)); 2408 static assert( isSameSymbol!(j, j)); 2409 static assert(!isSameSymbol!(j, r)); 2410 2411 static assert(!isSameSymbol!(r, i)); 2412 static assert(!isSameSymbol!(r, j)); 2413 static assert( isSameSymbol!(r, r)); 2414 2415 auto foo() { return 0; } 2416 auto bar() { return 0; } 2417 2418 static assert( isSameSymbol!(foo, foo)); 2419 static assert(!isSameSymbol!(foo, bar)); 2420 static assert(!isSameSymbol!(foo, i)); 2421 2422 static assert(!isSameSymbol!(bar, foo)); 2423 static assert( isSameSymbol!(bar, bar)); 2424 static assert(!isSameSymbol!(bar, i)); 2425 2426 // Types are symbols too. However, in most cases, they should be compared 2427 // as types, not symbols (be it with is expressions or with isSameType), 2428 // because the results aren't consistent between scalar types and 2429 // user-defined types with regards to type qualifiers when they're compared 2430 // as symbols. 2431 static assert( isSameSymbol!(double, double)); 2432 static assert(!isSameSymbol!(double, const double)); 2433 static assert(!isSameSymbol!(double, int)); 2434 static assert( isSameSymbol!(Object, Object)); 2435 static assert( isSameSymbol!(Object, const Object)); 2436 2437 static assert(!isSameSymbol!(i, int)); 2438 static assert( isSameSymbol!(typeof(i), int)); 2439 2440 // Lambdas can be compared with __traits(isSame, ...), 2441 // so they can be compared with isSameSymbol. 2442 static assert( isSameSymbol!(a => a + 42, a => a + 42)); 2443 static assert(!isSameSymbol!(a => a + 42, a => a + 99)); 2444 2445 // Partial instantiation allows it to be used with templates that expect 2446 // a predicate that takes only a single argument. 2447 import phobos.sys.meta : AliasSeq, indexOf; 2448 alias Types = AliasSeq!(i, j, r, int, long, foo); 2449 static assert(indexOf!(isSameSymbol!j, Types) == 1); 2450 static assert(indexOf!(isSameSymbol!int, Types) == 3); 2451 static assert(indexOf!(isSameSymbol!bar, Types) == -1); 2452 } 2453 2454 /++ 2455 Whether the given types are the same type. 2456 2457 All this does is $(D is(T == U)), so most code shouldn't use it. It's 2458 intended to be used in conjunction with templates that take a template 2459 predicate - such as those in phobos.sys.meta. 2460 2461 The single-argument overload makes it so that it can be partially 2462 instantiated with the first argument, which will often be necessary with 2463 template predicates. 2464 2465 See_Also: 2466 $(LREF isEqual) 2467 $(LREF isSameSymbol) 2468 +/ 2469 enum isSameType(T, U) = is(T == U); 2470 2471 /++ Ditto +/ 2472 template isSameType(T) 2473 { 2474 enum isSameType(U) = is(T == U); 2475 } 2476 2477 /// 2478 @safe unittest 2479 { 2480 static assert( isSameType!(long, long)); 2481 static assert(!isSameType!(long, const long)); 2482 static assert(!isSameType!(long, string)); 2483 static assert( isSameType!(string, string)); 2484 2485 int i; 2486 real r; 2487 static assert( isSameType!(int, typeof(i))); 2488 static assert(!isSameType!(int, typeof(r))); 2489 2490 static assert(!isSameType!(real, typeof(i))); 2491 static assert( isSameType!(real, typeof(r))); 2492 2493 // Partial instantiation allows it to be used with templates that expect 2494 // a predicate that takes only a single argument. 2495 import phobos.sys.meta : AliasSeq, indexOf; 2496 alias Types = AliasSeq!(float, string, int, double); 2497 static assert(indexOf!(isSameType!int, Types) == 2); 2498 } 2499 2500 /++ 2501 Evaluates to an $(D AliasSeq) of the names (as $(D string)s) of the member 2502 variables of an aggregate type (i.e. a struct, class, interface, or union). 2503 2504 These are fields which take up memory space within an instance of the type 2505 (i.e. not enums / manifest constants, since they don't take up memory 2506 space, and not static member variables, since they don't take up memory 2507 space within an instance). 2508 2509 Hidden fields (like the virtual function table pointer or the context 2510 pointer for nested types) are not included. 2511 2512 For classes, only the direct member variables are included and not those 2513 of any base classes. 2514 2515 For interfaces, the result of FieldNames is always empty, because 2516 interfaces cannot have member variables. However, because interfaces are 2517 aggregate types, they work with FieldNames for consistency so that code 2518 that's written to work on aggregate types doesn't have to worry about 2519 whether it's dealing with an interface. 2520 2521 See_Also: 2522 $(LREF FieldSymbols) 2523 $(LREF FieldTypes) 2524 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 2525 +/ 2526 template FieldNames(T) 2527 if (isAggregateType!T) 2528 { 2529 import phobos.sys.meta : AliasSeq; 2530 2531 static if (is(T == struct) && __traits(isNested, T)) 2532 private alias Fields = AliasSeq!(T.tupleof[0 .. $ - 1]); 2533 else 2534 private alias Fields = T.tupleof; 2535 2536 alias FieldNames = AliasSeq!(); 2537 static foreach (Field; Fields) 2538 FieldNames = AliasSeq!(FieldNames, Field.stringof); 2539 } 2540 2541 /// 2542 @safe unittest 2543 { 2544 import phobos.sys.meta : AliasSeq; 2545 2546 struct S 2547 { 2548 int x; 2549 float y; 2550 } 2551 static assert(FieldNames!S == AliasSeq!("x", "y")); 2552 2553 // Since the AliasSeq contains values, all of which are of the same type, 2554 // it can be used to create a dynamic array, which would be more 2555 // efficient than operating on an AliasSeq in the cases where an 2556 // AliasSeq is not necessary. 2557 static assert([FieldNames!S] == ["x", "y"]); 2558 2559 class C 2560 { 2561 // static variables are not included. 2562 static int var; 2563 2564 // Manifest constants are not included. 2565 enum lang = "dlang"; 2566 2567 // Functions are not included, even if they're @property functions. 2568 @property int foo() { return 42; } 2569 2570 string s; 2571 int i; 2572 int[] arr; 2573 } 2574 static assert(FieldNames!C == AliasSeq!("s", "i", "arr")); 2575 2576 static assert([FieldNames!C] == ["s", "i", "arr"]); 2577 2578 // Only direct member variables are included. Member variables from any base 2579 // classes are not. 2580 class D : C 2581 { 2582 real r; 2583 } 2584 static assert(FieldNames!D == AliasSeq!"r"); 2585 2586 static assert([FieldNames!D] == ["r"]); 2587 2588 // FieldNames will always be empty for an interface, since it's not legal 2589 // for interfaces to have member variables. 2590 interface I 2591 { 2592 } 2593 static assert(FieldNames!I.length == 0); 2594 2595 union U 2596 { 2597 int i; 2598 double d; 2599 long l; 2600 S s; 2601 } 2602 static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s")); 2603 2604 static assert([FieldNames!U] == ["i", "d", "l", "s"]);; 2605 2606 // FieldNames only operates on aggregate types. 2607 static assert(!__traits(compiles, FieldNames!int)); 2608 static assert(!__traits(compiles, FieldNames!(S*))); 2609 static assert(!__traits(compiles, FieldNames!(C[]))); 2610 } 2611 2612 @safe unittest 2613 { 2614 import phobos.sys.meta : AliasSeq; 2615 2616 { 2617 static struct S0 {} 2618 static assert(FieldNames!S0.length == 0); 2619 2620 static struct S1 { int a; } 2621 static assert(FieldNames!S1 == AliasSeq!"a"); 2622 2623 static struct S2 { int a; string b; } 2624 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 2625 2626 static struct S3 { int a; string b; real c; } 2627 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 2628 } 2629 { 2630 int i; 2631 struct S0 { void foo() { i = 0; }} 2632 static assert(FieldNames!S0.length == 0); 2633 static assert(__traits(isNested, S0)); 2634 2635 struct S1 { int a; void foo() { i = 0; } } 2636 static assert(FieldNames!S1 == AliasSeq!"a"); 2637 static assert(__traits(isNested, S1)); 2638 2639 struct S2 { int a; string b; void foo() { i = 0; } } 2640 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 2641 static assert(__traits(isNested, S2)); 2642 2643 struct S3 { int a; string b; real c; void foo() { i = 0; } } 2644 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 2645 static assert(__traits(isNested, S3)); 2646 } 2647 { 2648 static class C0 {} 2649 static assert(FieldNames!C0.length == 0); 2650 2651 static class C1 { int a; } 2652 static assert(FieldNames!C1 == AliasSeq!"a"); 2653 2654 static class C2 { int a; string b; } 2655 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 2656 2657 static class C3 { int a; string b; real c; } 2658 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 2659 2660 static class D0 : C3 {} 2661 static assert(FieldNames!D0.length == 0); 2662 2663 static class D1 : C3 { bool x; } 2664 static assert(FieldNames!D1 == AliasSeq!"x"); 2665 2666 static class D2 : C3 { bool x; int* y; } 2667 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 2668 2669 static class D3 : C3 { bool x; int* y; short[] z; } 2670 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 2671 } 2672 { 2673 int i; 2674 class C0 { void foo() { i = 0; }} 2675 static assert(FieldNames!C0.length == 0); 2676 static assert(__traits(isNested, C0)); 2677 2678 class C1 { int a; void foo() { i = 0; } } 2679 static assert(FieldNames!C1 == AliasSeq!"a"); 2680 static assert(__traits(isNested, C1)); 2681 2682 class C2 { int a; string b; void foo() { i = 0; } } 2683 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 2684 static assert(__traits(isNested, C2)); 2685 2686 class C3 { int a; string b; real c; void foo() { i = 0; } } 2687 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 2688 static assert(__traits(isNested, C3)); 2689 2690 class D0 : C3 {} 2691 static assert(FieldNames!D0.length == 0); 2692 static assert(__traits(isNested, D0)); 2693 2694 class D1 : C3 { bool x; } 2695 static assert(FieldNames!D1 == AliasSeq!"x"); 2696 static assert(__traits(isNested, D1)); 2697 2698 class D2 : C3 { bool x; int* y; } 2699 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 2700 static assert(__traits(isNested, D2)); 2701 2702 class D3 : C3 { bool x; int* y; short[] z; } 2703 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 2704 static assert(__traits(isNested, D3)); 2705 } 2706 { 2707 static union U0 {} 2708 static assert(FieldNames!U0.length == 0); 2709 2710 static union U1 { int a; } 2711 static assert(FieldNames!U1 == AliasSeq!"a"); 2712 2713 static union U2 { int a; string b; } 2714 static assert(FieldNames!U2 == AliasSeq!("a", "b")); 2715 2716 static union U3 { int a; string b; real c; } 2717 static assert(FieldNames!U3 == AliasSeq!("a", "b", "c")); 2718 } 2719 { 2720 static struct S 2721 { 2722 enum e = 42; 2723 static str = "foobar"; 2724 2725 string name() { return "foo"; } 2726 2727 int[] arr; 2728 2729 struct Inner1 { int i; } 2730 2731 static struct Inner2 { long gnol; } 2732 2733 union { int a; string b; } 2734 2735 alias Foo = Inner1; 2736 } 2737 2738 static assert(FieldNames!S == AliasSeq!("arr", "a", "b")); 2739 static assert(FieldNames!(const S) == AliasSeq!("arr", "a", "b")); 2740 static assert(FieldNames!(S.Inner1) == AliasSeq!"i"); 2741 static assert(FieldNames!(S.Inner2) == AliasSeq!"gnol"); 2742 } 2743 } 2744 2745 /++ 2746 Evaluates to an $(D AliasSeq) of the symbols for the member variables of an 2747 aggregate type (i.e. a struct, class, interface, or union). 2748 2749 These are fields which take up memory space within an instance of the type 2750 (i.e. not enums / manifest constants, since they don't take up memory 2751 space, and not static member variables, since they don't take up memory 2752 space within an instance). 2753 2754 Hidden fields (like the virtual function table pointer or the context 2755 pointer for nested types) are not included. 2756 2757 For classes, only the direct member variables are included and not those 2758 of any base classes. 2759 2760 For interfaces, the result of FieldSymbols is always empty, because 2761 interfaces cannot have member variables. However, because interfaces are 2762 aggregate types, they work with FieldSymbols for consistency so that code 2763 that's written to work on aggregate types doesn't have to worry about 2764 whether it's dealing with an interface. 2765 2766 In most cases, $(D FieldSymbols!T) has the same result as $(D T.tupleof). 2767 The difference is that for nested structs with a context pointer, 2768 $(D T.tupleof) includes the context pointer, whereas $(D FieldSymbols!T) 2769 does not. For non-nested structs, and for classes, interfaces, and unions, 2770 $(D FieldSymbols!T) and $(D T.tupleof) are the same. 2771 2772 So, for most cases, $(D T.tupleof) is sufficient and avoids instantiating 2773 an additional template, but FieldSymbols is provided so that the code that 2774 needs to avoid including context pointers in the list of fields can do so 2775 without the programmer having to figure how to do that correctly. It also 2776 provides a template that's equivalent to what $(LREF FieldNames) and 2777 $(LREF FieldTypes) do in terms of which fields it gives (the difference of 2778 course then being whether you get the symbols, names, or types for the 2779 fields), whereas the behavior for $(D tupleof) is subtly different. 2780 2781 See_Also: 2782 $(LREF FieldNames) 2783 $(LREF FieldTypes) 2784 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 2785 $(DDSUBLINK spec/traits, isNested, $(D __traits(isNested, ...))). 2786 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, ...))). 2787 +/ 2788 template FieldSymbols(T) 2789 if (isAggregateType!T) 2790 { 2791 static if (is(T == struct) && __traits(isNested, T)) 2792 { 2793 import phobos.sys.meta : AliasSeq; 2794 alias FieldSymbols = AliasSeq!(T.tupleof[0 .. $ - 1]); 2795 } 2796 else 2797 alias FieldSymbols = T.tupleof; 2798 } 2799 2800 /// 2801 @safe unittest 2802 { 2803 import phobos.sys.meta : AliasSeq; 2804 2805 struct S 2806 { 2807 int x; 2808 float y; 2809 } 2810 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.x, S.y))); 2811 2812 // FieldSymbols!S and S.tupleof are the same, because S is not nested. 2813 static assert(__traits(isSame, FieldSymbols!S, S.tupleof)); 2814 2815 // Note that type qualifiers _should_ be passed on to the result, but due 2816 // to https://issues.dlang.org/show_bug.cgi?id=24516, they aren't. 2817 // FieldTypes does not have this problem, because it aliases the types 2818 // rather than the symbols, so if you need the types from the symbols, you 2819 // should use either FieldTypes or tupleof until the compiler bug has been 2820 // fixed (and if you use tupleof, you need to avoid aliasing the result 2821 // before getting the types from it). 2822 static assert(is(typeof(FieldSymbols!S[0]) == int)); 2823 2824 // These currently fail when they shouldn't: 2825 //static assert(is(typeof(FieldSymbols!(const S)[0]) == const int)); 2826 //static assert(is(typeof(FieldSymbols!(shared S)[0]) == shared int)); 2827 2828 class C 2829 { 2830 // static variables are not included. 2831 static int var; 2832 2833 // Manifest constants are not included. 2834 enum lang = "dlang"; 2835 2836 // Functions are not included, even if they're @property functions. 2837 @property int foo() { return 42; } 2838 2839 string s; 2840 int i; 2841 int[] arr; 2842 } 2843 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.s, C.i, C.arr))); 2844 2845 // FieldSymbols!C and C.tupleof have the same symbols, because they are 2846 // always the same for classes. 2847 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 2848 2849 // Only direct member variables are included. Member variables from any base 2850 // classes are not. 2851 class D : C 2852 { 2853 real r; 2854 } 2855 static assert(__traits(isSame, FieldSymbols!D, AliasSeq!(D.r))); 2856 static assert(__traits(isSame, FieldSymbols!D, D.tupleof)); 2857 2858 // FieldSymbols will always be empty for an interface, since it's not legal 2859 // for interfaces to have member variables. 2860 interface I 2861 { 2862 } 2863 static assert(FieldSymbols!I.length == 0); 2864 static assert(I.tupleof.length == 0); 2865 2866 union U 2867 { 2868 int i; 2869 double d; 2870 long l; 2871 S s; 2872 } 2873 static assert(__traits(isSame, FieldSymbols!U, AliasSeq!(U.i, U.d, U.l, U.s))); 2874 2875 // FieldSymbols!C and C.tupleof have the same symbols, because they are 2876 // always the same for unions. 2877 static assert(__traits(isSame, FieldSymbols!U, U.tupleof)); 2878 2879 // FieldSymbols only operates on aggregate types. 2880 static assert(!__traits(compiles, FieldSymbols!int)); 2881 static assert(!__traits(compiles, FieldSymbols!(S*))); 2882 static assert(!__traits(compiles, FieldSymbols!(C[]))); 2883 } 2884 2885 /// Some examples with nested types. 2886 @safe unittest 2887 { 2888 import phobos.sys.meta : AliasSeq; 2889 2890 int outside; 2891 2892 struct S 2893 { 2894 long l; 2895 string s; 2896 2897 void foo() { outside = 2; } 2898 } 2899 static assert(__traits(isNested, S)); 2900 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.l, S.s))); 2901 2902 // FieldSymbols!S and S.tupleof are not the same, because S is nested, and 2903 // the context pointer to the outer scope is included in S.tupleof, whereas 2904 // it is excluded from FieldSymbols!S. 2905 static assert(__traits(isSame, S.tupleof[0 .. $ - 1], AliasSeq!(S.l, S.s))); 2906 static assert(S.tupleof[$ - 1].stringof == "this"); 2907 2908 class C 2909 { 2910 bool b; 2911 int* ptr; 2912 2913 void foo() { outside = 7; } 2914 } 2915 static assert(__traits(isNested, C)); 2916 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.b, C.ptr))); 2917 2918 // FieldSymbols!C and C.tupleof have the same symbols, because they are 2919 // always the same for classes. No context pointer is provided as part of 2920 // tupleof for nested classes. 2921 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 2922 2923 // __traits(isNested, ...) is never true for interfaces or unions, since 2924 // they cannot have a context pointer to an outer scope. So, tupleof and 2925 // FieldSymbols will always be the same for interfaces and unions. 2926 } 2927 2928 @safe unittest 2929 { 2930 import phobos.sys.meta : AliasSeq; 2931 2932 { 2933 static struct S0 {} 2934 static assert(FieldSymbols!S0.length == 0); 2935 2936 static struct S1 { int a; } 2937 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 2938 2939 static struct S2 { int a; string b; } 2940 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 2941 2942 static struct S3 { int a; string b; real c; } 2943 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 2944 } 2945 { 2946 int i; 2947 struct S0 { void foo() { i = 0; }} 2948 static assert(FieldSymbols!S0.length == 0); 2949 static assert(__traits(isNested, S0)); 2950 2951 struct S1 { int a; void foo() { i = 0; } } 2952 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 2953 static assert(__traits(isNested, S1)); 2954 2955 struct S2 { int a; string b; void foo() { i = 0; } } 2956 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 2957 static assert(__traits(isNested, S2)); 2958 2959 struct S3 { int a; string b; real c; void foo() { i = 0; } } 2960 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 2961 static assert(__traits(isNested, S3)); 2962 } 2963 { 2964 static class C0 {} 2965 static assert(FieldSymbols!C0.length == 0); 2966 2967 static class C1 { int a; } 2968 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 2969 2970 static class C2 { int a; string b; } 2971 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 2972 2973 static class C3 { int a; string b; real c; } 2974 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 2975 2976 static class D0 : C3 {} 2977 static assert(FieldSymbols!D0.length == 0); 2978 2979 static class D1 : C3 { bool x; } 2980 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 2981 2982 static class D2 : C3 { bool x; int* y; } 2983 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 2984 2985 static class D3 : C3 { bool x; int* y; short[] z; } 2986 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 2987 } 2988 { 2989 int i; 2990 class C0 { void foo() { i = 0; }} 2991 static assert(FieldSymbols!C0.length == 0); 2992 static assert(__traits(isNested, C0)); 2993 2994 class C1 { int a; void foo() { i = 0; } } 2995 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 2996 static assert(__traits(isNested, C1)); 2997 2998 class C2 { int a; string b; void foo() { i = 0; } } 2999 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 3000 static assert(__traits(isNested, C2)); 3001 3002 class C3 { int a; string b; real c; void foo() { i = 0; } } 3003 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 3004 static assert(__traits(isNested, C3)); 3005 3006 class D0 : C3 {} 3007 static assert(FieldSymbols!D0.length == 0); 3008 static assert(__traits(isNested, D0)); 3009 3010 class D1 : C3 { bool x; } 3011 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 3012 static assert(__traits(isNested, D1)); 3013 3014 class D2 : C3 { bool x; int* y; } 3015 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 3016 static assert(__traits(isNested, D2)); 3017 3018 class D3 : C3 { bool x; int* y; short[] z; } 3019 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 3020 static assert(__traits(isNested, D3)); 3021 } 3022 { 3023 static union U0 {} 3024 static assert(FieldSymbols!U0.length == 0); 3025 3026 static union U1 { int a; } 3027 static assert(__traits(isSame, FieldSymbols!U1, AliasSeq!(U1.a))); 3028 3029 static union U2 { int a; string b; } 3030 static assert(__traits(isSame, FieldSymbols!U2, AliasSeq!(U2.a, U2.b))); 3031 3032 static union U3 { int a; string b; real c; } 3033 static assert(__traits(isSame, FieldSymbols!U3, AliasSeq!(U3.a, U3.b, U3.c))); 3034 } 3035 { 3036 static struct S 3037 { 3038 enum e = 42; 3039 static str = "foobar"; 3040 3041 string name() { return "foo"; } 3042 3043 int[] arr; 3044 3045 struct Inner1 { int i; } 3046 3047 static struct Inner2 { long gnol; } 3048 3049 union { int a; string b; } 3050 3051 alias Foo = Inner1; 3052 } 3053 3054 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.arr, S.a, S.b))); 3055 static assert(__traits(isSame, FieldSymbols!(const S), AliasSeq!(S.arr, S.a, S.b))); 3056 static assert(__traits(isSame, FieldSymbols!(S.Inner1), AliasSeq!(S.Inner1.i))); 3057 static assert(__traits(isSame, FieldSymbols!(S.Inner2), AliasSeq!(S.Inner2.gnol))); 3058 } 3059 } 3060 3061 /++ 3062 Evaluates to an $(D AliasSeq) of the types of the member variables of an 3063 aggregate type (i.e. a struct, class, interface, or union). 3064 3065 These are fields which take up memory space within an instance of the type 3066 (i.e. not enums / manifest constants, since they don't take up memory 3067 space, and not static member variables, since they don't take up memory 3068 space within an instance). 3069 3070 Hidden fields (like the virtual function table pointer or the context 3071 pointer for nested types) are not included. 3072 3073 For classes, only the direct member variables are included and not those 3074 of any base classes. 3075 3076 For interfaces, the result of FieldTypes is always empty, because 3077 interfaces cannot have member variables. However, because interfaces are 3078 aggregate types, they work with FieldTypes for consistency so that code 3079 that's written to work on aggregate types doesn't have to worry about 3080 whether it's dealing with an interface. 3081 3082 See_Also: 3083 $(LREF FieldNames) 3084 $(LREF FieldSymbols) 3085 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 3086 +/ 3087 template FieldTypes(T) 3088 if (isAggregateType!T) 3089 { 3090 static if (is(T == struct) && __traits(isNested, T)) 3091 alias FieldTypes = typeof(T.tupleof[0 .. $ - 1]); 3092 else 3093 alias FieldTypes = typeof(T.tupleof); 3094 } 3095 3096 /// 3097 @safe unittest 3098 { 3099 import phobos.sys.meta : AliasSeq; 3100 3101 struct S 3102 { 3103 int x; 3104 float y; 3105 } 3106 static assert(is(FieldTypes!S == AliasSeq!(int, float))); 3107 3108 // Type qualifers will be passed on to the result. 3109 static assert(is(FieldTypes!(const S) == AliasSeq!(const int, const float))); 3110 static assert(is(FieldTypes!(shared S) == AliasSeq!(shared int, shared float))); 3111 3112 class C 3113 { 3114 // static variables are not included. 3115 static int var; 3116 3117 // Manifest constants are not included. 3118 enum lang = "dlang"; 3119 3120 // Functions are not included, even if they're @property functions. 3121 @property int foo() { return 42; } 3122 3123 string s; 3124 int i; 3125 int[] arr; 3126 } 3127 static assert(is(FieldTypes!C == AliasSeq!(string, int, int[]))); 3128 3129 // Only direct member variables are included. Member variables from any base 3130 // classes are not. 3131 class D : C 3132 { 3133 real r; 3134 } 3135 static assert(is(FieldTypes!D == AliasSeq!real)); 3136 3137 // FieldTypes will always be empty for an interface, since it's not legal 3138 // for interfaces to have member variables. 3139 interface I 3140 { 3141 } 3142 static assert(FieldTypes!I.length == 0); 3143 3144 union U 3145 { 3146 int i; 3147 double d; 3148 long l; 3149 S s; 3150 } 3151 static assert(is(FieldTypes!U == AliasSeq!(int, double, long, S))); 3152 3153 // FieldTypes only operates on aggregate types. 3154 static assert(!__traits(compiles, FieldTypes!int)); 3155 static assert(!__traits(compiles, FieldTypes!(S*))); 3156 static assert(!__traits(compiles, FieldTypes!(C[]))); 3157 } 3158 3159 @safe unittest 3160 { 3161 import phobos.sys.meta : AliasSeq; 3162 3163 { 3164 static struct S0 {} 3165 static assert(FieldTypes!S0.length == 0); 3166 3167 static struct S1 { int a; } 3168 static assert(is(FieldTypes!S1 == AliasSeq!int)); 3169 3170 static struct S2 { int a; string b; } 3171 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 3172 3173 static struct S3 { int a; string b; real c; } 3174 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 3175 } 3176 { 3177 int i; 3178 struct S0 { void foo() { i = 0; }} 3179 static assert(FieldTypes!S0.length == 0); 3180 static assert(__traits(isNested, S0)); 3181 3182 struct S1 { int a; void foo() { i = 0; } } 3183 static assert(is(FieldTypes!S1 == AliasSeq!int)); 3184 static assert(__traits(isNested, S1)); 3185 3186 struct S2 { int a; string b; void foo() { i = 0; } } 3187 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 3188 static assert(__traits(isNested, S2)); 3189 3190 struct S3 { int a; string b; real c; void foo() { i = 0; } } 3191 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 3192 static assert(__traits(isNested, S3)); 3193 } 3194 { 3195 static class C0 {} 3196 static assert(FieldTypes!C0.length == 0); 3197 3198 static class C1 { int a; } 3199 static assert(is(FieldTypes!C1 == AliasSeq!int)); 3200 3201 static class C2 { int a; string b; } 3202 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 3203 3204 static class C3 { int a; string b; real c; } 3205 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 3206 3207 static class D0 : C3 {} 3208 static assert(FieldTypes!D0.length == 0); 3209 3210 static class D1 : C3 { bool x; } 3211 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 3212 3213 static class D2 : C3 { bool x; int* y; } 3214 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 3215 3216 static class D3 : C3 { bool x; int* y; short[] z; } 3217 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 3218 } 3219 { 3220 int i; 3221 class C0 { void foo() { i = 0; }} 3222 static assert(FieldTypes!C0.length == 0); 3223 static assert(__traits(isNested, C0)); 3224 3225 class C1 { int a; void foo() { i = 0; } } 3226 static assert(is(FieldTypes!C1 == AliasSeq!int)); 3227 static assert(__traits(isNested, C1)); 3228 3229 class C2 { int a; string b; void foo() { i = 0; } } 3230 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 3231 static assert(__traits(isNested, C2)); 3232 3233 class C3 { int a; string b; real c; void foo() { i = 0; } } 3234 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 3235 static assert(__traits(isNested, C3)); 3236 3237 class D0 : C3 {} 3238 static assert(FieldTypes!D0.length == 0); 3239 static assert(__traits(isNested, D0)); 3240 3241 class D1 : C3 { bool x; } 3242 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 3243 static assert(__traits(isNested, D1)); 3244 3245 class D2 : C3 { bool x; int* y; } 3246 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 3247 static assert(__traits(isNested, D2)); 3248 3249 class D3 : C3 { bool x; int* y; short[] z; } 3250 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 3251 static assert(__traits(isNested, D3)); 3252 } 3253 { 3254 static union U0 {} 3255 static assert(FieldTypes!U0.length == 0); 3256 3257 static union U1 { int a; } 3258 static assert(is(FieldTypes!U1 == AliasSeq!int)); 3259 3260 static union U2 { int a; string b; } 3261 static assert(is(FieldTypes!U2 == AliasSeq!(int, string))); 3262 3263 static union U3 { int a; string b; real c; } 3264 static assert(is(FieldTypes!U3 == AliasSeq!(int, string, real))); 3265 } 3266 { 3267 static struct S 3268 { 3269 enum e = 42; 3270 static str = "foobar"; 3271 3272 string name() { return "foo"; } 3273 3274 int[] arr; 3275 3276 struct Inner1 { int i; } 3277 3278 static struct Inner2 { long gnol; } 3279 3280 union { int a; string b; } 3281 3282 alias Foo = Inner1; 3283 } 3284 3285 static assert(is(FieldTypes!S == AliasSeq!(int[], int, string))); 3286 static assert(is(FieldTypes!(const S) == AliasSeq!(const(int[]), const int, const string))); 3287 static assert(is(FieldTypes!(S.Inner1) == AliasSeq!int)); 3288 static assert(is(FieldTypes!(S.Inner2) == AliasSeq!long)); 3289 } 3290 } 3291 3292 /++ 3293 Whether assigning to a variable of the given type involves either a 3294 user-defined $(D opAssign) or a compiler-generated $(D opAssign) rather than 3295 using the default assignment behavior (which would use $(D memcpy)). The 3296 $(D opAssign) must accept the same type (with compatible qualifiers) as the 3297 type which the $(D opAssign) is declared on for it to count for 3298 hasComplexAssignment. 3299 3300 The compiler will generate an $(D opAssign) for a struct when a member 3301 variable of that struct defines an $(D opAssign). It will also generate one 3302 when the struct has a postblit constructor or destructor (and those can be 3303 either user-defined or compiler-generated). 3304 3305 However, due to $(BUGZILLA 24834), the compiler does not currently generate 3306 an $(D opAssign) for structs that define a copy constructor, and so 3307 hasComplexAssignment is $(D false) for such types unless they have an 3308 explicit $(D opAssign), or the compiler generates one due to a member 3309 variable having an $(D opAssign). 3310 3311 Note that hasComplexAssignment is also $(D true) for static arrays whose 3312 element type has an $(D opAssign), since while the static array itself does 3313 not have an $(D opAssign), the compiler must use the $(D opAssign) of the 3314 elements when assigning to the static array. 3315 3316 Due to $(BUGZILLA 24833), enums never have complex assignment even if their 3317 base type does. Their $(D opAssign) is never called, resulting in incorrect 3318 behavior for such enums. So, because the compiler does not treat them as 3319 having complex assignment, hasComplexAssignment is $(D false) for them. 3320 3321 No other types (including class references, pointers, and unions) 3322 ever have an $(D opAssign) and thus hasComplexAssignment is never $(D true) 3323 for them. It is particularly important to note that unions never have an 3324 $(D opAssign), so if a struct contains a union which contains one or more 3325 members which have an $(D opAssign), that struct will have to have a 3326 user-defined $(D opAssign) which explicitly assigns to the correct member 3327 of the union if you don't want the current value of the union to simply be 3328 memcopied when assigning to the struct. 3329 3330 One big reason that code would need to worry about hasComplexAssignment is 3331 if void initialization is used anywhere. While it might be okay to assign 3332 to uninitialized memory for a type where assignment does a memcopy, 3333 assigning to uninitialized memory will cause serious issues with any 3334 $(D opAssign) which looks at the object before assigning to it (e.g. 3335 because the type uses reference counting). In such cases, 3336 $(REF copyEmplace, core, sys, lifetime) needs to be used instead of 3337 assignment. 3338 3339 See_Also: 3340 $(LREF hasComplexCopying) 3341 $(LREF hasComplexDestruction) 3342 $(DDSUBLINK spec/operatoroverloading, assignment, 3343 The language spec for overloading assignment) 3344 $(DDSUBLINK spec/struct, assign-overload, 3345 The language spec for $(D opAssign) on structs) 3346 +/ 3347 template hasComplexAssignment(T) 3348 { 3349 import core.internal.traits : hasElaborateAssign; 3350 alias hasComplexAssignment = hasElaborateAssign!T; 3351 } 3352 3353 /// 3354 @safe unittest 3355 { 3356 static assert(!hasComplexAssignment!int); 3357 static assert(!hasComplexAssignment!real); 3358 static assert(!hasComplexAssignment!string); 3359 static assert(!hasComplexAssignment!(int[])); 3360 static assert(!hasComplexAssignment!(int[42])); 3361 static assert(!hasComplexAssignment!(int[string])); 3362 static assert(!hasComplexAssignment!Object); 3363 3364 static struct NoOpAssign 3365 { 3366 int i; 3367 } 3368 static assert(!hasComplexAssignment!NoOpAssign); 3369 3370 // For complex assignment, the parameter type must match the type of the 3371 // struct (with compatible qualifiers), but refness does not matter (though 3372 // it will obviously affect whether rvalues will be accepted as well as 3373 // whether non-copyable types will be accepted). 3374 static struct HasOpAssign 3375 { 3376 void opAssign(HasOpAssign) {} 3377 } 3378 static assert( hasComplexAssignment!HasOpAssign); 3379 static assert(!hasComplexAssignment!(const(HasOpAssign))); 3380 3381 static struct HasOpAssignRef 3382 { 3383 void opAssign(ref HasOpAssignRef) {} 3384 } 3385 static assert( hasComplexAssignment!HasOpAssignRef); 3386 static assert(!hasComplexAssignment!(const(HasOpAssignRef))); 3387 3388 static struct HasOpAssignAutoRef 3389 { 3390 void opAssign()(auto ref HasOpAssignAutoRef) {} 3391 } 3392 static assert( hasComplexAssignment!HasOpAssignAutoRef); 3393 static assert(!hasComplexAssignment!(const(HasOpAssignAutoRef))); 3394 3395 // Assigning a mutable value works when opAssign takes const, because 3396 // mutable implicitly converts to const, but assigning to a const variable 3397 // does not work, so normally, a const object is not considered to have 3398 // complex assignment. 3399 static struct HasOpAssignC 3400 { 3401 void opAssign(const HasOpAssignC) {} 3402 } 3403 static assert( hasComplexAssignment!HasOpAssignC); 3404 static assert(!hasComplexAssignment!(const(HasOpAssignC))); 3405 3406 // If opAssign is const, then assigning to a const variable will work, and a 3407 // const object will have complex assignment. However, such a type would 3408 // not normally make sense, since it can't actually be mutated by opAssign. 3409 static struct HasConstOpAssignC 3410 { 3411 void opAssign(const HasConstOpAssignC) const {} 3412 } 3413 static assert( hasComplexAssignment!HasConstOpAssignC); 3414 static assert( hasComplexAssignment!(const(HasConstOpAssignC))); 3415 3416 // For a type to have complex assignment, the types must match aside from 3417 // the qualifiers. So, an opAssign which takes another type does not count 3418 // as complex assignment. 3419 static struct OtherOpAssign 3420 { 3421 void opAssign(int) {} 3422 } 3423 static assert(!hasComplexAssignment!OtherOpAssign); 3424 3425 // The return type doesn't matter for complex assignment, though normally, 3426 // opAssign should either return a reference to the this reference (so that 3427 // assignments can be chained) or void. 3428 static struct HasOpAssignWeirdRet 3429 { 3430 int opAssign(HasOpAssignWeirdRet) { return 42; } 3431 } 3432 static assert( hasComplexAssignment!HasOpAssignWeirdRet); 3433 3434 // The compiler will generate an assignment operator if a member variable 3435 // has one. 3436 static struct HasMemberWithOpAssign 3437 { 3438 HasOpAssign s; 3439 } 3440 static assert( hasComplexAssignment!HasMemberWithOpAssign); 3441 3442 // The compiler will generate an assignment operator if the type has a 3443 // postblit constructor or a destructor. 3444 static struct HasDtor 3445 { 3446 ~this() {} 3447 } 3448 static assert( hasComplexAssignment!HasDtor); 3449 3450 // If a struct has @disabled opAssign (and thus assigning to a variable of 3451 // that type will result in a compilation error), then 3452 // hasComplexAssignment is false. 3453 // Code that wants to check whether assignment works will need to test that 3454 // assigning to a variable of that type compiles (which could need to test 3455 // both an lvalue and an rvalue depending on the exact sort of assignment 3456 // the code is actually going to do). 3457 static struct DisabledOpAssign 3458 { 3459 @disable void opAssign(DisabledOpAssign); 3460 } 3461 static assert(!hasComplexAssignment!DisabledOpAssign); 3462 static assert(!__traits(compiles, { DisabledOpAssign s; 3463 s = rvalueOf!DisabledOpAssign; 3464 s = lvalueOf!DisabledOpAssign; })); 3465 static assert(!is(typeof({ DisabledOpAssign s; 3466 s = rvalueOf!DisabledOpAssign; 3467 s = lvalueOf!DisabledOpAssign; }))); 3468 3469 // Static arrays have complex assignment if their elements do. 3470 static assert( hasComplexAssignment!(HasOpAssign[1])); 3471 3472 // Static arrays with no elements do not have complex assignment, because 3473 // there's nothing to assign to. 3474 static assert(!hasComplexAssignment!(HasOpAssign[0])); 3475 3476 // Dynamic arrays do not have complex assignment, because assigning to them 3477 // just slices them rather than assigning to their elements. Assigning to 3478 // an array with a slice operation - e.g. arr[0 .. 5] = other[0 .. 5]; - 3479 // does use opAssign if the elements have it, but since assigning to the 3480 // array itself does not, hasComplexAssignment is false for dynamic arrays. 3481 static assert(!hasComplexAssignment!(HasOpAssign[])); 3482 3483 // Classes and unions do not have complex assignment even if they have 3484 // members which do. 3485 class C 3486 { 3487 HasOpAssign s; 3488 } 3489 static assert(!hasComplexAssignment!C); 3490 3491 union U 3492 { 3493 HasOpAssign s; 3494 } 3495 static assert(!hasComplexAssignment!U); 3496 3497 // https://issues.dlang.org/show_bug.cgi?id=24833 3498 // This static assertion fails, because the compiler 3499 // currently ignores assignment operators for enum types. 3500 enum E : HasOpAssign { a = HasOpAssign.init } 3501 //static assert( hasComplexAssignment!E); 3502 } 3503 3504 @safe unittest 3505 { 3506 import phobos.sys.meta : AliasSeq; 3507 3508 { 3509 struct S1 { int i; } 3510 struct S2 { real r; } 3511 struct S3 { string s; } 3512 struct S4 { int[] arr; } 3513 struct S5 { int[0] arr; } 3514 struct S6 { int[42] arr; } 3515 struct S7 { int[string] aa; } 3516 3517 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 3518 { 3519 static assert(!hasComplexAssignment!T); 3520 static assert(!hasComplexAssignment!(T[0])); 3521 static assert(!hasComplexAssignment!(T[42])); 3522 static assert(!hasComplexAssignment!(T[])); 3523 } 3524 } 3525 3526 // Basic variations of opAssign. 3527 { 3528 static struct S { void opAssign(S) {} } 3529 static assert( hasComplexAssignment!S); 3530 3531 static struct S2 { S s; } 3532 static assert( hasComplexAssignment!S2); 3533 } 3534 { 3535 static struct S { void opAssign(ref S) {} } 3536 static assert( hasComplexAssignment!S); 3537 3538 static struct S2 { S s; } 3539 static assert( hasComplexAssignment!S2); 3540 } 3541 { 3542 static struct S { void opAssign()(auto ref S) {} } 3543 static assert( hasComplexAssignment!S); 3544 3545 static struct S2 { S s; } 3546 static assert( hasComplexAssignment!S2); 3547 } 3548 { 3549 static struct S { ref opAssign(S) { return this; } } 3550 static assert( hasComplexAssignment!S); 3551 3552 static struct S2 { S s; } 3553 static assert( hasComplexAssignment!S2); 3554 } 3555 { 3556 static struct S { ref opAssign(ref S) { return this; } } 3557 static assert( hasComplexAssignment!S); 3558 3559 static struct S2 { S s; } 3560 static assert( hasComplexAssignment!S2); 3561 } 3562 { 3563 static struct S { ref opAssign()(auto ref S) { return this; } } 3564 static assert( hasComplexAssignment!S); 3565 3566 static struct S2 { S s; } 3567 static assert( hasComplexAssignment!S2); 3568 } 3569 { 3570 static struct S { ref opAssign(T)(auto ref T) { return this; } } 3571 static assert( hasComplexAssignment!S); 3572 3573 static struct S2 { S s; } 3574 static assert( hasComplexAssignment!S2); 3575 } 3576 3577 // Non-complex opAssign. 3578 { 3579 static struct S { ref opAssign(int) { return this; } } 3580 static assert(!hasComplexAssignment!S); 3581 3582 static struct S2 { S s; } 3583 static assert(!hasComplexAssignment!S2); 3584 } 3585 { 3586 struct Other {} 3587 static struct S { ref opAssign(Other) { return this; } } 3588 static assert(!hasComplexAssignment!S); 3589 3590 static struct S2 { S s; } 3591 static assert(!hasComplexAssignment!S2); 3592 } 3593 3594 // Multiple opAssigns. 3595 { 3596 static struct S 3597 { 3598 void opAssign(S) {} 3599 void opAssign(int) {} 3600 } 3601 static assert( hasComplexAssignment!S); 3602 3603 static struct S2 { S s; } 3604 static assert( hasComplexAssignment!S2); 3605 } 3606 { 3607 // This just flips the order of the previous test to catch potential 3608 // bugs related to the order of declaration, since that's occasionally 3609 // popped up in the compiler in other contexts. 3610 static struct S 3611 { 3612 void opAssign(int) {} 3613 void opAssign(S) {} 3614 } 3615 static assert( hasComplexAssignment!S); 3616 3617 static struct S2 { S s; } 3618 static assert( hasComplexAssignment!S2); 3619 } 3620 { 3621 static struct S 3622 { 3623 void opAssign(S) {} 3624 void opAssign(ref S) {} 3625 void opAssign(const ref S) {} 3626 } 3627 static assert( hasComplexAssignment!S); 3628 3629 static struct S2 { S s; } 3630 static assert( hasComplexAssignment!S2); 3631 } 3632 3633 // Make sure that @disabled alternate opAssigns don't cause issues. 3634 { 3635 static struct S 3636 { 3637 void opAssign(S) {} 3638 @disable void opAssign(ref S) {} 3639 } 3640 static assert( hasComplexAssignment!S); 3641 3642 // See https://issues.dlang.org/show_bug.cgi?id=24854 3643 // The compiler won't generate any opAssign (even if it theoretically 3644 // can) if the member variable has an @disabled opAssign which counts as 3645 // complex assignment. 3646 static struct S2 { S s; } 3647 static assert(!hasComplexAssignment!S2); 3648 } 3649 { 3650 static struct S 3651 { 3652 void opAssign(T)(T) {} 3653 @disable void opAssign(T)(ref T) {} 3654 } 3655 static assert( hasComplexAssignment!S); 3656 3657 static struct S2 { S s; } 3658 static assert(!hasComplexAssignment!S2); 3659 } 3660 { 3661 static struct S 3662 { 3663 @disable void opAssign(S) {} 3664 void opAssign(ref S) {} 3665 } 3666 static assert( hasComplexAssignment!S); 3667 3668 static struct S2 { S s; } 3669 static assert(!hasComplexAssignment!S2); 3670 } 3671 { 3672 static struct S 3673 { 3674 @disable void opAssign(T)(T) {} 3675 void opAssign(T)(ref T) {} 3676 } 3677 static assert( hasComplexAssignment!S); 3678 3679 static struct S2 { S s; } 3680 static assert(!hasComplexAssignment!S2); 3681 } 3682 { 3683 static struct S 3684 { 3685 void opAssign(S) {} 3686 @disable void opAssign(int) {} 3687 } 3688 static assert( hasComplexAssignment!S); 3689 3690 static struct S2 { S s; } 3691 static assert( hasComplexAssignment!S2); 3692 } 3693 { 3694 // The same as the previous test but in reverse order just to catch 3695 // compiler bugs related to the order of declaration. 3696 static struct S 3697 { 3698 @disable void opAssign(int) {} 3699 void opAssign(S) {} 3700 } 3701 static assert( hasComplexAssignment!S); 3702 3703 static struct S2 { S s; } 3704 static assert( hasComplexAssignment!S2); 3705 } 3706 3707 // Generated opAssign due to other functions. 3708 { 3709 static struct S { this(this) {} } 3710 static assert( hasComplexAssignment!S); 3711 3712 static struct S2 { S s; } 3713 static assert( hasComplexAssignment!S2); 3714 } 3715 // https://issues.dlang.org/show_bug.cgi?id=24834 3716 /+ 3717 { 3718 static struct S { this(ref S) {} } 3719 static assert( hasComplexAssignment!S); 3720 3721 static struct S2 { S s; } 3722 static assert( hasComplexAssignment!S2); 3723 } 3724 +/ 3725 { 3726 static struct S { ~this() {} } 3727 static assert( hasComplexAssignment!S); 3728 3729 static struct S2 { S s; } 3730 static assert( hasComplexAssignment!S2); 3731 } 3732 3733 { 3734 static struct S 3735 { 3736 this(this) {} 3737 @disable void opAssign()(auto ref S) {} 3738 } 3739 static assert(!hasComplexAssignment!S); 3740 3741 static struct S2 { S s; } 3742 static assert(!hasComplexAssignment!S2); 3743 } 3744 { 3745 static struct S 3746 { 3747 this(this) {} 3748 void opAssign()(auto ref S) {} 3749 @disable void opAssign(int) {} 3750 } 3751 static assert( hasComplexAssignment!S); 3752 3753 static struct S2 { S s; } 3754 static assert( hasComplexAssignment!S2); 3755 } 3756 3757 // Static arrays 3758 { 3759 static struct S { void opAssign(S) {} } 3760 static assert( hasComplexAssignment!S); 3761 3762 static assert(!hasComplexAssignment!(S[0])); 3763 static assert( hasComplexAssignment!(S[12])); 3764 static assert(!hasComplexAssignment!(S[])); 3765 3766 static struct S2 { S[42] s; } 3767 static assert( hasComplexAssignment!S2); 3768 } 3769 } 3770 3771 /++ 3772 Whether copying an object of the given type involves either a user-defined 3773 copy / postblit constructor or a compiler-generated copy / postblit 3774 constructor rather than using the default copying behavior (which would use 3775 $(D memcpy)). 3776 3777 The compiler will generate a copy / postblit constructor for a struct when 3778 a member variable of that struct defines a copy / postblit constructor. 3779 3780 Note that hasComplexCopying is also $(D true) for static arrays whose 3781 element type has a copy constructor or postblit constructor, since while 3782 the static array itself does not have a copy constructor or postblit 3783 constructor, the compiler must use the copy / postblit constructor of the 3784 elements when copying the static array. 3785 3786 Due to $(BUGZILLA 24833), enums never have complex copying even if their 3787 base type does. Their copy / postblit constructor is never called, 3788 resulting in incorrect behavior for such enums. So, because the compiler 3789 does not treat them as having complex copying, hasComplexCopying is 3790 $(D false) for them. 3791 3792 No other types (including class references, pointers, and unions) ever have 3793 a copy constructor or postblit constructor and thus hasComplexCopying is 3794 never $(D true) for them. It is particularly important to note that unions 3795 never have a copy constructor or postblit constructor, so if a struct 3796 contains a union which contains one or more members which have a copy 3797 constructor or postblit constructor, that struct will have to have a 3798 user-defined copy constructor or posthblit constructor which explicitly 3799 copies the correct member of the union if you don't want the current value 3800 of the union to simply be memcopied when copying the struct. 3801 3802 If a particular piece of code cares about the existence of a copy 3803 constructor or postblit constructor specifically rather than if a type has 3804 one or the other, the traits 3805 $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T))) 3806 and 3807 $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) can 3808 be used, though note that they will not be true for static arrays. 3809 3810 See_Also: 3811 $(LREF hasComplexAssignment) 3812 $(LREF hasComplexDestruction) 3813 $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T))) 3814 $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) 3815 $(DDSUBLINK spec/traits, isCopyable, $(D __traits(isCopyable, T))) 3816 $(DDSUBLINK spec/structs, struct-copy-constructor, The language spec for copy constructors) 3817 $(DDSUBLINK spec/structs, struct-postblit, The language spec for postblit constructors) 3818 +/ 3819 template hasComplexCopying(T) 3820 { 3821 import core.internal.traits : hasElaborateCopyConstructor; 3822 alias hasComplexCopying = hasElaborateCopyConstructor!T; 3823 } 3824 3825 /// 3826 @safe unittest 3827 { 3828 static assert(!hasComplexCopying!int); 3829 static assert(!hasComplexCopying!real); 3830 static assert(!hasComplexCopying!string); 3831 static assert(!hasComplexCopying!(int[])); 3832 static assert(!hasComplexCopying!(int[42])); 3833 static assert(!hasComplexCopying!(int[string])); 3834 static assert(!hasComplexCopying!Object); 3835 3836 static struct NoCopyCtor1 3837 { 3838 int i; 3839 } 3840 static assert(!hasComplexCopying!NoCopyCtor1); 3841 static assert(!__traits(hasCopyConstructor, NoCopyCtor1)); 3842 static assert(!__traits(hasPostblit, NoCopyCtor1)); 3843 3844 static struct NoCopyCtor2 3845 { 3846 int i; 3847 3848 this(int i) 3849 { 3850 this.i = i; 3851 } 3852 } 3853 static assert(!hasComplexCopying!NoCopyCtor2); 3854 static assert(!__traits(hasCopyConstructor, NoCopyCtor2)); 3855 static assert(!__traits(hasPostblit, NoCopyCtor2)); 3856 3857 struct HasCopyCtor 3858 { 3859 this(ref HasCopyCtor) 3860 { 3861 } 3862 } 3863 static assert( hasComplexCopying!HasCopyCtor); 3864 static assert( __traits(hasCopyConstructor, HasCopyCtor)); 3865 static assert(!__traits(hasPostblit, HasCopyCtor)); 3866 3867 // hasComplexCopying does not take constness into account. 3868 // Code that wants to check whether copying works will need to test 3869 // __traits(isCopyable, T) or test that copying compiles. 3870 static assert( hasComplexCopying!(const HasCopyCtor)); 3871 static assert( __traits(hasCopyConstructor, const HasCopyCtor)); 3872 static assert(!__traits(hasPostblit, const HasCopyCtor)); 3873 static assert(!__traits(isCopyable, const HasCopyCtor)); 3874 static assert(!__traits(compiles, { const HasCopyCtor h; 3875 auto h2 = h; })); 3876 static assert(!is(typeof({ const HasCopyCtor h1; 3877 auto h2 = h1; }))); 3878 3879 // An rvalue constructor is not a copy constructor. 3880 struct HasRValueCtor 3881 { 3882 this(HasRValueCtor) 3883 { 3884 } 3885 } 3886 static assert(!hasComplexCopying!HasRValueCtor); 3887 static assert(!__traits(hasCopyConstructor, HasRValueCtor)); 3888 static assert(!__traits(hasPostblit, HasRValueCtor)); 3889 3890 struct HasPostblit 3891 { 3892 this(this) 3893 { 3894 } 3895 } 3896 static assert( hasComplexCopying!HasPostblit); 3897 static assert(!__traits(hasCopyConstructor, HasPostblit)); 3898 static assert( __traits(hasPostblit, HasPostblit)); 3899 3900 // The compiler will generate a copy constructor if a member variable 3901 // has one. 3902 static struct HasMemberWithCopyCtor 3903 { 3904 HasCopyCtor s; 3905 } 3906 static assert( hasComplexCopying!HasMemberWithCopyCtor); 3907 3908 // The compiler will generate a postblit constructor if a member variable 3909 // has one. 3910 static struct HasMemberWithPostblit 3911 { 3912 HasPostblit s; 3913 } 3914 static assert( hasComplexCopying!HasMemberWithPostblit); 3915 3916 // If a struct has @disabled copying, hasComplexCopying is still true. 3917 // Code that wants to check whether copying works will need to test 3918 // __traits(isCopyable, T) or test that copying compiles. 3919 static struct DisabledCopying 3920 { 3921 @disable this(this); 3922 @disable this(ref DisabledCopying); 3923 } 3924 static assert( hasComplexCopying!DisabledCopying); 3925 static assert(!__traits(isCopyable, DisabledCopying)); 3926 static assert(!__traits(compiles, { DisabledCopying dc1; 3927 auto dc2 = dc1; })); 3928 static assert(!is(typeof({ DisabledCopying dc1; 3929 auto dc2 = dc1; }))); 3930 3931 // Static arrays have complex copying if their elements do. 3932 static assert( hasComplexCopying!(HasCopyCtor[1])); 3933 static assert( hasComplexCopying!(HasPostblit[1])); 3934 3935 // Static arrays with no elements do not have complex copying, because 3936 // there's nothing to copy. 3937 static assert(!hasComplexCopying!(HasCopyCtor[0])); 3938 static assert(!hasComplexCopying!(HasPostblit[0])); 3939 3940 // Dynamic arrays do not have complex copying, because copying them 3941 // just slices them rather than copying their elements. 3942 static assert(!hasComplexCopying!(HasCopyCtor[])); 3943 static assert(!hasComplexCopying!(HasPostblit[])); 3944 3945 // Classes and unions do not have complex copying even if they have 3946 // members which do. 3947 class C 3948 { 3949 HasCopyCtor s; 3950 } 3951 static assert(!hasComplexCopying!C); 3952 3953 union U 3954 { 3955 HasCopyCtor s; 3956 } 3957 static assert(!hasComplexCopying!U); 3958 3959 // https://issues.dlang.org/show_bug.cgi?id=24833 3960 // This static assertion fails, because the compiler 3961 // currently ignores assignment operators for enum types. 3962 enum E : HasCopyCtor { a = HasCopyCtor.init } 3963 //static assert( hasComplexCopying!E); 3964 } 3965 3966 @safe unittest 3967 { 3968 import phobos.sys.meta : AliasSeq; 3969 3970 { 3971 struct S1 { int i; } 3972 struct S2 { real r; } 3973 struct S3 { string s; } 3974 struct S4 { int[] arr; } 3975 struct S5 { int[0] arr; } 3976 struct S6 { int[42] arr; } 3977 struct S7 { int[string] aa; } 3978 3979 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 3980 { 3981 static assert(!hasComplexCopying!T); 3982 static assert(!hasComplexCopying!(T[0])); 3983 static assert(!hasComplexCopying!(T[42])); 3984 static assert(!hasComplexCopying!(T[])); 3985 } 3986 } 3987 3988 // Basic variations of copy constructors. 3989 { 3990 static struct S { this(ref S) {} } 3991 static assert( hasComplexCopying!S); 3992 3993 static struct S2 { S s; } 3994 static assert( hasComplexCopying!S2); 3995 } 3996 { 3997 static struct S { this(const ref S) const {} } 3998 static assert( hasComplexCopying!S); 3999 4000 static struct S2 { S s; } 4001 static assert( hasComplexCopying!S2); 4002 } 4003 { 4004 static struct S 4005 { 4006 this(ref S) {} 4007 this(const ref S) const {} 4008 } 4009 static assert( hasComplexCopying!S); 4010 4011 static struct S2 { S s; } 4012 static assert( hasComplexCopying!S2); 4013 } 4014 { 4015 static struct S { this(inout ref S) inout {} } 4016 static assert( hasComplexCopying!S); 4017 4018 static struct S2 { S s; } 4019 static assert( hasComplexCopying!S2); 4020 } 4021 { 4022 static struct S { this(scope ref S) {} } 4023 static assert( hasComplexCopying!S); 4024 4025 static struct S2 { S s; } 4026 static assert( hasComplexCopying!S2); 4027 } 4028 { 4029 static struct S { this(scope ref S) scope {} } 4030 static assert( hasComplexCopying!S); 4031 4032 static struct S2 { S s; } 4033 static assert( hasComplexCopying!S2); 4034 } 4035 { 4036 static struct S { this(ref S) @safe {} } 4037 static assert( hasComplexCopying!S); 4038 4039 static struct S2 { S s; } 4040 static assert( hasComplexCopying!S2); 4041 } 4042 { 4043 static struct S { this(ref S) nothrow {} } 4044 static assert( hasComplexCopying!S); 4045 4046 static struct S2 { S s; } 4047 static assert( hasComplexCopying!S2); 4048 } 4049 { 4050 static struct S { this(scope inout ref S) inout scope @safe pure nothrow @nogc {} } 4051 static assert( hasComplexCopying!S); 4052 4053 static struct S2 { S s; } 4054 static assert( hasComplexCopying!S2); 4055 } 4056 4057 // Basic variations of postblit constructors. 4058 { 4059 static struct S { this(this) {} } 4060 static assert( hasComplexCopying!S); 4061 4062 static struct S2 { S s; } 4063 static assert( hasComplexCopying!S2); 4064 } 4065 { 4066 static struct S { this(this) scope @safe pure nothrow @nogc {} } 4067 static assert( hasComplexCopying!S); 4068 4069 static struct S2 { S s; } 4070 static assert( hasComplexCopying!S2); 4071 } 4072 4073 // Rvalue constructors. 4074 { 4075 static struct S { this(S) {} } 4076 static assert(!hasComplexCopying!S); 4077 4078 static struct S2 { S s; } 4079 static assert(!hasComplexCopying!S2); 4080 } 4081 { 4082 static struct S { this(const S) const {} } 4083 static assert(!hasComplexCopying!S); 4084 4085 static struct S2 { S s; } 4086 static assert(!hasComplexCopying!S2); 4087 } 4088 { 4089 static struct S 4090 { 4091 this(S) {} 4092 this(const S) const {} 4093 } 4094 static assert(!hasComplexCopying!S); 4095 4096 static struct S2 { S s; } 4097 static assert(!hasComplexCopying!S2); 4098 } 4099 { 4100 static struct S { this(inout S) inout {} } 4101 static assert(!hasComplexCopying!S); 4102 4103 static struct S2 { S s; } 4104 static assert(!hasComplexCopying!S2); 4105 } 4106 { 4107 static struct S { this(S) @safe {} } 4108 static assert(!hasComplexCopying!S); 4109 4110 static struct S2 { S s; } 4111 static assert(!hasComplexCopying!S2); 4112 } 4113 { 4114 static struct S { this(S) nothrow {} } 4115 static assert(!hasComplexCopying!S); 4116 4117 static struct S2 { S s; } 4118 static assert(!hasComplexCopying!S2); 4119 } 4120 { 4121 static struct S { this(inout S) inout @safe pure nothrow @nogc {} } 4122 static assert(!hasComplexCopying!S); 4123 4124 static struct S2 { S s; } 4125 static assert(!hasComplexCopying!S2); 4126 } 4127 4128 // @disabled copy constructors. 4129 { 4130 static struct S { @disable this(ref S) {} } 4131 static assert( hasComplexCopying!S); 4132 4133 static struct S2 { S s; } 4134 static assert( hasComplexCopying!S2); 4135 } 4136 { 4137 static struct S { @disable this(const ref S) const {} } 4138 static assert( hasComplexCopying!S); 4139 4140 static struct S2 { S s; } 4141 static assert( hasComplexCopying!S2); 4142 } 4143 { 4144 static struct S 4145 { 4146 @disable this(ref S) {} 4147 this(const ref S) const {} 4148 } 4149 static assert( hasComplexCopying!S); 4150 4151 static struct S2 { S s; } 4152 static assert( hasComplexCopying!S2); 4153 } 4154 { 4155 static struct S 4156 { 4157 this(ref S) {} 4158 @disable this(const ref S) const {} 4159 } 4160 static assert( hasComplexCopying!S); 4161 4162 static struct S2 { S s; } 4163 static assert( hasComplexCopying!S2); 4164 } 4165 { 4166 static struct S 4167 { 4168 @disable this(ref S) {} 4169 @disable this(const ref S) const {} 4170 } 4171 static assert( hasComplexCopying!S); 4172 4173 static struct S2 { S s; } 4174 static assert( hasComplexCopying!S2); 4175 } 4176 4177 // Static arrays 4178 { 4179 static struct S { this(ref S) {} } 4180 static assert( hasComplexCopying!S); 4181 4182 static assert(!hasComplexCopying!(S[0])); 4183 static assert( hasComplexCopying!(S[12])); 4184 static assert(!hasComplexCopying!(S[])); 4185 4186 static struct S2 { S[42] s; } 4187 static assert( hasComplexCopying!S2); 4188 } 4189 { 4190 static struct S { this(this) {} } 4191 static assert( hasComplexCopying!S); 4192 4193 static assert(!hasComplexCopying!(S[0])); 4194 static assert( hasComplexCopying!(S[12])); 4195 static assert(!hasComplexCopying!(S[])); 4196 4197 static struct S2 { S[42] s; } 4198 static assert( hasComplexCopying!S2); 4199 } 4200 } 4201 4202 /++ 4203 Whether the given type has either a user-defined destructor or a 4204 compiler-generated destructor. 4205 4206 The compiler will generate a destructor for a struct when a member variable 4207 of that struct defines a destructor. 4208 4209 Note that hasComplexDestruction is also $(D true) for static arrays whose 4210 element type has a destructor, since while the static array itself does not 4211 have a destructor, the compiler must use the destructor of the elements 4212 when destroying the static array. 4213 4214 Due to $(BUGZILLA 24833), enums never have complex destruction even if their 4215 base type does. Their destructor is never called, resulting in incorrect 4216 behavior for such enums. So, because the compiler does not treat them as 4217 having complex destruction, hasComplexDestruction is $(D false) for them. 4218 4219 Note that while the $(DDSUBLINK spec/class, destructors, language spec) 4220 currently refers to $(D ~this()) on classes as destructors (whereas the 4221 runtime refers to them as finalizers, and they're arguably finalizers 4222 rather than destructors given how they work), classes are not considered to 4223 have complex destruction. Under normal circumstances, it's just the GC or 4224 $(REF1 destroy, object) which calls the destructor / finalizer on a class 4225 (and it's not guaranteed that a class destructor / finalizer will even ever 4226 be called), which is in stark contrast to structs, which normally live on 4227 the stack and need to be destroyed when they leave scope. So, 4228 hasComplexDestruction is concerned with whether that type will have a 4229 destructor that's run when it leaves scope and not with what happens when 4230 the GC destroys an object prior to freeing its memory. 4231 4232 No other types (including pointers and unions) ever have a destructor and 4233 thus hasComplexDestruction is never $(D true) for them. It is particularly 4234 important to note that unions never have a destructor, so if a struct 4235 contains a union which contains one or more members which have a 4236 destructor, that struct will have to have a user-defined destructor which 4237 explicitly calls $(REF1 destroy, object) on the correct member of the 4238 union if you want the object in question to be destroyed properly. 4239 4240 See_Also: 4241 $(LREF hasComplexAssignment) 4242 $(LREF hasComplexCopying) 4243 $(REF destroy, object) 4244 $(DDSUBLINK spec/structs, struct-destructor, The language spec for destructors) 4245 $(DDSUBLINK spec/class, destructors, The language spec for class finalizers) 4246 +/ 4247 template hasComplexDestruction(T) 4248 { 4249 import core.internal.traits : hasElaborateDestructor; 4250 alias hasComplexDestruction = hasElaborateDestructor!T; 4251 } 4252 4253 /// 4254 @safe unittest 4255 { 4256 static assert(!hasComplexDestruction!int); 4257 static assert(!hasComplexDestruction!real); 4258 static assert(!hasComplexDestruction!string); 4259 static assert(!hasComplexDestruction!(int[])); 4260 static assert(!hasComplexDestruction!(int[42])); 4261 static assert(!hasComplexDestruction!(int[string])); 4262 static assert(!hasComplexDestruction!Object); 4263 4264 static struct NoDtor 4265 { 4266 int i; 4267 } 4268 static assert(!hasComplexDestruction!NoDtor); 4269 4270 struct HasDtor 4271 { 4272 ~this() {} 4273 } 4274 static assert( hasComplexDestruction!HasDtor); 4275 4276 // The compiler will generate a destructor if a member variable has one. 4277 static struct HasMemberWithDtor 4278 { 4279 HasDtor s; 4280 } 4281 static assert( hasComplexDestruction!HasMemberWithDtor); 4282 4283 // If a struct has @disabled destruction, hasComplexDestruction is still 4284 // true. Code that wants to check whether destruction works can either 4285 // test for whether the __xdtor member is disabled, or it can test whether 4286 // code that will destroy the object compiles. That being said, a disabled 4287 // destructor probably isn't very common in practice, because about all that 4288 // such a type is good for is being allocated on the heap. 4289 static struct DisabledDtor 4290 { 4291 @disable ~this() {} 4292 } 4293 static assert( hasComplexDestruction!DisabledDtor); 4294 static assert( __traits(isDisabled, 4295 __traits(getMember, DisabledDtor, "__xdtor"))); 4296 4297 // A type with a disabled destructor cannot be created on the stack or used 4298 // in any way that would ever trigger a destructor, making it pretty much 4299 // useless outside of providing a way to force a struct to be allocated on 4300 // the heap - though that could be useful in some situations, since it 4301 // it makes it possible to have a type that has to be a reference type but 4302 // which doesn't have the overhead of a class. 4303 static assert(!__traits(compiles, { DisabledDtor d; })); 4304 static assert( __traits(compiles, { auto d = new DisabledDtor; })); 4305 4306 // Static arrays have complex destruction if their elements do. 4307 static assert( hasComplexDestruction!(HasDtor[1])); 4308 4309 // Static arrays with no elements do not have complex destruction, because 4310 // there's nothing to destroy. 4311 static assert(!hasComplexDestruction!(HasDtor[0])); 4312 4313 // Dynamic arrays do not have complex destruction, because their elements 4314 // are contained in the memory that the dynamic array is a slice of and not 4315 // in the dynamic array itself, so there's nothing to destroy when a 4316 // dynamic array leaves scope. 4317 static assert(!hasComplexDestruction!(HasDtor[])); 4318 4319 // Classes and unions do not have complex copying even if they have 4320 // members which do. 4321 class C 4322 { 4323 HasDtor s; 4324 } 4325 static assert(!hasComplexDestruction!C); 4326 4327 union U 4328 { 4329 HasDtor s; 4330 } 4331 static assert(!hasComplexDestruction!U); 4332 4333 // https://issues.dlang.org/show_bug.cgi?id=24833 4334 // This static assertion fails, because the compiler 4335 // currently ignores assignment operators for enum types. 4336 enum E : HasDtor { a = HasDtor.init } 4337 //static assert( hasComplexDestruction!E); 4338 } 4339 4340 @safe unittest 4341 { 4342 import phobos.sys.meta : AliasSeq; 4343 4344 { 4345 struct S1 { int i; } 4346 struct S2 { real r; } 4347 struct S3 { string s; } 4348 struct S4 { int[] arr; } 4349 struct S5 { int[0] arr; } 4350 struct S6 { int[42] arr; } 4351 struct S7 { int[string] aa; } 4352 4353 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 4354 { 4355 static assert(!hasComplexDestruction!T); 4356 static assert(!hasComplexDestruction!(T[0])); 4357 static assert(!hasComplexDestruction!(T[42])); 4358 static assert(!hasComplexDestruction!(T[])); 4359 } 4360 } 4361 4362 // Basic variations of destructors. 4363 { 4364 static struct S { ~this() {} } 4365 static assert( hasComplexDestruction!S); 4366 4367 static struct S2 { S s; } 4368 static assert( hasComplexDestruction!S2); 4369 } 4370 { 4371 static struct S { ~this() const {} } 4372 static assert( hasComplexDestruction!S); 4373 4374 static struct S2 { S s; } 4375 static assert( hasComplexDestruction!S2); 4376 } 4377 { 4378 static struct S { ~this() @safe {} } 4379 static assert( hasComplexDestruction!S); 4380 4381 static struct S2 { S s; } 4382 static assert( hasComplexDestruction!S2); 4383 } 4384 { 4385 static struct S { ~this() @safe pure nothrow @nogc {} } 4386 static assert( hasComplexDestruction!S); 4387 4388 static struct S2 { S s; } 4389 static assert( hasComplexDestruction!S2); 4390 } 4391 4392 // @disabled destructors. 4393 { 4394 static struct S { @disable ~this() {} } 4395 static assert( __traits(isDisabled, 4396 __traits(getMember, S, "__xdtor"))); 4397 4398 static struct S2 { S s; } 4399 static assert( hasComplexDestruction!S2); 4400 static assert( __traits(isDisabled, 4401 __traits(getMember, S2, "__xdtor"))); 4402 } 4403 4404 // Static arrays 4405 { 4406 static struct S { ~this() {} } 4407 static assert( hasComplexDestruction!S); 4408 4409 static assert(!hasComplexDestruction!(S[0])); 4410 static assert( hasComplexDestruction!(S[12])); 4411 static assert(!hasComplexDestruction!(S[])); 4412 4413 static struct S2 { S[42] s; } 4414 static assert( hasComplexDestruction!S2); 4415 } 4416 } 4417 4418 /++ 4419 Evaluates to $(D true) if the given type is one or more of the following, 4420 or if it's a struct, union, or static array which contains one or more of 4421 the following: 4422 4423 $(OL $(LI A raw pointer) 4424 $(LI A class reference) 4425 $(LI An interface reference) 4426 $(LI A dynamic array) 4427 $(LI An associative array) 4428 $(LI A delegate) 4429 $(LI A struct with a 4430 $(DDSUBLINK spec/traits, isNested, $(D context pointer)).)) 4431 4432 Note that function pointers are not considered to have indirections, because 4433 they do not point to any data (whereas a delegate has a context pointer 4434 and therefore has data that it points to). 4435 4436 Also, while static arrays do not have indirections unless their element 4437 type has indirections, static arrays with an element type of $(D void) are 4438 considered to have indirections by hasIndirections, because it's unknown 4439 what type their elements actually are, so they $(I might) have 4440 indirections, and thus, the conservative approach is to assume that they do 4441 have indirections. 4442 4443 Static arrays with length 0 do not have indirections no matter what their 4444 element type is, since they don't actually have any elements. 4445 +/ 4446 version (StdDdoc) template hasIndirections(T) 4447 { 4448 import core.internal.traits : _hasIndirections = hasIndirections; 4449 alias hasIndirections = _hasIndirections!T; 4450 } 4451 else 4452 { 4453 import core.internal.traits : _hasIndirections = hasIndirections; 4454 alias hasIndirections = _hasIndirections; 4455 } 4456 4457 /// 4458 @safe unittest 4459 { 4460 static class C {} 4461 static interface I {} 4462 4463 static assert( hasIndirections!(int*)); 4464 static assert( hasIndirections!C); 4465 static assert( hasIndirections!I); 4466 static assert( hasIndirections!(int[])); 4467 static assert( hasIndirections!(int[string])); 4468 static assert( hasIndirections!(void delegate())); 4469 static assert( hasIndirections!(string delegate(int))); 4470 4471 static assert(!hasIndirections!(void function())); 4472 static assert(!hasIndirections!int); 4473 4474 static assert(!hasIndirections!(ubyte[9])); 4475 static assert( hasIndirections!(ubyte[9]*)); 4476 static assert( hasIndirections!(ubyte*[9])); 4477 static assert(!hasIndirections!(ubyte*[0])); 4478 static assert( hasIndirections!(ubyte[])); 4479 4480 static assert( hasIndirections!(void[])); 4481 static assert( hasIndirections!(void[42])); 4482 4483 static struct NoContext 4484 { 4485 int i; 4486 } 4487 4488 int local; 4489 4490 struct HasContext 4491 { 4492 int foo() { return local; } 4493 } 4494 4495 struct HasMembersWithIndirections 4496 { 4497 int* ptr; 4498 } 4499 4500 static assert(!hasIndirections!NoContext); 4501 static assert( hasIndirections!HasContext); 4502 static assert( hasIndirections!HasMembersWithIndirections); 4503 4504 union U1 4505 { 4506 int i; 4507 float f; 4508 } 4509 static assert(!hasIndirections!U1); 4510 4511 union U2 4512 { 4513 int i; 4514 int[] arr; 4515 } 4516 static assert( hasIndirections!U2); 4517 } 4518 4519 // hasIndirections with types which aren't aggregate types. 4520 @safe unittest 4521 { 4522 import phobos.sys.meta : AliasSeq; 4523 4524 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 4525 4526 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 4527 float, double, real, char, wchar, dchar, int function(string), void)) 4528 { 4529 mixin testWithQualifiers!(T, false); 4530 mixin testWithQualifiers!(T*, true); 4531 mixin testWithQualifiers!(T[], true); 4532 4533 mixin testWithQualifiers!(T[42], is(T == void)); 4534 mixin testWithQualifiers!(T[0], false); 4535 4536 mixin testWithQualifiers!(T*[42], true); 4537 mixin testWithQualifiers!(T*[0], false); 4538 4539 mixin testWithQualifiers!(T[][42], true); 4540 mixin testWithQualifiers!(T[][0], false); 4541 } 4542 4543 foreach (T; AliasSeq!(int[int], int delegate(string))) 4544 { 4545 mixin testWithQualifiers!(T, true); 4546 mixin testWithQualifiers!(T*, true); 4547 mixin testWithQualifiers!(T[], true); 4548 4549 mixin testWithQualifiers!(T[42], true); 4550 mixin testWithQualifiers!(T[0], false); 4551 4552 mixin testWithQualifiers!(T*[42], true); 4553 mixin testWithQualifiers!(T*[0], false); 4554 4555 mixin testWithQualifiers!(T[][42], true); 4556 mixin testWithQualifiers!(T[][0], false); 4557 } 4558 } 4559 4560 // hasIndirections with structs. 4561 @safe unittest 4562 { 4563 import phobos.sys.meta : AliasSeq; 4564 4565 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 4566 4567 { 4568 struct S {} 4569 mixin testWithQualifiers!(S, false); 4570 } 4571 { 4572 static struct S {} 4573 mixin testWithQualifiers!(S, false); 4574 } 4575 { 4576 struct S { void foo() {} } 4577 mixin testWithQualifiers!(S, true); 4578 } 4579 { 4580 static struct S { void foo() {} } 4581 mixin testWithQualifiers!(S, false); 4582 } 4583 4584 // Structs with members which aren't aggregate types and don't have indirections. 4585 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 4586 float, double, real, char, wchar, dchar, int function(string))) 4587 { 4588 // No indirections. 4589 { 4590 struct S { T member; } 4591 mixin testWithQualifiers!(S, false); 4592 } 4593 { 4594 struct S { const T member; } 4595 mixin testWithQualifiers!(S, false); 4596 } 4597 { 4598 struct S { immutable T member; } 4599 mixin testWithQualifiers!(S, false); 4600 } 4601 { 4602 struct S { shared T member; } 4603 mixin testWithQualifiers!(S, false); 4604 } 4605 4606 { 4607 static struct S { T member; void foo() {} } 4608 mixin testWithQualifiers!(S, false); 4609 } 4610 { 4611 static struct S { const T member; void foo() {} } 4612 mixin testWithQualifiers!(S, false); 4613 } 4614 { 4615 static struct S { immutable T member; void foo() {} } 4616 mixin testWithQualifiers!(S, false); 4617 } 4618 { 4619 static struct S { shared T member; void foo() {} } 4620 mixin testWithQualifiers!(S, false); 4621 } 4622 4623 // Has context pointer. 4624 { 4625 struct S { T member; void foo() {} } 4626 mixin testWithQualifiers!(S, true); 4627 } 4628 { 4629 struct S { const T member; void foo() {} } 4630 mixin testWithQualifiers!(S, true); 4631 } 4632 { 4633 struct S { immutable T member; void foo() {} } 4634 mixin testWithQualifiers!(S, true); 4635 } 4636 { 4637 struct S { shared T member; void foo() {} } 4638 mixin testWithQualifiers!(S, true); 4639 } 4640 4641 { 4642 T local; 4643 struct S { void foo() { auto v = local; } } 4644 mixin testWithQualifiers!(S, true); 4645 } 4646 { 4647 const T local; 4648 struct S { void foo() { auto v = local; } } 4649 mixin testWithQualifiers!(S, true); 4650 } 4651 { 4652 immutable T local; 4653 struct S { void foo() { auto v = local; } } 4654 mixin testWithQualifiers!(S, true); 4655 } 4656 { 4657 shared T local; 4658 struct S { void foo() @trusted { auto v = cast() local; } } 4659 mixin testWithQualifiers!(S, true); 4660 } 4661 4662 // Pointers. 4663 { 4664 struct S { T* member; } 4665 mixin testWithQualifiers!(S, true); 4666 } 4667 { 4668 struct S { const(T)* member; } 4669 mixin testWithQualifiers!(S, true); 4670 } 4671 { 4672 struct S { const T* member; } 4673 mixin testWithQualifiers!(S, true); 4674 } 4675 { 4676 struct S { immutable T* member; } 4677 mixin testWithQualifiers!(S, true); 4678 } 4679 { 4680 struct S { shared T* member; } 4681 mixin testWithQualifiers!(S, true); 4682 } 4683 4684 // Dynamic arrays. 4685 { 4686 struct S { T[] member; } 4687 mixin testWithQualifiers!(S, true); 4688 } 4689 { 4690 struct S { const(T)[] member; } 4691 mixin testWithQualifiers!(S, true); 4692 } 4693 { 4694 struct S { const T[] member; } 4695 mixin testWithQualifiers!(S, true); 4696 } 4697 { 4698 struct S { immutable T[] member; } 4699 mixin testWithQualifiers!(S, true); 4700 } 4701 { 4702 struct S { shared T[] member; } 4703 mixin testWithQualifiers!(S, true); 4704 } 4705 4706 // Static arrays. 4707 { 4708 struct S { T[1] member; } 4709 mixin testWithQualifiers!(S, false); 4710 } 4711 { 4712 struct S { const(T)[1] member; } 4713 mixin testWithQualifiers!(S, false); 4714 } 4715 { 4716 struct S { const T[1] member; } 4717 mixin testWithQualifiers!(S, false); 4718 } 4719 { 4720 struct S { immutable T[1] member; } 4721 mixin testWithQualifiers!(S, false); 4722 } 4723 { 4724 struct S { shared T[1] member; } 4725 mixin testWithQualifiers!(S, false); 4726 } 4727 4728 // Static arrays of pointers. 4729 { 4730 struct S { T*[1] member; } 4731 mixin testWithQualifiers!(S, true); 4732 } 4733 { 4734 struct S { const(T)*[1] member; } 4735 mixin testWithQualifiers!(S, true); 4736 } 4737 { 4738 struct S { const(T*)[1] member; } 4739 mixin testWithQualifiers!(S, true); 4740 } 4741 { 4742 struct S { const T*[1] member; } 4743 mixin testWithQualifiers!(S, true); 4744 } 4745 { 4746 struct S { immutable T*[1] member; } 4747 mixin testWithQualifiers!(S, true); 4748 } 4749 { 4750 struct S { shared T*[1] member; } 4751 mixin testWithQualifiers!(S, true); 4752 } 4753 4754 { 4755 struct S { T*[0] member; } 4756 mixin testWithQualifiers!(S, false); 4757 } 4758 { 4759 struct S { const(T)*[0] member; } 4760 mixin testWithQualifiers!(S, false); 4761 } 4762 { 4763 struct S { const(T*)[0] member; } 4764 mixin testWithQualifiers!(S, false); 4765 } 4766 { 4767 struct S { const T*[0] member; } 4768 mixin testWithQualifiers!(S, false); 4769 } 4770 { 4771 struct S { immutable T*[0] member; } 4772 mixin testWithQualifiers!(S, false); 4773 } 4774 { 4775 struct S { shared T*[0] member; } 4776 mixin testWithQualifiers!(S, false); 4777 } 4778 4779 // Static arrays of dynamic arrays. 4780 { 4781 struct S { T[][1] member; } 4782 mixin testWithQualifiers!(S, true); 4783 } 4784 { 4785 struct S { const(T)[][1] member; } 4786 mixin testWithQualifiers!(S, true); 4787 } 4788 { 4789 struct S { const(T[])[1] member; } 4790 mixin testWithQualifiers!(S, true); 4791 } 4792 { 4793 struct S { const T[][1] member; } 4794 mixin testWithQualifiers!(S, true); 4795 } 4796 { 4797 struct S { immutable T[][1] member; } 4798 mixin testWithQualifiers!(S, true); 4799 } 4800 { 4801 struct S { shared T[][1] member; } 4802 mixin testWithQualifiers!(S, true); 4803 } 4804 4805 { 4806 struct S { T[][0] member; } 4807 mixin testWithQualifiers!(S, false); 4808 } 4809 { 4810 struct S { const(T)[][0] member; } 4811 mixin testWithQualifiers!(S, false); 4812 } 4813 { 4814 struct S { const(T[])[0] member; } 4815 mixin testWithQualifiers!(S, false); 4816 } 4817 { 4818 struct S { const T[][0] member; } 4819 mixin testWithQualifiers!(S, false); 4820 } 4821 { 4822 struct S { immutable T[][0] member; } 4823 mixin testWithQualifiers!(S, false); 4824 } 4825 { 4826 struct S { shared T[][0] member; } 4827 mixin testWithQualifiers!(S, false); 4828 } 4829 } 4830 4831 // Structs with arrays of void. 4832 { 4833 { 4834 static struct S { void[] member; } 4835 mixin testWithQualifiers!(S, true); 4836 } 4837 { 4838 static struct S { void[1] member; } 4839 mixin testWithQualifiers!(S, true); 4840 } 4841 { 4842 static struct S { void[0] member; } 4843 mixin testWithQualifiers!(S, false); 4844 } 4845 } 4846 4847 // Structs with multiple members, testing pointer types. 4848 { 4849 static struct S { int i; bool b; } 4850 mixin testWithQualifiers!(S, false); 4851 } 4852 { 4853 static struct S { int* i; bool b; } 4854 mixin testWithQualifiers!(S, true); 4855 } 4856 { 4857 static struct S { int i; bool* b; } 4858 mixin testWithQualifiers!(S, true); 4859 } 4860 { 4861 static struct S { int* i; bool* b; } 4862 mixin testWithQualifiers!(S, true); 4863 } 4864 4865 // Structs with multiple members, testing dynamic arrays. 4866 { 4867 static struct S { int[] arr; } 4868 mixin testWithQualifiers!(S, true); 4869 } 4870 { 4871 static struct S { int i; int[] arr; } 4872 mixin testWithQualifiers!(S, true); 4873 } 4874 { 4875 static struct S { int[] arr; int i; } 4876 mixin testWithQualifiers!(S, true); 4877 } 4878 4879 // Structs with multiple members, testing static arrays. 4880 { 4881 static struct S { int[1] arr; } 4882 mixin testWithQualifiers!(S, false); 4883 } 4884 { 4885 static struct S { int i; int[1] arr; } 4886 mixin testWithQualifiers!(S, false); 4887 } 4888 { 4889 static struct S { int[1] arr; int i; } 4890 mixin testWithQualifiers!(S, false); 4891 } 4892 4893 { 4894 static struct S { int*[0] arr; } 4895 mixin testWithQualifiers!(S, false); 4896 } 4897 { 4898 static struct S { int i; int*[0] arr; } 4899 mixin testWithQualifiers!(S, false); 4900 } 4901 { 4902 static struct S { int*[0] arr; int i; } 4903 mixin testWithQualifiers!(S, false); 4904 } 4905 4906 { 4907 static struct S { string[42] arr; } 4908 mixin testWithQualifiers!(S, true); 4909 } 4910 { 4911 static struct S { int i; string[42] arr; } 4912 mixin testWithQualifiers!(S, true); 4913 } 4914 { 4915 static struct S { string[42] arr; int i; } 4916 mixin testWithQualifiers!(S, true); 4917 } 4918 4919 // Structs with associative arrays. 4920 { 4921 static struct S { int[string] aa; } 4922 mixin testWithQualifiers!(S, true); 4923 } 4924 { 4925 static struct S { int i; int[string] aa; } 4926 mixin testWithQualifiers!(S, true); 4927 } 4928 { 4929 static struct S { int[string] aa; int i; } 4930 mixin testWithQualifiers!(S, true); 4931 } 4932 4933 { 4934 static struct S { int[42][int] aa; } 4935 mixin testWithQualifiers!(S, true); 4936 } 4937 { 4938 static struct S { int[0][int] aa; } 4939 mixin testWithQualifiers!(S, true); 4940 } 4941 4942 // Structs with classes. 4943 { 4944 class C {} 4945 struct S { C c; } 4946 mixin testWithQualifiers!(S, true); 4947 } 4948 { 4949 interface I {} 4950 struct S { I i; } 4951 mixin testWithQualifiers!(S, true); 4952 } 4953 4954 // Structs with delegates. 4955 { 4956 struct S { void delegate() d; } 4957 mixin testWithQualifiers!(S, true); 4958 } 4959 { 4960 struct S { int delegate(int) d; } 4961 mixin testWithQualifiers!(S, true); 4962 } 4963 4964 // Structs multiple layers deep. 4965 { 4966 struct S1 { int i; } 4967 struct S2 { S1 s; } 4968 struct S3 { S2 s; } 4969 struct S4 { S3 s; } 4970 struct S5 { S4 s; } 4971 struct S6 { S5 s; } 4972 struct S7 { S6[0] s; } 4973 struct S8 { S7 s; } 4974 struct S9 { S8 s; } 4975 struct S10 { S9 s; } 4976 mixin testWithQualifiers!(S1, false); 4977 mixin testWithQualifiers!(S2, false); 4978 mixin testWithQualifiers!(S3, false); 4979 mixin testWithQualifiers!(S4, false); 4980 mixin testWithQualifiers!(S5, false); 4981 mixin testWithQualifiers!(S6, false); 4982 mixin testWithQualifiers!(S7, false); 4983 mixin testWithQualifiers!(S8, false); 4984 mixin testWithQualifiers!(S9, false); 4985 mixin testWithQualifiers!(S10, false); 4986 } 4987 { 4988 struct S1 { int* i; } 4989 struct S2 { S1 s; } 4990 struct S3 { S2 s; } 4991 struct S4 { S3 s; } 4992 struct S5 { S4 s; } 4993 struct S6 { S5 s; } 4994 struct S7 { S6[0] s; } 4995 struct S8 { S7 s; } 4996 struct S9 { S8 s; } 4997 struct S10 { S9 s; } 4998 mixin testWithQualifiers!(S1, true); 4999 mixin testWithQualifiers!(S2, true); 5000 mixin testWithQualifiers!(S3, true); 5001 mixin testWithQualifiers!(S4, true); 5002 mixin testWithQualifiers!(S5, true); 5003 mixin testWithQualifiers!(S6, true); 5004 mixin testWithQualifiers!(S7, false); 5005 mixin testWithQualifiers!(S8, false); 5006 mixin testWithQualifiers!(S9, false); 5007 mixin testWithQualifiers!(S10, false); 5008 } 5009 } 5010 5011 // hasIndirections with unions. 5012 @safe unittest 5013 { 5014 import phobos.sys.meta : AliasSeq; 5015 5016 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 5017 5018 { 5019 union U {} 5020 mixin testWithQualifiers!(U, false); 5021 } 5022 { 5023 static union U {} 5024 mixin testWithQualifiers!(U, false); 5025 } 5026 5027 // Unions with members which aren't aggregate types and don't have indirections. 5028 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 5029 float, double, real, char, wchar, dchar, int function(string))) 5030 { 5031 // No indirections. 5032 { 5033 union U { T member; } 5034 mixin testWithQualifiers!(U, false); 5035 } 5036 { 5037 union U { const T member; } 5038 mixin testWithQualifiers!(U, false); 5039 } 5040 { 5041 union U { immutable T member; } 5042 mixin testWithQualifiers!(U, false); 5043 } 5044 { 5045 union U { shared T member; } 5046 mixin testWithQualifiers!(U, false); 5047 } 5048 5049 // Pointers. 5050 { 5051 union U { T* member; } 5052 mixin testWithQualifiers!(U, true); 5053 } 5054 { 5055 union U { const(T)* member; } 5056 mixin testWithQualifiers!(U, true); 5057 } 5058 { 5059 union U { const T* member; } 5060 mixin testWithQualifiers!(U, true); 5061 } 5062 { 5063 union U { immutable T* member; } 5064 mixin testWithQualifiers!(U, true); 5065 } 5066 { 5067 union U { shared T* member; } 5068 mixin testWithQualifiers!(U, true); 5069 } 5070 5071 // Dynamic arrays. 5072 { 5073 union U { T[] member; } 5074 mixin testWithQualifiers!(U, true); 5075 } 5076 { 5077 union U { const(T)[] member; } 5078 mixin testWithQualifiers!(U, true); 5079 } 5080 { 5081 union U { const T[] member; } 5082 mixin testWithQualifiers!(U, true); 5083 } 5084 { 5085 union U { immutable T[] member; } 5086 mixin testWithQualifiers!(U, true); 5087 } 5088 { 5089 union U { shared T[] member; } 5090 mixin testWithQualifiers!(U, true); 5091 } 5092 5093 // Static arrays. 5094 { 5095 union U { T[1] member; } 5096 mixin testWithQualifiers!(U, false); 5097 } 5098 { 5099 union U { const(T)[1] member; } 5100 mixin testWithQualifiers!(U, false); 5101 } 5102 { 5103 union U { const T[1] member; } 5104 mixin testWithQualifiers!(U, false); 5105 } 5106 { 5107 union U { immutable T[1] member; } 5108 mixin testWithQualifiers!(U, false); 5109 } 5110 { 5111 union U { shared T[1] member; } 5112 mixin testWithQualifiers!(U, false); 5113 } 5114 5115 // Static arrays of pointers. 5116 { 5117 union U { T*[1] member; } 5118 mixin testWithQualifiers!(U, true); 5119 } 5120 { 5121 union U { const(T)*[1] member; } 5122 mixin testWithQualifiers!(U, true); 5123 } 5124 { 5125 union U { const(T*)[1] member; } 5126 mixin testWithQualifiers!(U, true); 5127 } 5128 { 5129 union U { const T*[1] member; } 5130 mixin testWithQualifiers!(U, true); 5131 } 5132 { 5133 union U { immutable T*[1] member; } 5134 mixin testWithQualifiers!(U, true); 5135 } 5136 { 5137 union U { shared T*[1] member; } 5138 mixin testWithQualifiers!(U, true); 5139 } 5140 5141 { 5142 union U { T*[0] member; } 5143 mixin testWithQualifiers!(U, false); 5144 } 5145 { 5146 union U { const(T)*[0] member; } 5147 mixin testWithQualifiers!(U, false); 5148 } 5149 { 5150 union U { const(T*)[0] member; } 5151 mixin testWithQualifiers!(U, false); 5152 } 5153 { 5154 union U { const T*[0] member; } 5155 mixin testWithQualifiers!(U, false); 5156 } 5157 { 5158 union U { immutable T*[0] member; } 5159 mixin testWithQualifiers!(U, false); 5160 } 5161 { 5162 union U { shared T*[0] member; } 5163 mixin testWithQualifiers!(U, false); 5164 } 5165 5166 // Static arrays of dynamic arrays. 5167 { 5168 union U { T[][1] member; } 5169 mixin testWithQualifiers!(U, true); 5170 } 5171 { 5172 union U { const(T)[][1] member; } 5173 mixin testWithQualifiers!(U, true); 5174 } 5175 { 5176 union U { const(T[])[1] member; } 5177 mixin testWithQualifiers!(U, true); 5178 } 5179 { 5180 union U { const T[][1] member; } 5181 mixin testWithQualifiers!(U, true); 5182 } 5183 { 5184 union U { immutable T[][1] member; } 5185 mixin testWithQualifiers!(U, true); 5186 } 5187 { 5188 union U { shared T[][1] member; } 5189 mixin testWithQualifiers!(U, true); 5190 } 5191 5192 { 5193 union U { T[][0] member; } 5194 mixin testWithQualifiers!(U, false); 5195 } 5196 { 5197 union U { const(T)[][0] member; } 5198 mixin testWithQualifiers!(U, false); 5199 } 5200 { 5201 union U { const(T[])[0] member; } 5202 mixin testWithQualifiers!(U, false); 5203 } 5204 { 5205 union U { const T[][0] member; } 5206 mixin testWithQualifiers!(U, false); 5207 } 5208 { 5209 union U { immutable T[][0] member; } 5210 mixin testWithQualifiers!(U, false); 5211 } 5212 { 5213 union U { shared T[][0] member; } 5214 mixin testWithQualifiers!(U, false); 5215 } 5216 } 5217 5218 // Unions with arrays of void. 5219 { 5220 { 5221 static union U { void[] member; } 5222 mixin testWithQualifiers!(U, true); 5223 } 5224 { 5225 static union U { void[1] member; } 5226 mixin testWithQualifiers!(U, true); 5227 } 5228 { 5229 static union U { void[0] member; } 5230 mixin testWithQualifiers!(U, false); 5231 } 5232 } 5233 5234 // Unions with multiple members, testing pointer types. 5235 { 5236 static union U { int i; bool b; } 5237 mixin testWithQualifiers!(U, false); 5238 } 5239 { 5240 static union U { int* i; bool b; } 5241 mixin testWithQualifiers!(U, true); 5242 } 5243 { 5244 static union U { int i; bool* b; } 5245 mixin testWithQualifiers!(U, true); 5246 } 5247 { 5248 static union U { int* i; bool* b; } 5249 mixin testWithQualifiers!(U, true); 5250 } 5251 5252 // Unions with multiple members, testing dynamic arrays. 5253 { 5254 static union U { int[] arr; } 5255 mixin testWithQualifiers!(U, true); 5256 } 5257 { 5258 static union U { int i; int[] arr; } 5259 mixin testWithQualifiers!(U, true); 5260 } 5261 { 5262 static union U { int[] arr; int i; } 5263 mixin testWithQualifiers!(U, true); 5264 } 5265 5266 // Unions with multiple members, testing static arrays. 5267 { 5268 static union U { int[1] arr; } 5269 mixin testWithQualifiers!(U, false); 5270 } 5271 { 5272 static union U { int i; int[1] arr; } 5273 mixin testWithQualifiers!(U, false); 5274 } 5275 { 5276 static union U { int[1] arr; int i; } 5277 mixin testWithQualifiers!(U, false); 5278 } 5279 5280 { 5281 static union U { int*[0] arr; } 5282 mixin testWithQualifiers!(U, false); 5283 } 5284 { 5285 static union U { int i; int*[0] arr; } 5286 mixin testWithQualifiers!(U, false); 5287 } 5288 { 5289 static union U { int*[0] arr; int i; } 5290 mixin testWithQualifiers!(U, false); 5291 } 5292 5293 { 5294 static union U { string[42] arr; } 5295 mixin testWithQualifiers!(U, true); 5296 } 5297 { 5298 static union U { int i; string[42] arr; } 5299 mixin testWithQualifiers!(U, true); 5300 } 5301 { 5302 static union U { string[42] arr; int i; } 5303 mixin testWithQualifiers!(U, true); 5304 } 5305 5306 // Unions with associative arrays. 5307 { 5308 static union U { int[string] aa; } 5309 mixin testWithQualifiers!(U, true); 5310 } 5311 { 5312 static union U { int i; int[string] aa; } 5313 mixin testWithQualifiers!(U, true); 5314 } 5315 { 5316 static union U { int[string] aa; int i; } 5317 mixin testWithQualifiers!(U, true); 5318 } 5319 5320 { 5321 static union U { int[42][int] aa; } 5322 mixin testWithQualifiers!(U, true); 5323 } 5324 { 5325 static union U { int[0][int] aa; } 5326 mixin testWithQualifiers!(U, true); 5327 } 5328 5329 // Unions with classes. 5330 { 5331 class C {} 5332 union U { C c; } 5333 mixin testWithQualifiers!(U, true); 5334 } 5335 { 5336 interface I {} 5337 union U { I i; } 5338 mixin testWithQualifiers!(U, true); 5339 } 5340 5341 // Unions with delegates. 5342 { 5343 union U { void delegate() d; } 5344 mixin testWithQualifiers!(U, true); 5345 } 5346 { 5347 union U { int delegate(int) d; } 5348 mixin testWithQualifiers!(U, true); 5349 } 5350 5351 // Unions multiple layers deep. 5352 { 5353 union U1 { int i; } 5354 union U2 { U1 s; } 5355 union U3 { U2 s; } 5356 union U4 { U3 s; } 5357 union U5 { U4 s; } 5358 union U6 { U5 s; } 5359 union U7 { U6[0] s; } 5360 union U8 { U7 s; } 5361 union U9 { U8 s; } 5362 union U10 { U9 s; } 5363 mixin testWithQualifiers!(U1, false); 5364 mixin testWithQualifiers!(U2, false); 5365 mixin testWithQualifiers!(U3, false); 5366 mixin testWithQualifiers!(U4, false); 5367 mixin testWithQualifiers!(U5, false); 5368 mixin testWithQualifiers!(U6, false); 5369 mixin testWithQualifiers!(U7, false); 5370 mixin testWithQualifiers!(U8, false); 5371 mixin testWithQualifiers!(U9, false); 5372 mixin testWithQualifiers!(U10, false); 5373 } 5374 { 5375 union U1 { int* i; } 5376 union U2 { U1 s; } 5377 union U3 { U2 s; } 5378 union U4 { U3 s; } 5379 union U5 { U4 s; } 5380 union U6 { U5 s; } 5381 union U7 { U6[0] s; } 5382 union U8 { U7 s; } 5383 union U9 { U8 s; } 5384 union U10 { U9 s; } 5385 mixin testWithQualifiers!(U1, true); 5386 mixin testWithQualifiers!(U2, true); 5387 mixin testWithQualifiers!(U3, true); 5388 mixin testWithQualifiers!(U4, true); 5389 mixin testWithQualifiers!(U5, true); 5390 mixin testWithQualifiers!(U6, true); 5391 mixin testWithQualifiers!(U7, false); 5392 mixin testWithQualifiers!(U8, false); 5393 mixin testWithQualifiers!(U9, false); 5394 mixin testWithQualifiers!(U10, false); 5395 } 5396 } 5397 5398 // hasIndirections with classes and interfaces 5399 @safe unittest 5400 { 5401 import phobos.sys.meta : AliasSeq; 5402 5403 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 5404 5405 { 5406 class C {} 5407 mixin testWithQualifiers!(C, true); 5408 } 5409 5410 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 5411 float, double, real, char, wchar, dchar, int function(string), 5412 int[int], string delegate(int))) 5413 { 5414 { 5415 class C { T member; } 5416 mixin testWithQualifiers!(C, true); 5417 } 5418 { 5419 class C { const T member; } 5420 mixin testWithQualifiers!(C, true); 5421 } 5422 { 5423 class C { immutable T member; } 5424 mixin testWithQualifiers!(C, true); 5425 } 5426 { 5427 class C { shared T member; } 5428 mixin testWithQualifiers!(C, true); 5429 } 5430 } 5431 5432 { 5433 interface I {} 5434 mixin testWithQualifiers!(I, true); 5435 } 5436 } 5437 5438 /++ 5439 Takes a type which is an associative array and evaluates to the type of the 5440 keys in that associative array. 5441 5442 See_Also: 5443 $(LREF ValueType) 5444 +/ 5445 alias KeyType(V : V[K], K) = K; 5446 5447 /// 5448 @safe unittest 5449 { 5450 static assert(is(KeyType!(int[string]) == string)); 5451 static assert(is(KeyType!(string[int]) == int)); 5452 5453 static assert(is(KeyType!(string[const int]) == const int)); 5454 static assert(is(KeyType!(const int[string]) == string)); 5455 5456 struct S 5457 { 5458 int i; 5459 } 5460 5461 string[S] aa1; 5462 static assert(is(KeyType!(typeof(aa1)) == S)); 5463 5464 S[string] aa2; 5465 static assert(is(KeyType!(typeof(aa2)) == string)); 5466 5467 KeyType!(typeof(aa1)) key1 = S(42); 5468 KeyType!(typeof(aa2)) key2 = "foo"; 5469 5470 // Key types with indirections have their inner layers treated as const 5471 // by the compiler, because the values of keys can't change, or the hash 5472 // value could change, putting the associative array in an invalid state. 5473 static assert(is(KeyType!(bool[string[]]) == const(string)[])); 5474 static assert(is(KeyType!(bool[int*]) == const(int)*)); 5475 5476 // If the given type is not an AA, then KeyType won't compile. 5477 static assert(!__traits(compiles, KeyType!int)); 5478 static assert(!__traits(compiles, KeyType!(int[]))); 5479 } 5480 5481 /++ 5482 Takes a type which is an associative array and evaluates to the type of the 5483 values in that associative array. 5484 5485 See_Also: 5486 $(LREF KeyType) 5487 +/ 5488 alias ValueType(V : V[K], K) = V; 5489 5490 /// 5491 @safe unittest 5492 { 5493 static assert(is(ValueType!(int[string]) == int)); 5494 static assert(is(ValueType!(string[int]) == string)); 5495 5496 static assert(is(ValueType!(string[const int]) == string)); 5497 static assert(is(ValueType!(const int[string]) == const int)); 5498 5499 struct S 5500 { 5501 int i; 5502 } 5503 5504 string[S] aa1; 5505 static assert(is(ValueType!(typeof(aa1)) == string)); 5506 5507 S[string] aa2; 5508 static assert(is(ValueType!(typeof(aa2)) == S)); 5509 5510 ValueType!(typeof(aa1)) value1 = "foo"; 5511 ValueType!(typeof(aa2)) value2 = S(42); 5512 5513 // If the given type is not an AA, then ValueType won't compile. 5514 static assert(!__traits(compiles, ValueType!int)); 5515 static assert(!__traits(compiles, ValueType!(int[]))); 5516 } 5517 5518 /++ 5519 Evaluates to the original / ultimate base type of an enum type - or for 5520 non-enum types, it evaluates to the type that it's given. 5521 5522 If the base type of the given enum type is not an enum, then the result of 5523 OriginalType is its direct base type. However, if the base type of the 5524 given enum is also an enum, then OriginalType gives the ultimate base type 5525 - that is, it keeps getting the base type for each succesive enum in the 5526 chain until it gets to a base type that isn't an enum, and that's the 5527 result. So, the result will never be an enum type. 5528 5529 If the given type has any qualifiers, the result will have those same 5530 qualifiers. 5531 +/ 5532 version (StdDdoc) template OriginalType(T) 5533 { 5534 import core.internal.traits : CoreOriginalType = OriginalType; 5535 alias OriginalType = CoreOriginalType!T; 5536 } 5537 else 5538 { 5539 import core.internal.traits : CoreOriginalType = OriginalType; 5540 alias OriginalType = CoreOriginalType; 5541 } 5542 5543 /// 5544 @safe unittest 5545 { 5546 enum E { a, b, c } 5547 static assert(is(OriginalType!E == int)); 5548 5549 enum F : E { x = E.a } 5550 static assert(is(OriginalType!F == int)); 5551 5552 enum G : F { y = F.x } 5553 static assert(is(OriginalType!G == int)); 5554 static assert(is(OriginalType!(const G) == const int)); 5555 static assert(is(OriginalType!(immutable G) == immutable int)); 5556 static assert(is(OriginalType!(shared G) == shared int)); 5557 5558 enum C : char { a = 'a', b = 'b' } 5559 static assert(is(OriginalType!C == char)); 5560 5561 enum D : string { d = "dlang" } 5562 static assert(is(OriginalType!D == string)); 5563 5564 static assert(is(OriginalType!int == int)); 5565 static assert(is(OriginalType!(const long) == const long)); 5566 static assert(is(OriginalType!string == string)); 5567 5568 // OriginalType gets the base type of enums and for all other types gives 5569 // the same type back. It does nothing special for other types - like 5570 // classes - where one could talk about the type having a base type. 5571 class Base {} 5572 class Derived : Base {} 5573 static assert(is(OriginalType!Base == Base)); 5574 static assert(is(OriginalType!Derived == Derived)); 5575 } 5576 5577 /++ 5578 Removes the outer layer of $(D const), $(D inout), or $(D immutable) 5579 from type $(D T). 5580 5581 If none of those qualifiers have been applied to the outer layer of 5582 type $(D T), then the result is $(D T). 5583 5584 For the built-in scalar types (that is $(D bool), the character types, and 5585 the numeric types), they only have one layer, so $(D const U) simply becomes 5586 $(D U). 5587 5588 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 5589 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 5590 goes from being fully $(D const) to being a mutable pointer to $(D const), 5591 and a dynamic array goes from being fully $(D const) to being a mutable 5592 dynamic array of $(D const) elements. And if there are multiple layers of 5593 pointers or arrays, it's just that outer layer which is affected - e.g. 5594 $(D const(U**)) would become $(D const(U*)*). 5595 5596 For user-defined types, the effect is that $(D const U) becomes $(D U), and 5597 how that affects member variables depends on the type of the member 5598 variable. If a member variable is explicitly marked with any mutability 5599 qualifiers, then it will continue to have those qualifiers even after 5600 Unconst has stripped all mutability qualifiers from the containing type. 5601 However, if a mutability qualifier was on the member variable only because 5602 the containing type had that qualifier, then when Unconst removes the 5603 qualifier from the containing type, it is removed from the member variable 5604 as well. 5605 5606 Also, Unconst has no effect on what a templated type is instantiated 5607 with, so if a templated type is instantiated with a template argument which 5608 has a mutability qualifier, the template instantiation will not change. 5609 +/ 5610 version (StdDdoc) template Unconst(T) 5611 { 5612 import core.internal.traits : CoreUnconst = Unconst; 5613 alias Unconst = CoreUnconst!T; 5614 } 5615 else 5616 { 5617 import core.internal.traits : CoreUnconst = Unconst; 5618 alias Unconst = CoreUnconst; 5619 } 5620 5621 /// 5622 @safe unittest 5623 { 5624 static assert(is(Unconst!( int) == int)); 5625 static assert(is(Unconst!( const int) == int)); 5626 static assert(is(Unconst!( inout int) == int)); 5627 static assert(is(Unconst!( inout const int) == int)); 5628 static assert(is(Unconst!(shared int) == shared int)); 5629 static assert(is(Unconst!(shared const int) == shared int)); 5630 static assert(is(Unconst!(shared inout int) == shared int)); 5631 static assert(is(Unconst!(shared inout const int) == shared int)); 5632 static assert(is(Unconst!( immutable int) == int)); 5633 5634 // Only the outer layer of immutable is removed. 5635 // immutable(int[]) -> immutable(int)[] 5636 alias ImmIntArr = immutable(int[]); 5637 static assert(is(Unconst!ImmIntArr == immutable(int)[])); 5638 5639 // Only the outer layer of const is removed. 5640 // immutable(int*) -> immutable(int)* 5641 alias ConstIntPtr = const(int*); 5642 static assert(is(Unconst!ConstIntPtr == const(int)*)); 5643 5644 // const(int)* -> const(int)* 5645 alias PtrToConstInt = const(int)*; 5646 static assert(is(Unconst!PtrToConstInt == const(int)*)); 5647 5648 static struct S 5649 { 5650 int* ptr; 5651 const int* cPtr; 5652 shared int* sPtr; 5653 } 5654 5655 const S s; 5656 static assert(is(typeof(s) == const S)); 5657 static assert(is(typeof(typeof(s).ptr) == const int*)); 5658 static assert(is(typeof(typeof(s).cPtr) == const int*)); 5659 static assert(is(typeof(typeof(s).sPtr) == const shared int*)); 5660 5661 // For user-defined types, all mutability qualifiers that are applied to 5662 // member variables only because the containing type has them are removed, 5663 // but the ones that are directly on those member variables remain. 5664 5665 // const S -> S 5666 static assert(is(Unconst!(typeof(s)) == S)); 5667 static assert(is(typeof(Unconst!(typeof(s)).ptr) == int*)); 5668 static assert(is(typeof(Unconst!(typeof(s)).cPtr) == const int*)); 5669 static assert(is(typeof(Unconst!(typeof(s)).sPtr) == shared int*)); 5670 5671 static struct Foo(T) 5672 { 5673 T* ptr; 5674 } 5675 5676 // The qualifier on the type is removed, but the qualifier on the template 5677 // argument is not. 5678 static assert(is(Unconst!(const(Foo!(const int))) == Foo!(const int))); 5679 static assert(is(Unconst!(Foo!(const int)) == Foo!(const int))); 5680 static assert(is(Unconst!(const(Foo!int)) == Foo!int)); 5681 } 5682 5683 /++ 5684 Removes the outer layer of $(D shared) from type $(D T). 5685 5686 If $(D shared) has not been applied to the outer layer of type $(D T), then 5687 the result is $(D T). 5688 5689 Note that while $(D immutable) is implicitly $(D shared), it is unaffected 5690 by Unshared. Only explicit $(D shared) is removed. 5691 5692 For the built-in scalar types (that is $(D bool), the character types, and 5693 the numeric types), they only have one layer, so $(D shared U) simply 5694 becomes $(D U). 5695 5696 Where the layers come in is pointers and arrays. $(D shared(U*)) becomes 5697 $(D shared(U)*), and $(D shared(U[])), becomes $(D shared(U)[]). So, a 5698 pointer goes from being fully $(D shared) to being a mutable pointer to 5699 $(D shared), and a dynamic array goes from being fully $(D shared) to being 5700 a mutable dynamic array of $(D shared) elements. And if there are multiple 5701 layers of pointers or arrays, it's just that outer layer which is affected 5702 - e.g. $(D shared(U**)) would become $(D shared(U*)*). 5703 5704 For user-defined types, the effect is that $(D shared U) becomes $(D U), 5705 and how that affects member variables depends on the type of the member 5706 variable. If a member variable is explicitly marked with $(D shared), then 5707 it will continue to be $(D shared) even after Unshared has stripped 5708 $(D shared) from the containing type. However, if $(D shared) was on the 5709 member variable only because the containing type was $(D shared), then when 5710 Unshared removes the qualifier from the containing type, it is removed from 5711 the member variable as well. 5712 5713 Also, Unshared has no effect on what a templated type is instantiated 5714 with, so if a templated type is instantiated with a template argument which 5715 has a type qualifier, the template instantiation will not change. 5716 +/ 5717 template Unshared(T) 5718 { 5719 static if (is(T == shared U, U)) 5720 alias Unshared = U; 5721 else 5722 alias Unshared = T; 5723 } 5724 5725 /// 5726 @safe unittest 5727 { 5728 static assert(is(Unshared!( int) == int)); 5729 static assert(is(Unshared!( const int) == const int)); 5730 static assert(is(Unshared!( inout int) == inout int)); 5731 static assert(is(Unshared!( inout const int) == inout const int)); 5732 static assert(is(Unshared!(shared int) == int)); 5733 static assert(is(Unshared!(shared const int) == const int)); 5734 static assert(is(Unshared!(shared inout int) == inout int)); 5735 static assert(is(Unshared!(shared inout const int) == inout const int)); 5736 static assert(is(Unshared!( immutable int) == immutable int)); 5737 5738 // Only the outer layer of shared is removed. 5739 // shared(int[]) -> shared(int)[] 5740 alias SharedIntArr = shared(int[]); 5741 static assert(is(Unshared!SharedIntArr == shared(int)[])); 5742 5743 // Only the outer layer of shared is removed. 5744 // shared(int*) -> shared(int)* 5745 alias SharedIntPtr = shared(int*); 5746 static assert(is(Unshared!SharedIntPtr == shared(int)*)); 5747 5748 // shared(int)* -> shared(int)* 5749 alias PtrToSharedInt = shared(int)*; 5750 static assert(is(Unshared!PtrToSharedInt == shared(int)*)); 5751 5752 // immutable is unaffected 5753 alias ImmutableArr = immutable(int[]); 5754 static assert(is(Unshared!ImmutableArr == immutable(int[]))); 5755 5756 static struct S 5757 { 5758 int* ptr; 5759 const int* cPtr; 5760 shared int* sPtr; 5761 } 5762 5763 shared S s; 5764 static assert(is(typeof(s) == shared S)); 5765 static assert(is(typeof(typeof(s).ptr) == shared int*)); 5766 static assert(is(typeof(typeof(s).cPtr) == const shared int*)); 5767 static assert(is(typeof(typeof(s).sPtr) == shared int*)); 5768 5769 // For user-defined types, if shared is applied to a member variable only 5770 // because the containing type is shared, then shared is removed from that 5771 // member variable, but if the member variable is directly marked as shared, 5772 // then it continues to be shared. 5773 5774 // shared S -> S 5775 static assert(is(Unshared!(typeof(s)) == S)); 5776 static assert(is(typeof(Unshared!(typeof(s)).ptr) == int*)); 5777 static assert(is(typeof(Unshared!(typeof(s)).cPtr) == const int*)); 5778 static assert(is(typeof(Unshared!(typeof(s)).sPtr) == shared int*)); 5779 5780 static struct Foo(T) 5781 { 5782 T* ptr; 5783 } 5784 5785 // The qualifier on the type is removed, but the qualifier on the template 5786 // argument is not. 5787 static assert(is(Unshared!(shared(Foo!(shared int))) == Foo!(shared int))); 5788 static assert(is(Unshared!(Foo!(shared int)) == Foo!(shared int))); 5789 static assert(is(Unshared!(shared(Foo!int)) == Foo!int)); 5790 } 5791 5792 /++ 5793 Removes the outer layer of all type qualifiers from type $(D T) - this 5794 includes $(D shared). 5795 5796 If no type qualifiers have been applied to the outer layer of type $(D T), 5797 then the result is $(D T). 5798 5799 For the built-in scalar types (that is $(D bool), the character types, and 5800 the numeric types), they only have one layer, so $(D const U) simply becomes 5801 $(D U). 5802 5803 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 5804 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 5805 goes from being fully $(D const) to being a mutable pointer to $(D const), 5806 and a dynamic array goes from being fully $(D const) to being a mutable 5807 dynamic array of $(D const) elements. And if there are multiple layers of 5808 pointers or arrays, it's just that outer layer which is affected - e.g. 5809 $(D shared(U**)) would become $(D shared(U*)*). 5810 5811 For user-defined types, the effect is that $(D const U) becomes $(D U), and 5812 how that affects member variables depends on the type of the member 5813 variable. If a member variable is explicitly marked with any qualifiers, 5814 then it will continue to have those qualifiers even after Unqualified has 5815 stripped all qualifiers from the containing type. However, if a qualifier 5816 was on the member variable only because the containing type had that 5817 qualifier, then when Unqualified removes the qualifier from the containing 5818 type, it is removed from the member variable as well. 5819 5820 Also, Unqualified has no effect on what a templated type is instantiated 5821 with, so if a templated type is instantiated with a template argument which 5822 has a type qualifier, the template instantiation will not change. 5823 5824 Note that in most cases, $(LREF Unconst) or $(LREF Unshared) should be used 5825 rather than Unqualified, because in most cases, code is not designed to 5826 work with $(D shared) and thus doing type checks which remove $(D shared) 5827 will allow $(D shared) types to pass template constraints when they won't 5828 actually work with the code. And when code is designed to work with 5829 $(D shared), it's often the case that the type checks need to take 5830 $(D const) into account in order to avoid accidentally mutating $(D const) 5831 data and violating the type system. 5832 5833 In particular, historically, a lot of D code has used 5834 $(REF Unqual, std, traits) (which is equivalent to phobos.sys.traits' 5835 Unqualified) when the programmer's intent was to remove $(D const), and 5836 $(D shared) wasn't actually considered at all. And in such cases, the code 5837 really should use $(LREF Unconst) instead. 5838 5839 But of course, if a template constraint or $(D static if) really needs to 5840 strip off both the mutability qualifiers and $(D shared) for what it's 5841 testing for, then that's what Unqualified is for. It's just that it's best 5842 practice to use $(LREF Unconst) when it's not clear that $(D shared) should 5843 be removed as well. 5844 5845 Also, note that $(D is(immutable T == immutable U))) is equivalent to 5846 $(D is(Unqualified!T == Unqualified!U)) (using $(D immutable) converts 5847 $(D const), $(D inout), and $(D shared) to $(D immutable), whereas using 5848 Unqualified strips off all type qualifiers, but the resulting comparison is 5849 the same as long as $(D immutable) is used on both sides or Unqualified is 5850 used on both sides)). So, in cases where code needs to compare two types to 5851 see whether they're the same while ignoring all qualifiers, it's generally 5852 better to use $(D immutable) on both types rather than using Unqualfied on 5853 both types, since that avoids needing to instantiate a template, and those 5854 instantiations can really add up when a project has a lot of templates 5855 with template constraints, $(D static if)s, and other forms of conditional 5856 compilation that need to compare types. 5857 +/ 5858 template Unqualified(T) 5859 { 5860 import core.internal.traits : CoreUnqualified = Unqual; 5861 alias Unqualified = CoreUnqualified!(T); 5862 } 5863 5864 /// 5865 @safe unittest 5866 { 5867 static assert(is(Unqualified!( int) == int)); 5868 static assert(is(Unqualified!( const int) == int)); 5869 static assert(is(Unqualified!( inout int) == int)); 5870 static assert(is(Unqualified!( inout const int) == int)); 5871 static assert(is(Unqualified!(shared int) == int)); 5872 static assert(is(Unqualified!(shared const int) == int)); 5873 static assert(is(Unqualified!(shared inout int) == int)); 5874 static assert(is(Unqualified!(shared inout const int) == int)); 5875 static assert(is(Unqualified!( immutable int) == int)); 5876 5877 // Only the outer layer of immutable is removed. 5878 // immutable(int[]) -> immutable(int)[] 5879 alias ImmIntArr = immutable(int[]); 5880 static assert(is(Unqualified!ImmIntArr == immutable(int)[])); 5881 5882 // Only the outer layer of const is removed. 5883 // const(int*) -> const(int)* 5884 alias ConstIntPtr = const(int*); 5885 static assert(is(Unqualified!ConstIntPtr == const(int)*)); 5886 5887 // const(int)* -> const(int)* 5888 alias PtrToConstInt = const(int)*; 5889 static assert(is(Unqualified!PtrToConstInt == const(int)*)); 5890 5891 // Only the outer layer of shared is removed. 5892 // shared(int*) -> shared(int)* 5893 alias SharedIntPtr = shared(int*); 5894 static assert(is(Unqualified!SharedIntPtr == shared(int)*)); 5895 5896 // shared(int)* -> shared(int)* 5897 alias PtrToSharedInt = shared(int)*; 5898 static assert(is(Unqualified!PtrToSharedInt == shared(int)*)); 5899 5900 // Both const and shared are removed from the outer layer. 5901 // shared const int[] -> shared(const(int))[] 5902 alias SharedConstIntArr = shared const(int[]); 5903 static assert(is(Unqualified!SharedConstIntArr == shared(const(int))[])); 5904 5905 static struct S 5906 { 5907 int* ptr; 5908 const int* cPtr; 5909 shared int* sPtr; 5910 } 5911 5912 shared const S s; 5913 static assert(is(typeof(s) == shared const S)); 5914 static assert(is(typeof(typeof(s).ptr) == shared const int*)); 5915 static assert(is(typeof(typeof(s).cPtr) == shared const int*)); 5916 static assert(is(typeof(typeof(s).sPtr) == shared const int*)); 5917 5918 // For user-defined types, all qualifiers that are applied to member 5919 // variables only because the containing type has them are removed, but the 5920 // ones that are directly on those member variables remain. 5921 5922 // shared const S -> S 5923 static assert(is(Unqualified!(typeof(s)) == S)); 5924 static assert(is(typeof(Unqualified!(typeof(s)).ptr) == int*)); 5925 static assert(is(typeof(Unqualified!(typeof(s)).cPtr) == const int*)); 5926 static assert(is(typeof(Unqualified!(typeof(s)).sPtr) == shared int*)); 5927 5928 static struct Foo(T) 5929 { 5930 T* ptr; 5931 } 5932 5933 // The qualifiers on the type are removed, but the qualifiers on the 5934 // template argument are not. 5935 static assert(is(Unqualified!(const(Foo!(const int))) == Foo!(const int))); 5936 static assert(is(Unqualified!(Foo!(const int)) == Foo!(const int))); 5937 static assert(is(Unqualified!(const(Foo!int)) == Foo!int)); 5938 } 5939 5940 /++ 5941 Applies $(D const) to the given type. 5942 5943 This is primarily useful in conjunction with templates that take a template 5944 predicate (such as many of the templates in phobos.sys.meta), since while in 5945 most cases, you can simply do $(D const T) or $(D const(T)) to make $(D T) 5946 $(D const), with something like $(REF Map, phobos, sys, meta), you need to 5947 pass a template to be applied. 5948 5949 See_Also: 5950 $(LREF ImmutableOf) 5951 $(LREF InoutOf) 5952 $(LREF SharedOf) 5953 +/ 5954 alias ConstOf(T) = const T; 5955 5956 /// 5957 @safe unittest 5958 { 5959 static assert(is(ConstOf!int == const int)); 5960 static assert(is(ConstOf!(const int) == const int)); 5961 static assert(is(ConstOf!(inout int) == inout const int)); 5962 static assert(is(ConstOf!(shared int) == const shared int)); 5963 5964 // Note that const has no effect on immutable. 5965 static assert(is(ConstOf!(immutable int) == immutable int)); 5966 5967 import phobos.sys.meta : AliasSeq, Map; 5968 5969 alias Types = AliasSeq!(int, long, 5970 bool*, ubyte[], 5971 string, immutable(string)); 5972 alias WithConst = Map!(ConstOf, Types); 5973 static assert(is(WithConst == 5974 AliasSeq!(const int, const long, 5975 const(bool*), const(ubyte[]), 5976 const(string), immutable(string)))); 5977 } 5978 5979 /++ 5980 Applies $(D immutable) to the given type. 5981 5982 This is primarily useful in conjunction with templates that take a template 5983 predicate (such as many of the templates in phobos.sys.meta), since while in 5984 most cases, you can simply do $(D immutable T) or $(D immutable(T)) to make 5985 $(D T) $(D immutable), with something like $(REF Map, phobos, sys, meta), 5986 you need to pass a template to be applied. 5987 5988 See_Also: 5989 $(LREF ConstOf) 5990 $(LREF InoutOf) 5991 $(LREF SharedOf) 5992 +/ 5993 alias ImmutableOf(T) = immutable T; 5994 5995 /// 5996 @safe unittest 5997 { 5998 static assert(is(ImmutableOf!int == immutable int)); 5999 6000 // Note that immutable overrides const and inout. 6001 static assert(is(ImmutableOf!(const int) == immutable int)); 6002 static assert(is(ImmutableOf!(inout int) == immutable int)); 6003 6004 // Note that immutable overrides shared, since immutable is implicitly 6005 // shared. 6006 static assert(is(ImmutableOf!(shared int) == immutable int)); 6007 6008 static assert(is(ImmutableOf!(immutable int) == immutable int)); 6009 6010 import phobos.sys.meta : AliasSeq, Map; 6011 6012 alias Types = AliasSeq!(int, long, 6013 bool*, ubyte[], 6014 string, immutable(string)); 6015 alias WithImmutable = Map!(ImmutableOf, Types); 6016 static assert(is(WithImmutable == 6017 AliasSeq!(immutable int, immutable long, 6018 immutable(bool*), immutable(ubyte[]), 6019 immutable(string), immutable(string)))); 6020 } 6021 6022 /++ 6023 Applies $(D inout) to the given type. 6024 6025 This is primarily useful in conjunction with templates that take a template 6026 predicate (such as many of the templates in phobos.sys.meta), since while in 6027 most cases, you can simply do $(D inout T) or $(D inout(T)) to make $(D T) 6028 $(D inout), with something like $(REF Map, phobos, sys, meta), you need to 6029 pass a template to be applied. 6030 6031 See_Also: 6032 $(LREF ConstOf) 6033 $(LREF ImmutableOf) 6034 $(LREF SharedOf) 6035 +/ 6036 alias InoutOf(T) = inout T; 6037 6038 /// 6039 @safe unittest 6040 { 6041 static assert(is(InoutOf!int == inout int)); 6042 static assert(is(InoutOf!(const int) == inout const int)); 6043 static assert(is(InoutOf!(inout int) == inout int)); 6044 static assert(is(InoutOf!(shared int) == inout shared int)); 6045 6046 // Note that inout has no effect on immutable. 6047 static assert(is(InoutOf!(immutable int) == immutable int)); 6048 6049 import phobos.sys.meta : AliasSeq, Map; 6050 6051 alias Types = AliasSeq!(int, long, 6052 bool*, ubyte[], 6053 string, immutable(string)); 6054 alias WithInout = Map!(InoutOf, Types); 6055 static assert(is(WithInout == 6056 AliasSeq!(inout int, inout long, 6057 inout(bool*), inout(ubyte[]), 6058 inout(string), immutable(string)))); 6059 } 6060 6061 /++ 6062 Applies $(D shared) to the given type. 6063 6064 This is primarily useful in conjunction with templates that take a template 6065 predicate (such as many of the templates in phobos.sys.meta), since while in 6066 most cases, you can simply do $(D shared T) or $(D shared(T)) to make $(D T) 6067 $(D shared), with something like $(REF Map, phobos, sys, meta), you need to 6068 pass a template to be applied. 6069 6070 See_Also: 6071 $(LREF ConstOf) 6072 $(LREF ImmutableOf) 6073 $(LREF InoutOf) 6074 +/ 6075 alias SharedOf(T) = shared T; 6076 6077 /// 6078 @safe unittest 6079 { 6080 static assert(is(SharedOf!int == shared int)); 6081 static assert(is(SharedOf!(const int) == const shared int)); 6082 static assert(is(SharedOf!(inout int) == inout shared int)); 6083 static assert(is(SharedOf!(shared int) == shared int)); 6084 6085 // Note that shared has no effect on immutable, since immutable is 6086 // implicitly shared. 6087 static assert(is(SharedOf!(immutable int) == immutable int)); 6088 6089 import phobos.sys.meta : AliasSeq, Map; 6090 6091 alias Types = AliasSeq!(int, long, 6092 bool*, ubyte[], 6093 string, immutable(string)); 6094 alias WithShared = Map!(SharedOf, Types); 6095 static assert(is(WithShared == 6096 AliasSeq!(shared int, shared long, 6097 shared(bool*), shared(ubyte[]), 6098 shared(string), immutable(string)))); 6099 } 6100 6101 // Needed for rvalueOf/lvalueOf because 6102 // "inout on return means inout must be on a parameter as well" 6103 private struct __InoutWorkaroundStruct {} 6104 6105 /++ 6106 Creates an lvalue or rvalue of type T to be used in conjunction with 6107 $(D is(typeof(...))) or 6108 $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))). 6109 6110 The idea is that some traits or other forms of conditional compilation need 6111 to verify that a particular piece of code compiles with an rvalue or an 6112 lvalue of a specific type, and these $(D @property) functions allow you to 6113 get an rvalue or lvalue of a specific type to use within an expression that 6114 is then tested to see whether it compiles. 6115 6116 They're $(D @property) functions so that using $(D typeof) on them gives 6117 the return type rather than the type of the function. 6118 6119 Note that these functions are $(I not) defined, so if they're actually used 6120 outside of type introspection, they'll result in linker errors. They're 6121 entirely for testing that a particular piece of code compiles with an rvalue 6122 or lvalue of the given type. 6123 6124 The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that 6125 these work when the given type has the $(D inout) qualifier, since the 6126 language requires that a function that returns an $(D inout) type also have 6127 an $(D inout) type as a parameter. It should just be ignored. 6128 +/ 6129 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 6130 6131 /++ Ditto +/ 6132 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 6133 6134 /// 6135 @safe unittest 6136 { 6137 static int foo(int); 6138 static assert(is(typeof(foo(lvalueOf!int)) == int)); 6139 static assert(is(typeof(foo(rvalueOf!int)) == int)); 6140 6141 static bool bar(ref int); 6142 static assert(is(typeof(bar(lvalueOf!int)) == bool)); 6143 static assert(!is(typeof(bar(rvalueOf!int)))); 6144 6145 static assert( is(typeof({ lvalueOf!int = 42; }))); 6146 static assert(!is(typeof({ rvalueOf!int = 42; }))); 6147 6148 static struct S {} 6149 static assert( is(typeof({ lvalueOf!S = S.init; }))); 6150 static assert(!is(typeof({ rvalueOf!S = S.init; }))); 6151 6152 static struct NoAssign 6153 { 6154 @disable void opAssign(ref NoAssign); 6155 } 6156 static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; }))); 6157 static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; }))); 6158 } 6159 6160 @system unittest 6161 { 6162 import phobos.sys.meta : AliasSeq; 6163 6164 void needLvalue(T)(ref T); 6165 static struct S {} 6166 int i; 6167 struct Nested { void f() { ++i; } } 6168 6169 static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object)) 6170 { 6171 static assert(!__traits(compiles, needLvalue(rvalueOf!T))); 6172 static assert( __traits(compiles, needLvalue(lvalueOf!T))); 6173 static assert(is(typeof(rvalueOf!T) == T)); 6174 static assert(is(typeof(lvalueOf!T) == T)); 6175 } 6176 6177 static assert(!__traits(compiles, rvalueOf!int = 1)); 6178 static assert( __traits(compiles, lvalueOf!byte = 127)); 6179 static assert(!__traits(compiles, lvalueOf!byte = 128)); 6180 } 6181 6182 // We may want to add this as some sort of public test helper in the future in 6183 // whatever module would be appropriate for that. 6184 private template assertWithQualifiers(alias Pred, T, bool expected) 6185 { 6186 static assert(Pred!T == expected); 6187 static assert(Pred!(const T) == expected); 6188 static assert(Pred!(inout T) == expected); 6189 static assert(Pred!(immutable T) == expected); 6190 static assert(Pred!(shared T) == expected); 6191 6192 static if (is(T == U*, U)) 6193 { 6194 static assert(Pred!(const(U)*) == expected); 6195 static assert(Pred!(inout(U)*) == expected); 6196 static assert(Pred!(immutable(U)*) == expected); 6197 static assert(Pred!(shared(U)*) == expected); 6198 } 6199 else static if (is(T == U[], U)) 6200 { 6201 static assert(Pred!(const(U)[]) == expected); 6202 static assert(Pred!(inout(U)[]) == expected); 6203 static assert(Pred!(immutable(U)[]) == expected); 6204 static assert(Pred!(shared(U)[]) == expected); 6205 } 6206 else static if (is(T == U[n], U, size_t n)) 6207 { 6208 static assert(Pred!(const(U)[n]) == expected); 6209 static assert(Pred!(inout(U)[n]) == expected); 6210 static assert(Pred!(immutable(U)[n]) == expected); 6211 static assert(Pred!(shared(U)[n]) == expected); 6212 } 6213 } 6214 6215 private template assertWithQualifiers(alias Pred) 6216 { 6217 alias assertWithQualifiers(T, bool expected) = .assertWithQualifiers!(Pred, T, expected); 6218 } 6219 6220 @safe unittest 6221 { 6222 mixin assertWithQualifiers!(isPointer, int*, true); 6223 mixin assertWithQualifiers!(isPointer, int, false); 6224 6225 alias test = assertWithQualifiers!isPointer; 6226 mixin test!(int*, true); 6227 mixin test!(int, false); 6228 }