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