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 Traits testing for type conversions) $(TD 67 $(LREF isImplicitlyConvertible) 68 $(LREF isQualifierConvertible) 69 )) 70 $(TR $(TD Traits for comparisons) $(TD 71 $(LREF isEqual) 72 $(LREF isSameSymbol) 73 $(LREF isSameType) 74 )) 75 $(TR $(TD Function traits) $(TD 76 $(LREF isDelegate) 77 $(LREF isFunction) 78 $(LREF isFunctionPointer) 79 $(LREF isReturn) 80 $(LREF ReturnType) 81 $(LREF ToFunctionType) 82 )) 83 $(TR $(TD Aggregate Type Traits) $(TD 84 $(LREF FieldNames) 85 $(LREF FieldSymbols) 86 $(LREF FieldTypes) 87 $(LREF hasComplexAssignment) 88 $(LREF hasComplexCopying) 89 $(LREF hasComplexDestruction) 90 $(LREF hasIndirections) 91 )) 92 $(TR $(TD General Types) $(TD 93 $(LREF KeyType) 94 $(LREF OriginalType) 95 $(LREF PropertyType) 96 $(LREF SymbolType) 97 $(LREF ValueType) 98 )) 99 $(TR $(TD Traits for removing type qualfiers) $(TD 100 $(LREF Unconst) 101 $(LREF Unshared) 102 $(LREF Unqualified) 103 )) 104 $(TR $(TD Type Constructors) $(TD 105 $(LREF ConstOf) 106 $(LREF ImmutableOf) 107 $(LREF InoutOf) 108 $(LREF SharedOf) 109 )) 110 $(TR $(TD Misc) $(TD 111 $(LREF defaultInit) 112 $(LREF EnumMembers) 113 $(LREF lvalueOf) 114 $(LREF rvalueOf) 115 )) 116 ) 117 118 Copyright: Copyright The D Language Foundation 2005 - 2024. 119 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 120 Authors: $(HTTP jmdavisprog.com, Jonathan M Davis) 121 $(HTTP digitalmars.com, Walter Bright), 122 Tomasz Stachowiak (`isExpressions`), 123 $(HTTP erdani.org, Andrei Alexandrescu), 124 Shin Fujishiro, 125 $(HTTP octarineparrot.com, Robert Clipsham), 126 $(HTTP klickverbot.at, David Nadlinger), 127 Kenji Hara, 128 Shoichi Kato 129 Source: $(PHOBOSSRC phobos/sys/traits) 130 +/ 131 module phobos.sys.traits; 132 133 /++ 134 Whether the given type is an "aggregate type" - i.e. a struct, class, 135 interface, or union. Enum types whose base type is an aggregate type are 136 also considered aggregate types. 137 +/ 138 template isAggregateType(T) 139 { 140 static if (is(T == enum)) 141 enum isAggregateType = isAggregateType!(OriginalType!T); 142 else 143 enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union); 144 } 145 146 /// 147 @safe unittest 148 { 149 struct S {} 150 class C {} 151 interface I {} 152 union U {} 153 154 static assert( isAggregateType!S); 155 static assert( isAggregateType!C); 156 static assert( isAggregateType!I); 157 static assert( isAggregateType!U); 158 static assert( isAggregateType!(const S)); 159 static assert( isAggregateType!(shared C)); 160 161 static assert(!isAggregateType!int); 162 static assert(!isAggregateType!string); 163 static assert(!isAggregateType!(S*)); 164 static assert(!isAggregateType!(C[])); 165 static assert(!isAggregateType!(I[string])); 166 167 enum ES : S { a = S.init } 168 enum EC : C { a = C.init } 169 enum EI : I { a = I.init } 170 enum EU : U { a = U.init } 171 172 static assert( isAggregateType!ES); 173 static assert( isAggregateType!EC); 174 static assert( isAggregateType!EI); 175 static assert( isAggregateType!EU); 176 static assert( isAggregateType!(const ES)); 177 static assert( isAggregateType!(const EC)); 178 } 179 180 /++ 181 Whether the given type is a dynamic array (or what is sometimes referred to 182 as a slice, since a dynamic array in D is a slice of memory). 183 184 Note that this does not include implicit conversions or enum types. The 185 type itself must be a dynamic array. 186 187 Remember that D's dynamic arrays are essentially: 188 --- 189 struct DynamicArray(T) 190 { 191 size_t length; 192 T* ptr; 193 } 194 --- 195 where $(D ptr) points to the first element in the array, and $(D length) is 196 the number of elements in the array. 197 198 A dynamic array is not a pointer (unlike arrays in C/C++), and its elements 199 do not live inside the dynamic array itself. The dynamic array is simply a 200 slice of memory and does not own or manage its own memory. It can be a 201 slice of any piece of memory, including GC-allocated memory, the stack, 202 malloc-ed memory, etc. (with what kind of memory it is of course being 203 determined by how the dynamic array was created in the first place) 204 - though if you do any operations on it which end up requiring allocation 205 (e.g. appending to it if it doesn't have the capacity to expand in-place, 206 which it won't if it isn't a slice of GC-allocated memory), then that 207 reallocation will result in the dynamic array being a slice of newly 208 allocated, GC-backed memory (regardless of what it was a slice of before), 209 since it's the GC that deals with those allocations. 210 211 As long as code just accesses the elements or members of the dynamic array 212 - or reduces its length so that it's a smaller slice - it will continue to 213 point to whatever block of memory it pointed to originally. And because the 214 GC makes sure that appending to a dynamic array does not stomp on the 215 memory of any other dynamic arrays, appending to a dynamic array will not 216 affect any other dynamic array which is a slice of that same block of 217 memory whether a reallocation occurs or not. 218 219 Regardless, since what allocated the memory that the dynamic array is a 220 slice of is irrevelant to the type of the dynamic array, whether a given 221 type is a dynamic array has nothing to do with the kind of memory that's 222 backing it. A dynamic array which is a slice of a static array of $(D int) 223 is the the same type as a dynamic array of $(D int) allocated with $(D new) 224 - i.e. both are $(D int[]). So, this trait will not tell you anything about 225 what kind of memory a dynamic array is a slice of. It just tells you 226 whether the type is a dynamic array or not. 227 228 If for some reason, it matters for a function what kind of memory backs one 229 of its parameters which is a dynamic array, or it needs to be made clear 230 whether the function will possibly cause that dynamic array to be 231 reallocated, then that needs to be indicated by the documentation and 232 cannot be enforced with a template constraint. A template constraint can 233 enforce that a type used with a template meets certain criteria (e.g. that 234 it's a dynamic array), but it cannot enforce anything about how the 235 template actually uses the type. 236 237 However, it $(D is) possible to enforce that a function doesn't use any 238 operations on a dynamic array which might cause it to be reallocated by 239 marking that function as $(D @nogc). 240 241 In most cases though, code can be written to not care what kind of memory 242 backs a dynamic array, because none of the operations on a dynamic array 243 actually care what kind of memory it's a slice of. It mostly just matters 244 when you need to track the lifetime of the memory, because it wasn't 245 allocated by the GC, or when it matters whether a dynamic array could be 246 reallocated or not (e.g. because the code needs to have that dynamic array 247 continue to point to the same block of memory). 248 249 See_Also: 250 $(LREF isPointer) 251 $(LREF isStaticArray) 252 $(DDSUBLINK spec/arrays, , The language spec for arrays) 253 +/ 254 enum isDynamicArray(T) = is(T == U[], U); 255 256 /// 257 @safe unittest 258 { 259 // Some types which are dynamic arrays. 260 static assert( isDynamicArray!(int[])); 261 static assert( isDynamicArray!(const int[])); 262 static assert( isDynamicArray!(inout int[])); 263 static assert( isDynamicArray!(shared(int)[])); 264 static assert( isDynamicArray!string); 265 266 static assert( isDynamicArray!(typeof([1, 2, 3]))); 267 static assert( isDynamicArray!(typeof("dlang"))); 268 269 int[] arr; 270 static assert( isDynamicArray!(typeof(arr))); 271 272 // Some types which aren't dynamic arrays. 273 static assert(!isDynamicArray!int); 274 static assert(!isDynamicArray!(int*)); 275 static assert(!isDynamicArray!real); 276 277 static struct S 278 { 279 int[] arr; 280 } 281 static assert(!isDynamicArray!S); 282 283 // The struct itself isn't considered a dynamic array, 284 // but its member variable is when checked directly. 285 static assert( isDynamicArray!(typeof(S.arr))); 286 287 // Static arrays. 288 static assert(!isDynamicArray!(int[5])); 289 static assert(!isDynamicArray!(const(int)[5])); 290 291 int[2] sArr = [42, 97]; 292 static assert(!isDynamicArray!(typeof(sArr))); 293 294 // While a static array is not a dynamic array, 295 // a slice of a static array is a dynamic array. 296 static assert( isDynamicArray!(typeof(sArr[]))); 297 298 // Dynamic array of static arrays. 299 static assert( isDynamicArray!(long[3][])); 300 301 // Static array of dynamic arrays. 302 static assert(!isDynamicArray!(long[][3])); 303 304 // Associative array. 305 static assert(!isDynamicArray!(int[string])); 306 307 // While typeof(null) gets treated as void[] in some contexts, it is 308 // distinct from void[] and is not considered to be a dynamic array. 309 static assert(!isDynamicArray!(typeof(null))); 310 311 // However, naturally, if null is cast to a dynamic array, it's a 312 // dynamic array, since the cast forces the type. 313 static assert( isDynamicArray!(typeof(cast(int[]) null))); 314 315 enum E : int[] 316 { 317 a = [1, 2, 3], 318 } 319 320 // Enums do not count. 321 static assert(!isDynamicArray!E); 322 323 static struct AliasThis 324 { 325 int[] arr; 326 alias this = arr; 327 } 328 329 // Other implicit conversions do not count. 330 static assert(!isDynamicArray!AliasThis); 331 } 332 333 @safe unittest 334 { 335 import phobos.sys.meta : Alias, AliasSeq; 336 337 static struct AliasThis(T) 338 { 339 T member; 340 alias this = member; 341 } 342 343 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 344 { 345 foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][])) 346 { 347 enum E : Q!T { a = Q!T.init } 348 349 static assert( isDynamicArray!(Q!T)); 350 static assert(!isDynamicArray!E); 351 static assert(!isDynamicArray!(AliasThis!(Q!T))); 352 } 353 354 foreach (T; AliasSeq!(int, int[51], int[][2], 355 char[][int][11], immutable char[13u], 356 const(real)[1], const(real)[1][1], void[0])) 357 { 358 enum E : Q!T { a = Q!T.init } 359 360 static assert(!isDynamicArray!(Q!T)); 361 static assert(!isDynamicArray!E); 362 static assert(!isDynamicArray!(AliasThis!(Q!T))); 363 } 364 } 365 } 366 367 /++ 368 Whether type $(D T) is a static array. 369 370 Note that this does not include implicit conversions or enum types. The 371 type itself must be a static array. This is in contrast to 372 $(D __traits(isStaticArray, T)) which is true for enums (but not for other 373 implict conversions to static arrays). 374 375 As explained in the module documentation, traits like this one are not true 376 for enums (unlike most of the $(D __traits) traits) in order to avoid 377 testing for implicit conversions by default with template constraints, 378 since that tends to lead to subtle bugs when the code isn't carefully 379 written to take implicit conversions into account. 380 381 See also: 382 $(DDSUBLINK spec/traits, isStaticArray, $(D __traits(isStaticArray, T))) 383 $(DDSUBLINK spec/arrays, , The language spec for arrays) 384 +/ 385 enum isStaticArray(T) = is(T == U[n], U, size_t n); 386 387 /// 388 @safe unittest 389 { 390 // Some types which are static arrays. 391 static assert( isStaticArray!(int[12])); 392 static assert( isStaticArray!(const int[42])); 393 static assert( isStaticArray!(inout int[0])); 394 static assert( isStaticArray!(shared(int)[907])); 395 static assert( isStaticArray!(immutable(char)[5])); 396 397 // D doesn't have static array literals, but you get the same effect 398 // by casting a dynamic array literal to a static array, and of course, 399 // the result is typed as a static array. 400 static assert( isStaticArray!(typeof(cast(int[3]) [1, 2, 3]))); 401 402 int[2] sArr = [1, 2]; 403 static assert( isStaticArray!(typeof(sArr))); 404 405 // Some types which are not static arrays. 406 static assert(!isStaticArray!int); 407 static assert(!isStaticArray!(int*)); 408 static assert(!isStaticArray!real); 409 410 static struct S 411 { 412 int[4] arr; 413 } 414 static assert(!isStaticArray!S); 415 416 // The struct itself isn't considered a static array, 417 // but its member variable is when checked directly. 418 static assert( isStaticArray!(typeof(S.arr))); 419 420 // Dynamic arrays. 421 static assert(!isStaticArray!(int[])); 422 static assert(!isStaticArray!(const(int)[])); 423 static assert(!isStaticArray!string); 424 425 int[] arr; 426 static assert(!isStaticArray!(typeof(arr))); 427 428 // A slice of a static array is of course not a static array, 429 // because it's a dynamic array. 430 static assert(!isStaticArray!(typeof(sArr[]))); 431 432 // Static array of dynamic arrays. 433 static assert( isStaticArray!(long[][3])); 434 435 // Dynamic array of static arrays. 436 static assert(!isStaticArray!(long[3][])); 437 438 // Associative array. 439 static assert(!isStaticArray!(int[string])); 440 441 // Of course, null is not considered to be a static array. 442 static assert(!isStaticArray!(typeof(null))); 443 444 enum E : int[3] 445 { 446 a = [1, 2, 3], 447 } 448 449 // Enums do not count. 450 static assert(!isStaticArray!E); 451 452 // This is where isStaticArray differs from __traits(isStaticArray, ...) 453 static assert( __traits(isStaticArray, E)); 454 455 static struct AliasThis 456 { 457 int[] arr; 458 alias this = arr; 459 } 460 461 // Other implicit conversions do not count. 462 static assert(!isStaticArray!AliasThis); 463 464 static assert(!__traits(isStaticArray, AliasThis)); 465 } 466 467 @safe unittest 468 { 469 import phobos.sys.meta : Alias, AliasSeq; 470 471 static struct AliasThis(T) 472 { 473 T member; 474 alias this = member; 475 } 476 477 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 478 { 479 foreach (T; AliasSeq!(int[51], int[][2], 480 char[][int][11], immutable char[13u], 481 const(real)[1], const(real)[1][1], void[0])) 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 foreach (T; AliasSeq!(int, int[], char[], string, long[3][], double[string][])) 491 { 492 enum E : Q!T { a = Q!T.init, } 493 494 static assert(!isStaticArray!(Q!T)); 495 static assert(!isStaticArray!E); 496 static assert(!isStaticArray!(AliasThis!(Q!T))); 497 } 498 } 499 } 500 501 /++ 502 Whether the given type is one of the built-in integer types, ignoring all 503 qualifiers. 504 505 $(TABLE 506 $(TR $(TH Integer Types)) 507 $(TR $(TD byte)) 508 $(TR $(TD ubyte)) 509 $(TR $(TD short)) 510 $(TR $(TD ushort)) 511 $(TR $(TD int)) 512 $(TR $(TD uint)) 513 $(TR $(TD long)) 514 $(TR $(TD ulong)) 515 ) 516 517 Note that this does not include implicit conversions or enum types. The 518 type itself must be one of the built-in integer types. 519 520 This trait does have some similarities with $(D __traits(isIntegral, T)), 521 but $(D isIntegral) accepts a $(I lot) more types than isInteger does. 522 isInteger is specifically for testing for the built-in integer types, 523 whereas $(D isIntegral) tests for a whole set of types that are vaguely 524 integer-like (including $(D bool), the three built-in character types, and 525 some of the vector types from core.simd). So, for most code, isInteger is 526 going to be more appropriate, but obviously, it depends on what the code is 527 trying to do. 528 529 See also: 530 $(DDSUBLINK spec/traits, isIntegral, $(D __traits(isIntegral, T))) 531 $(LREF isFloatingPoint) 532 $(LREF isSignedInteger) 533 $(LREF isNumeric) 534 $(LREF isUnsignedInteger) 535 +/ 536 enum isInteger(T) = is(immutable T == immutable byte) || 537 is(immutable T == immutable ubyte) || 538 is(immutable T == immutable short) || 539 is(immutable T == immutable ushort) || 540 is(immutable T == immutable int) || 541 is(immutable T == immutable uint) || 542 is(immutable T == immutable long) || 543 is(immutable T == immutable ulong); 544 545 /// 546 @safe unittest 547 { 548 // Some types which are integer types. 549 static assert( isInteger!byte); 550 static assert( isInteger!ubyte); 551 static assert( isInteger!short); 552 static assert( isInteger!ushort); 553 static assert( isInteger!int); 554 static assert( isInteger!uint); 555 static assert( isInteger!long); 556 static assert( isInteger!ulong); 557 558 static assert( isInteger!(const ubyte)); 559 static assert( isInteger!(immutable short)); 560 static assert( isInteger!(inout int)); 561 static assert( isInteger!(shared uint)); 562 static assert( isInteger!(const shared ulong)); 563 564 static assert( isInteger!(typeof(42))); 565 static assert( isInteger!(typeof(1234567890L))); 566 567 int i; 568 static assert( isInteger!(typeof(i))); 569 570 // Some types which aren't integer types. 571 static assert(!isInteger!bool); 572 static assert(!isInteger!char); 573 static assert(!isInteger!wchar); 574 static assert(!isInteger!dchar); 575 static assert(!isInteger!(int[])); 576 static assert(!isInteger!(ubyte[4])); 577 static assert(!isInteger!(int*)); 578 static assert(!isInteger!double); 579 static assert(!isInteger!string); 580 581 static struct S 582 { 583 int i; 584 } 585 static assert(!isInteger!S); 586 587 // The struct itself isn't considered an integer, 588 // but its member variable is when checked directly. 589 static assert( isInteger!(typeof(S.i))); 590 591 enum E : int 592 { 593 a = 42 594 } 595 596 // Enums do not count. 597 static assert(!isInteger!E); 598 599 static struct AliasThis 600 { 601 int i; 602 alias this = i; 603 } 604 605 // Other implicit conversions do not count. 606 static assert(!isInteger!AliasThis); 607 } 608 609 @safe unittest 610 { 611 import phobos.sys.meta : Alias, AliasSeq; 612 613 static struct AliasThis(T) 614 { 615 T member; 616 alias this = member; 617 } 618 619 // The actual core.simd types available vary from system to system, so we 620 // have to be a bit creative here. The reason that we're testing these types 621 // is because __traits(isIntegral, T) accepts them, but isInteger is not 622 // supposed to. 623 template SIMDTypes() 624 { 625 import core.simd; 626 627 alias SIMDTypes = AliasSeq!(); 628 static if (is(ubyte16)) 629 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 630 static if (is(int4)) 631 SIMDTypes = AliasSeq!(SIMDTypes, int4); 632 static if (is(double2)) 633 SIMDTypes = AliasSeq!(SIMDTypes, double2); 634 static if (is(void16)) 635 SIMDTypes = AliasSeq!(SIMDTypes, void16); 636 } 637 638 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 639 { 640 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong)) 641 { 642 enum E : Q!T { a = Q!T.init } 643 644 static assert( isInteger!(Q!T)); 645 static assert(!isInteger!E); 646 static assert(!isInteger!(AliasThis!(Q!T))); 647 } 648 649 foreach (T; AliasSeq!(bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 650 int[], ubyte[8], dchar[], void[], long*)) 651 { 652 enum E : Q!T { a = Q!T.init } 653 654 static assert(!isInteger!(Q!T)); 655 static assert(!isInteger!E); 656 static assert(!isInteger!(AliasThis!(Q!T))); 657 } 658 } 659 } 660 661 /++ 662 Whether the given type is one of the built-in signed integer types, ignoring 663 all qualifiers. 664 665 $(TABLE 666 $(TR $(TH Signed Integer Types)) 667 $(TR $(TD byte)) 668 $(TR $(TD short)) 669 $(TR $(TD int)) 670 $(TR $(TD long)) 671 ) 672 673 Note that this does not include implicit conversions or enum types. The 674 type itself must be one of the built-in signed integer types. 675 676 See also: 677 $(LREF isFloatingPoint) 678 $(LREF isInteger) 679 $(LREF isNumeric) 680 $(LREF isUnsignedInteger) 681 +/ 682 enum isSignedInteger(T) = is(immutable T == immutable byte) || 683 is(immutable T == immutable short) || 684 is(immutable T == immutable int) || 685 is(immutable T == immutable long); 686 687 /// 688 @safe unittest 689 { 690 // Some types which are signed integer types. 691 static assert( isSignedInteger!byte); 692 static assert( isSignedInteger!short); 693 static assert( isSignedInteger!int); 694 static assert( isSignedInteger!long); 695 696 static assert( isSignedInteger!(const byte)); 697 static assert( isSignedInteger!(immutable short)); 698 static assert( isSignedInteger!(inout int)); 699 static assert( isSignedInteger!(shared int)); 700 static assert( isSignedInteger!(const shared long)); 701 702 static assert( isSignedInteger!(typeof(42))); 703 static assert( isSignedInteger!(typeof(1234567890L))); 704 705 int i; 706 static assert( isSignedInteger!(typeof(i))); 707 708 // Some types which aren't signed integer types. 709 static assert(!isSignedInteger!ubyte); 710 static assert(!isSignedInteger!ushort); 711 static assert(!isSignedInteger!uint); 712 static assert(!isSignedInteger!ulong); 713 714 static assert(!isSignedInteger!bool); 715 static assert(!isSignedInteger!char); 716 static assert(!isSignedInteger!wchar); 717 static assert(!isSignedInteger!dchar); 718 static assert(!isSignedInteger!(int[])); 719 static assert(!isSignedInteger!(ubyte[4])); 720 static assert(!isSignedInteger!(int*)); 721 static assert(!isSignedInteger!double); 722 static assert(!isSignedInteger!string); 723 724 static struct S 725 { 726 int i; 727 } 728 static assert(!isSignedInteger!S); 729 730 // The struct itself isn't considered a signed integer, 731 // but its member variable is when checked directly. 732 static assert( isSignedInteger!(typeof(S.i))); 733 734 enum E : int 735 { 736 a = 42 737 } 738 739 // Enums do not count. 740 static assert(!isSignedInteger!E); 741 742 static struct AliasThis 743 { 744 int i; 745 alias this = i; 746 } 747 748 // Other implicit conversions do not count. 749 static assert(!isSignedInteger!AliasThis); 750 } 751 752 @safe unittest 753 { 754 import phobos.sys.meta : Alias, AliasSeq; 755 756 static struct AliasThis(T) 757 { 758 T member; 759 alias this = member; 760 } 761 762 // The actual core.simd types available vary from system to system, so we 763 // have to be a bit creative here. The reason that we're testing these types 764 // is because __traits(isIntegral, T) accepts them, but isSignedInteger is 765 // not supposed to. 766 template SIMDTypes() 767 { 768 import core.simd; 769 770 alias SIMDTypes = AliasSeq!(); 771 static if (is(ubyte16)) 772 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 773 static if (is(int4)) 774 SIMDTypes = AliasSeq!(SIMDTypes, int4); 775 static if (is(double2)) 776 SIMDTypes = AliasSeq!(SIMDTypes, double2); 777 static if (is(void16)) 778 SIMDTypes = AliasSeq!(SIMDTypes, void16); 779 } 780 781 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 782 { 783 foreach (T; AliasSeq!(byte, short, int, long)) 784 { 785 enum E : Q!T { a = Q!T.init } 786 787 static assert( isSignedInteger!(Q!T)); 788 static assert(!isSignedInteger!E); 789 static assert(!isSignedInteger!(AliasThis!(Q!T))); 790 } 791 792 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, 793 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 794 int[], ubyte[8], dchar[], void[], long*)) 795 { 796 enum E : Q!T { a = Q!T.init } 797 798 static assert(!isSignedInteger!(Q!T)); 799 static assert(!isSignedInteger!E); 800 static assert(!isSignedInteger!(AliasThis!(Q!T))); 801 } 802 } 803 } 804 805 /++ 806 Whether the given type is one of the built-in unsigned integer types, 807 ignoring all qualifiers. 808 809 $(TABLE 810 $(TR $(TH Integer Types)) 811 $(TR $(TD ubyte)) 812 $(TR $(TD ushort)) 813 $(TR $(TD uint)) 814 $(TR $(TD ulong)) 815 ) 816 817 Note that this does not include implicit conversions or enum types. The 818 type itself must be one of the built-in unsigned integer types. 819 820 This trait does have some similarities with $(D __traits(isUnsigned, T)), 821 but $(D isUnsigned) accepts a $(I lot) more types than isUnsignedInteger 822 does. isUnsignedInteger is specifically for testing for the built-in 823 unsigned integer types, whereas $(D isUnsigned) tests for a whole set of 824 types that are unsigned and vaguely integer-like (including $(D bool), the 825 three built-in character types, and some of the vector types from 826 core.simd). So, for most code, isUnsignedInteger is going to be more 827 appropriate, but obviously, it depends on what the code is trying to do. 828 829 See also: 830 $(DDSUBLINK spec/traits, isUnsigned, $(D __traits(isUnsigned, T))) 831 $(LREF isFloatingPoint) 832 $(LREF isInteger) 833 $(LREF isSignedInteger) 834 $(LREF isNumeric) 835 +/ 836 enum isUnsignedInteger(T) = is(immutable T == immutable ubyte) || 837 is(immutable T == immutable ushort) || 838 is(immutable T == immutable uint) || 839 is(immutable T == immutable ulong); 840 841 /// 842 @safe unittest 843 { 844 // Some types which are unsigned integer types. 845 static assert( isUnsignedInteger!ubyte); 846 static assert( isUnsignedInteger!ushort); 847 static assert( isUnsignedInteger!uint); 848 static assert( isUnsignedInteger!ulong); 849 850 static assert( isUnsignedInteger!(const ubyte)); 851 static assert( isUnsignedInteger!(immutable ushort)); 852 static assert( isUnsignedInteger!(inout uint)); 853 static assert( isUnsignedInteger!(shared uint)); 854 static assert( isUnsignedInteger!(const shared ulong)); 855 856 static assert( isUnsignedInteger!(typeof(42u))); 857 static assert( isUnsignedInteger!(typeof(1234567890UL))); 858 859 uint u; 860 static assert( isUnsignedInteger!(typeof(u))); 861 862 // Some types which aren't unsigned integer types. 863 static assert(!isUnsignedInteger!byte); 864 static assert(!isUnsignedInteger!short); 865 static assert(!isUnsignedInteger!int); 866 static assert(!isUnsignedInteger!long); 867 868 static assert(!isUnsignedInteger!bool); 869 static assert(!isUnsignedInteger!char); 870 static assert(!isUnsignedInteger!wchar); 871 static assert(!isUnsignedInteger!dchar); 872 static assert(!isUnsignedInteger!(int[])); 873 static assert(!isUnsignedInteger!(ubyte[4])); 874 static assert(!isUnsignedInteger!(int*)); 875 static assert(!isUnsignedInteger!double); 876 static assert(!isUnsignedInteger!string); 877 878 static struct S 879 { 880 uint u; 881 } 882 static assert(!isUnsignedInteger!S); 883 884 // The struct itself isn't considered an unsigned integer, 885 // but its member variable is when checked directly. 886 static assert( isUnsignedInteger!(typeof(S.u))); 887 888 enum E : uint 889 { 890 a = 42 891 } 892 893 // Enums do not count. 894 static assert(!isUnsignedInteger!E); 895 896 static struct AliasThis 897 { 898 uint u; 899 alias this = u; 900 } 901 902 // Other implicit conversions do not count. 903 static assert(!isUnsignedInteger!AliasThis); 904 } 905 906 @safe unittest 907 { 908 import phobos.sys.meta : Alias, AliasSeq; 909 910 static struct AliasThis(T) 911 { 912 T member; 913 alias this = member; 914 } 915 916 // The actual core.simd types available vary from system to system, so we 917 // have to be a bit creative here. The reason that we're testing these types 918 // is because __traits(isIntegral, T) and __traits(isUnsigned, T) accept 919 // them, but isUnsignedInteger is not supposed to. 920 template SIMDTypes() 921 { 922 import core.simd; 923 924 alias SIMDTypes = AliasSeq!(); 925 static if (is(ubyte16)) 926 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 927 static if (is(int4)) 928 SIMDTypes = AliasSeq!(SIMDTypes, int4); 929 static if (is(double2)) 930 SIMDTypes = AliasSeq!(SIMDTypes, double2); 931 static if (is(void16)) 932 SIMDTypes = AliasSeq!(SIMDTypes, void16); 933 } 934 935 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 936 { 937 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong)) 938 { 939 enum E : Q!T { a = Q!T.init } 940 941 static assert( isUnsignedInteger!(Q!T)); 942 static assert(!isUnsignedInteger!E); 943 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 944 } 945 946 foreach (T; AliasSeq!(byte, short, int, long, 947 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 948 int[], ubyte[8], dchar[], void[], long*)) 949 { 950 enum E : Q!T { a = Q!T.init } 951 952 static assert(!isUnsignedInteger!(Q!T)); 953 static assert(!isUnsignedInteger!E); 954 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 955 } 956 } 957 } 958 959 /++ 960 Whether the given type is one of the built-in floating-point types, ignoring 961 all qualifiers. 962 963 $(TABLE 964 $(TR $(TH Floating-Point Types)) 965 $(TR $(TD float)) 966 $(TR $(TD double)) 967 $(TR $(TD real)) 968 ) 969 970 Note that this does not include implicit conversions or enum types. The 971 type itself must be one of the built-in floating-point types. 972 973 This trait does have some similarities with $(D __traits(isFloating, T)), 974 but $(D isFloating) accepts more types than isFloatingPoint does. 975 isFloatingPoint is specifically for testing for the built-in floating-point 976 types, whereas $(D isFloating) tests for a whole set of types that are 977 vaguely float-like (including enums with a base type which is a 978 floating-point type and some of the vector types from core.simd). So, for 979 most code, isFloatingPoint is going to be more appropriate, but obviously, 980 it depends on what the code is trying to do. 981 982 See also: 983 $(DDSUBLINK spec/traits, isFloating, $(D __traits(isFloating, T))) 984 $(LREF isInteger) 985 $(LREF isSignedInteger) 986 $(LREF isNumeric) 987 $(LREF isUnsignedInteger) 988 +/ 989 enum isFloatingPoint(T) = is(immutable T == immutable float) || 990 is(immutable T == immutable double) || 991 is(immutable T == immutable real); 992 993 /// 994 @safe unittest 995 { 996 // Some types which are floating-point types. 997 static assert( isFloatingPoint!float); 998 static assert( isFloatingPoint!double); 999 static assert( isFloatingPoint!real); 1000 1001 static assert( isFloatingPoint!(const float)); 1002 static assert( isFloatingPoint!(immutable float)); 1003 static assert( isFloatingPoint!(inout double)); 1004 static assert( isFloatingPoint!(shared double)); 1005 static assert( isFloatingPoint!(const shared real)); 1006 1007 static assert( isFloatingPoint!(typeof(42.0))); 1008 static assert( isFloatingPoint!(typeof(42f))); 1009 static assert( isFloatingPoint!(typeof(1e5))); 1010 static assert( isFloatingPoint!(typeof(97.4L))); 1011 1012 double d; 1013 static assert( isFloatingPoint!(typeof(d))); 1014 1015 // Some types which aren't floating-point types. 1016 static assert(!isFloatingPoint!bool); 1017 static assert(!isFloatingPoint!char); 1018 static assert(!isFloatingPoint!dchar); 1019 static assert(!isFloatingPoint!int); 1020 static assert(!isFloatingPoint!long); 1021 static assert(!isFloatingPoint!(float[])); 1022 static assert(!isFloatingPoint!(double[4])); 1023 static assert(!isFloatingPoint!(real*)); 1024 static assert(!isFloatingPoint!string); 1025 1026 static struct S 1027 { 1028 double d; 1029 } 1030 static assert(!isFloatingPoint!S); 1031 1032 // The struct itself isn't considered a floating-point type, 1033 // but its member variable is when checked directly. 1034 static assert( isFloatingPoint!(typeof(S.d))); 1035 1036 enum E : double 1037 { 1038 a = 12.34 1039 } 1040 1041 // Enums do not count. 1042 static assert(!isFloatingPoint!E); 1043 1044 static struct AliasThis 1045 { 1046 double d; 1047 alias this = d; 1048 } 1049 1050 // Other implicit conversions do not count. 1051 static assert(!isFloatingPoint!AliasThis); 1052 } 1053 1054 @safe unittest 1055 { 1056 import phobos.sys.meta : Alias, AliasSeq; 1057 1058 static struct AliasThis(T) 1059 { 1060 T member; 1061 alias this = member; 1062 } 1063 1064 // The actual core.simd types available vary from system to system, so we 1065 // have to be a bit creative here. The reason that we're testing these types 1066 // is because __traits(isFloating, T) accepts them, but isFloatingPoint is 1067 // not supposed to. 1068 template SIMDTypes() 1069 { 1070 import core.simd; 1071 1072 alias SIMDTypes = AliasSeq!(); 1073 static if (is(int4)) 1074 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1075 static if (is(double2)) 1076 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1077 static if (is(void16)) 1078 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1079 } 1080 1081 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1082 { 1083 foreach (T; AliasSeq!(float, double, real)) 1084 { 1085 enum E : Q!T { a = Q!T.init } 1086 1087 static assert( isFloatingPoint!(Q!T)); 1088 static assert(!isFloatingPoint!E); 1089 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1090 } 1091 1092 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, ubyte, short, ushort, 1093 int, uint, long, ulong, SIMDTypes!(), 1094 int[], float[8], real[], void[], double*)) 1095 { 1096 enum E : Q!T { a = Q!T.init } 1097 1098 static assert(!isFloatingPoint!(Q!T)); 1099 static assert(!isFloatingPoint!E); 1100 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1101 } 1102 } 1103 } 1104 1105 /++ 1106 Whether the given type is one of the built-in numeric types, ignoring all 1107 qualifiers. It's equivalent to $(D isInteger!T || isFloatingPoint!T), but 1108 it only involves a single template instantation instead of two. 1109 1110 $(TABLE 1111 $(TR $(TH Numeric Types)) 1112 $(TR $(TD byte)) 1113 $(TR $(TD ubyte)) 1114 $(TR $(TD short)) 1115 $(TR $(TD ushort)) 1116 $(TR $(TD int)) 1117 $(TR $(TD uint)) 1118 $(TR $(TD long)) 1119 $(TR $(TD ulong)) 1120 $(TR $(TD float)) 1121 $(TR $(TD double)) 1122 $(TR $(TD real)) 1123 ) 1124 1125 Note that this does not include implicit conversions or enum types. The 1126 type itself must be one of the built-in numeric types. 1127 1128 See_Also: 1129 $(LREF isFloatingPoint) 1130 $(LREF isInteger) 1131 $(LREF isSignedInteger) 1132 $(LREF isUnsignedInteger) 1133 +/ 1134 enum isNumeric(T) = is(immutable T == immutable byte) || 1135 is(immutable T == immutable ubyte) || 1136 is(immutable T == immutable short) || 1137 is(immutable T == immutable ushort) || 1138 is(immutable T == immutable int) || 1139 is(immutable T == immutable uint) || 1140 is(immutable T == immutable long) || 1141 is(immutable T == immutable ulong) || 1142 is(immutable T == immutable float) || 1143 is(immutable T == immutable double) || 1144 is(immutable T == immutable real); 1145 1146 /// 1147 @safe unittest 1148 { 1149 // Some types which are numeric types. 1150 static assert( isNumeric!byte); 1151 static assert( isNumeric!ubyte); 1152 static assert( isNumeric!short); 1153 static assert( isNumeric!ushort); 1154 static assert( isNumeric!int); 1155 static assert( isNumeric!uint); 1156 static assert( isNumeric!long); 1157 static assert( isNumeric!ulong); 1158 static assert( isNumeric!float); 1159 static assert( isNumeric!double); 1160 static assert( isNumeric!real); 1161 1162 static assert( isNumeric!(const short)); 1163 static assert( isNumeric!(immutable int)); 1164 static assert( isNumeric!(inout uint)); 1165 static assert( isNumeric!(shared long)); 1166 static assert( isNumeric!(const shared real)); 1167 1168 static assert( isNumeric!(typeof(42))); 1169 static assert( isNumeric!(typeof(1234657890L))); 1170 static assert( isNumeric!(typeof(42.0))); 1171 static assert( isNumeric!(typeof(42f))); 1172 static assert( isNumeric!(typeof(1e5))); 1173 static assert( isNumeric!(typeof(97.4L))); 1174 1175 int i; 1176 static assert( isNumeric!(typeof(i))); 1177 1178 // Some types which aren't numeric types. 1179 static assert(!isNumeric!bool); 1180 static assert(!isNumeric!char); 1181 static assert(!isNumeric!dchar); 1182 static assert(!isNumeric!(int[])); 1183 static assert(!isNumeric!(double[4])); 1184 static assert(!isNumeric!(real*)); 1185 static assert(!isNumeric!string); 1186 1187 static struct S 1188 { 1189 int i; 1190 } 1191 static assert(!isNumeric!S); 1192 1193 // The struct itself isn't considered a numeric type, 1194 // but its member variable is when checked directly. 1195 static assert( isNumeric!(typeof(S.i))); 1196 1197 enum E : int 1198 { 1199 a = 42 1200 } 1201 1202 // Enums do not count. 1203 static assert(!isNumeric!E); 1204 1205 static struct AliasThis 1206 { 1207 int i; 1208 alias this = i; 1209 } 1210 1211 // Other implicit conversions do not count. 1212 static assert(!isNumeric!AliasThis); 1213 } 1214 1215 @safe unittest 1216 { 1217 import phobos.sys.meta : Alias, AliasSeq; 1218 1219 static struct AliasThis(T) 1220 { 1221 T member; 1222 alias this = member; 1223 } 1224 1225 // The actual core.simd types available vary from system to system, so we 1226 // have to be a bit creative here. The reason that we're testing these types 1227 // is because __traits(isInteger, T) and __traits(isFloating, T) accept 1228 // them, but isNumeric is not supposed to. 1229 template SIMDTypes() 1230 { 1231 import core.simd; 1232 1233 alias SIMDTypes = AliasSeq!(); 1234 static if (is(int4)) 1235 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1236 static if (is(double2)) 1237 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1238 static if (is(void16)) 1239 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1240 } 1241 1242 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1243 { 1244 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real)) 1245 { 1246 enum E : Q!T { a = Q!T.init } 1247 1248 static assert( isNumeric!(Q!T)); 1249 static assert(!isNumeric!E); 1250 static assert(!isNumeric!(AliasThis!(Q!T))); 1251 } 1252 1253 foreach (T; AliasSeq!(bool, char, wchar, dchar, SIMDTypes!(), 1254 int[], float[8], real[], void[], double*)) 1255 { 1256 enum E : Q!T { a = Q!T.init } 1257 1258 static assert(!isNumeric!(Q!T)); 1259 static assert(!isNumeric!E); 1260 static assert(!isNumeric!(AliasThis!(Q!T))); 1261 } 1262 } 1263 } 1264 1265 /++ 1266 Whether the given type is a pointer. 1267 1268 Note that this does not include implicit conversions or enum types. The 1269 type itself must be a pointer. 1270 1271 Also, remember that unlike C/C++, D's arrays are not pointers. Rather, a 1272 dynamic array in D is a slice of memory which has a member which is a 1273 pointer to its first element and another member which is the length of the 1274 array as $(D size_t). So, a dynamic array / slice has a $(D ptr) member 1275 which is a pointer, but the dynamic array itself is not a pointer. 1276 1277 See_Also: 1278 $(LREF isDynamicArray) 1279 +/ 1280 enum isPointer(T) = is(T == U*, U); 1281 1282 /// 1283 @system unittest 1284 { 1285 // Some types which are pointers. 1286 static assert( isPointer!(bool*)); 1287 static assert( isPointer!(int*)); 1288 static assert( isPointer!(int**)); 1289 static assert( isPointer!(real*)); 1290 static assert( isPointer!(string*)); 1291 1292 static assert( isPointer!(const int*)); 1293 static assert( isPointer!(immutable int*)); 1294 static assert( isPointer!(inout int*)); 1295 static assert( isPointer!(shared int*)); 1296 static assert( isPointer!(const shared int*)); 1297 1298 static assert( isPointer!(typeof("foobar".ptr))); 1299 1300 int* ptr; 1301 static assert( isPointer!(typeof(ptr))); 1302 1303 int i; 1304 static assert( isPointer!(typeof(&i))); 1305 1306 // Some types which aren't pointers. 1307 static assert(!isPointer!bool); 1308 static assert(!isPointer!int); 1309 static assert(!isPointer!dchar); 1310 static assert(!isPointer!(int[])); 1311 static assert(!isPointer!(double[4])); 1312 static assert(!isPointer!string); 1313 1314 static struct S 1315 { 1316 int* ptr; 1317 } 1318 static assert(!isPointer!S); 1319 1320 // The struct itself isn't considered a numeric type, 1321 // but its member variable is when checked directly. 1322 static assert( isPointer!(typeof(S.ptr))); 1323 1324 enum E : immutable(char*) 1325 { 1326 a = "foobar".ptr 1327 } 1328 1329 // Enums do not count. 1330 static assert(!isPointer!E); 1331 1332 static struct AliasThis 1333 { 1334 int* ptr; 1335 alias this = ptr; 1336 } 1337 1338 // Other implicit conversions do not count. 1339 static assert(!isPointer!AliasThis); 1340 } 1341 1342 @safe unittest 1343 { 1344 import phobos.sys.meta : Alias, AliasSeq; 1345 1346 static struct AliasThis(T) 1347 { 1348 T member; 1349 alias this = member; 1350 } 1351 1352 static struct S 1353 { 1354 int i; 1355 } 1356 1357 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1358 { 1359 foreach (T; AliasSeq!(long*, S*, S**, S***, double[]*)) 1360 { 1361 enum E : Q!T { a = Q!T.init } 1362 1363 static assert( isPointer!(Q!T)); 1364 static assert(!isPointer!E); 1365 static assert(!isPointer!(AliasThis!(Q!T))); 1366 } 1367 1368 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, int, uint, long, 1369 int[], float[8], real[], void[])) 1370 { 1371 enum E : Q!T { a = Q!T.init } 1372 1373 static assert(!isPointer!(Q!T)); 1374 static assert(!isPointer!E); 1375 static assert(!isPointer!(AliasThis!(Q!T))); 1376 } 1377 } 1378 } 1379 1380 /++ 1381 Evaluates to $(D true) if given a type and $(D false) for all other symbols. 1382 1383 This is equivalent to $(D is(T)), but some people may find using a named 1384 trait to be clearer, and it can be used in conjunction with templates that 1385 take a template predicate (such as those in phobos.sys.meta), which can't 1386 be done with naked is expressions. 1387 1388 See_Also: 1389 $(DDSUBLINK dlang.org/spec/expression.html, is-type, Spec on the related is expression) 1390 +/ 1391 enum isType(T) = true; 1392 1393 /// Ditto 1394 enum isType(alias sym) = false; 1395 1396 /// 1397 @safe unittest 1398 { 1399 static assert( isType!int); 1400 static assert( isType!(int[])); 1401 static assert( isType!string); 1402 static assert( isType!(int[int])); 1403 static assert( isType!(ubyte*)); 1404 static assert( isType!void); 1405 1406 int i; 1407 static assert(!isType!i); 1408 static assert( isType!(typeof(i))); 1409 1410 struct S {} 1411 static assert( isType!S); 1412 static assert(!isType!(S.init)); 1413 1414 class C {} 1415 static assert( isType!C); 1416 static assert(!isType!(C.init)); 1417 1418 interface I {} 1419 static assert( isType!I); 1420 static assert(!isType!(I.init)); 1421 1422 union U {} 1423 static assert( isType!U); 1424 static assert(!isType!(U.init)); 1425 1426 static void func() {} 1427 static assert(!isType!func); 1428 static assert( isType!(typeof(func))); 1429 1430 void funcWithContext() { ++i; } 1431 static assert(!isType!funcWithContext); 1432 static assert( isType!(typeof(funcWithContext))); 1433 1434 int function() funcPtr; 1435 static assert(!isType!funcPtr); 1436 static assert( isType!(typeof(funcPtr))); 1437 1438 int delegate() del; 1439 static assert(!isType!del); 1440 static assert( isType!(typeof(del))); 1441 1442 template Templ() {} 1443 static assert(!isType!Templ); 1444 static assert(!isType!(Templ!())); 1445 1446 template TemplWithType() 1447 { 1448 struct S {} 1449 } 1450 static assert(!isType!TemplWithType); 1451 static assert(!isType!(TemplWithType!())); 1452 static assert( isType!(TemplWithType!().S)); 1453 1454 struct TemplType() {} 1455 static assert(!isType!TemplType); 1456 static assert( isType!(TemplType!())); 1457 } 1458 1459 /++ 1460 Evaluates to $(D true) if the given type or symbol is an instantiation of 1461 the given template. 1462 1463 The overload which takes $(D T) operates on types and indicates whether an 1464 aggregate type (i.e. struct, class, interface, or union) is an 1465 instantiation of the given template. 1466 1467 The overload which takes $(D Symbol) operates on function templates, 1468 because unlike with aggregate types, the type of a function does not retain 1469 the fact that it was instantiated from a template. So, for functions, it's 1470 necessary to pass the function itself as a symbol rather than pass the type 1471 of the function. 1472 1473 The overload which takes $(D Symbol) also works with templates which are 1474 not types or functions. 1475 1476 The single-argument overload makes it so that it can be partially 1477 instantiated with the first argument, which will often be necessary with 1478 template predicates. 1479 +/ 1480 template isInstantiationOf(alias Template, T) 1481 if (__traits(isTemplate, Template)) 1482 { 1483 enum isInstantiationOf = is(T == Template!Args, Args...); 1484 } 1485 1486 /++ Ditto +/ 1487 template isInstantiationOf(alias Template, alias Symbol) 1488 if (__traits(isTemplate, Template)) 1489 { 1490 enum impl(alias T : Template!Args, Args...) = true; 1491 enum impl(alias T) = false; 1492 enum isInstantiationOf = impl!Symbol; 1493 } 1494 1495 /++ Ditto +/ 1496 template isInstantiationOf(alias Template) 1497 if (__traits(isTemplate, Template)) 1498 { 1499 enum isInstantiationOf(T) = is(T == Template!Args, Args...); 1500 1501 template isInstantiationOf(alias Symbol) 1502 { 1503 enum impl(alias T : Template!Args, Args...) = true; 1504 enum impl(alias T) = false; 1505 enum isInstantiationOf = impl!Symbol; 1506 } 1507 } 1508 1509 /// Examples of templated types. 1510 @safe unittest 1511 { 1512 static struct S(T) {} 1513 static class C(T) {} 1514 1515 static assert( isInstantiationOf!(S, S!int)); 1516 static assert( isInstantiationOf!(S, S!int)); 1517 static assert( isInstantiationOf!(S, S!string)); 1518 static assert( isInstantiationOf!(S, const S!string)); 1519 static assert( isInstantiationOf!(S, shared S!string)); 1520 static assert(!isInstantiationOf!(S, int)); 1521 static assert(!isInstantiationOf!(S, C!int)); 1522 static assert(!isInstantiationOf!(S, C!string)); 1523 static assert(!isInstantiationOf!(S, C!(S!int))); 1524 1525 static assert( isInstantiationOf!(C, C!int)); 1526 static assert( isInstantiationOf!(C, C!string)); 1527 static assert( isInstantiationOf!(C, const C!string)); 1528 static assert( isInstantiationOf!(C, shared C!string)); 1529 static assert(!isInstantiationOf!(C, int)); 1530 static assert(!isInstantiationOf!(C, S!int)); 1531 static assert(!isInstantiationOf!(C, S!string)); 1532 static assert(!isInstantiationOf!(C, S!(C!int))); 1533 1534 static struct Variadic(T...) {} 1535 1536 static assert( isInstantiationOf!(Variadic, Variadic!())); 1537 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1538 static assert( isInstantiationOf!(Variadic, Variadic!(int, string))); 1539 static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int))); 1540 static assert( isInstantiationOf!(Variadic, const Variadic!(int, short))); 1541 static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short))); 1542 static assert(!isInstantiationOf!(Variadic, int)); 1543 static assert(!isInstantiationOf!(Variadic, S!int)); 1544 static assert(!isInstantiationOf!(Variadic, C!int)); 1545 1546 static struct ValueArg(int i) {} 1547 static assert( isInstantiationOf!(ValueArg, ValueArg!42)); 1548 static assert( isInstantiationOf!(ValueArg, ValueArg!256)); 1549 static assert( isInstantiationOf!(ValueArg, const ValueArg!1024)); 1550 static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024)); 1551 static assert(!isInstantiationOf!(ValueArg, int)); 1552 static assert(!isInstantiationOf!(ValueArg, S!int)); 1553 1554 int i; 1555 1556 static struct AliasArg(alias Symbol) {} 1557 static assert( isInstantiationOf!(AliasArg, AliasArg!42)); 1558 static assert( isInstantiationOf!(AliasArg, AliasArg!int)); 1559 static assert( isInstantiationOf!(AliasArg, AliasArg!i)); 1560 static assert( isInstantiationOf!(AliasArg, const AliasArg!i)); 1561 static assert( isInstantiationOf!(AliasArg, shared AliasArg!i)); 1562 static assert(!isInstantiationOf!(AliasArg, int)); 1563 static assert(!isInstantiationOf!(AliasArg, S!int)); 1564 1565 // An uninstantiated template is not an instance of any template, 1566 // not even itself. 1567 static assert(!isInstantiationOf!(S, S)); 1568 static assert(!isInstantiationOf!(S, C)); 1569 static assert(!isInstantiationOf!(C, C)); 1570 static assert(!isInstantiationOf!(C, S)); 1571 1572 // Variables of a templated type are not considered instantiations of that 1573 // type. For templated types, the overload which takes a type must be used. 1574 S!int s; 1575 C!string c; 1576 static assert(!isInstantiationOf!(S, s)); 1577 static assert(!isInstantiationOf!(C, c)); 1578 } 1579 1580 // Examples of templated functions. 1581 @safe unittest 1582 { 1583 static int foo(T...)() { return 42; } 1584 static void bar(T...)(T var) {} 1585 static void baz(T)(T var) {} 1586 static bool frobozz(alias pred)(int) { return true; } 1587 1588 static assert( isInstantiationOf!(foo, foo!int)); 1589 static assert( isInstantiationOf!(foo, foo!string)); 1590 static assert( isInstantiationOf!(foo, foo!(int, string))); 1591 static assert(!isInstantiationOf!(foo, bar!int)); 1592 static assert(!isInstantiationOf!(foo, bar!string)); 1593 static assert(!isInstantiationOf!(foo, bar!(int, string))); 1594 1595 static assert( isInstantiationOf!(bar, bar!int)); 1596 static assert( isInstantiationOf!(bar, bar!string)); 1597 static assert( isInstantiationOf!(bar, bar!(int, string))); 1598 static assert(!isInstantiationOf!(bar, foo!int)); 1599 static assert(!isInstantiationOf!(bar, foo!string)); 1600 static assert(!isInstantiationOf!(bar, foo!(int, string))); 1601 1602 static assert( isInstantiationOf!(baz, baz!int)); 1603 static assert( isInstantiationOf!(baz, baz!string)); 1604 static assert(!isInstantiationOf!(baz, foo!(int, string))); 1605 1606 static assert( isInstantiationOf!(frobozz, frobozz!(a => a))); 1607 static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2))); 1608 static assert(!isInstantiationOf!(frobozz, baz!int)); 1609 1610 // Unfortunately, the function type is not considered an instantiation of 1611 // the template, because that information is not part of the type, unlike 1612 // with templated structs or classes. 1613 static assert(!isInstantiationOf!(foo, typeof(foo!int))); 1614 static assert(!isInstantiationOf!(bar, typeof(bar!int))); 1615 } 1616 1617 // Examples of templates which aren't types or functions. 1618 @safe unittest 1619 { 1620 template SingleArg(T) {} 1621 template Variadic(T...) {} 1622 template ValueArg(string s) {} 1623 template Alias(alias symbol) {} 1624 1625 static assert( isInstantiationOf!(SingleArg, SingleArg!int)); 1626 static assert( isInstantiationOf!(SingleArg, SingleArg!string)); 1627 static assert(!isInstantiationOf!(SingleArg, int)); 1628 static assert(!isInstantiationOf!(SingleArg, Variadic!int)); 1629 1630 static assert( isInstantiationOf!(Variadic, Variadic!())); 1631 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1632 static assert( isInstantiationOf!(Variadic, Variadic!string)); 1633 static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long))); 1634 static assert(!isInstantiationOf!(Variadic, int)); 1635 static assert(!isInstantiationOf!(Variadic, SingleArg!int)); 1636 1637 static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang")); 1638 static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar")); 1639 static assert(!isInstantiationOf!(ValueArg, string)); 1640 static assert(!isInstantiationOf!(ValueArg, Variadic!string)); 1641 1642 int i; 1643 1644 static assert( isInstantiationOf!(Alias, Alias!int)); 1645 static assert( isInstantiationOf!(Alias, Alias!42)); 1646 static assert( isInstantiationOf!(Alias, Alias!i)); 1647 static assert(!isInstantiationOf!(Alias, int)); 1648 static assert(!isInstantiationOf!(Alias, SingleArg!int)); 1649 } 1650 1651 /// Examples of partial instantation. 1652 @safe unittest 1653 { 1654 static struct SingleArg(T) {} 1655 static struct Variadic(T...) {} 1656 1657 alias isSingleArg = isInstantiationOf!SingleArg; 1658 alias isVariadic = isInstantiationOf!Variadic; 1659 1660 static assert( isSingleArg!(SingleArg!int)); 1661 static assert( isSingleArg!(const SingleArg!int)); 1662 static assert(!isSingleArg!int); 1663 static assert(!isSingleArg!(Variadic!int)); 1664 1665 static assert( isVariadic!(Variadic!())); 1666 static assert( isVariadic!(Variadic!int)); 1667 static assert( isVariadic!(shared Variadic!int)); 1668 static assert( isVariadic!(Variadic!(int, string))); 1669 static assert(!isVariadic!int); 1670 static assert(!isVariadic!(SingleArg!int)); 1671 1672 T foo(T)(T t) { return t; } 1673 T likeFoo(T)(T t) { return t; } 1674 bool bar(alias pred)(int i) { return pred(i); } 1675 1676 alias isFoo = isInstantiationOf!foo; 1677 alias isBar = isInstantiationOf!bar; 1678 1679 static assert( isFoo!(foo!int)); 1680 static assert( isFoo!(foo!string)); 1681 static assert(!isFoo!int); 1682 static assert(!isFoo!(likeFoo!int)); 1683 static assert(!isFoo!(bar!(a => true))); 1684 1685 static assert( isBar!(bar!(a => true))); 1686 static assert( isBar!(bar!(a => a > 2))); 1687 static assert(!isBar!int); 1688 static assert(!isBar!(foo!int)); 1689 static assert(!isBar!(likeFoo!int)); 1690 } 1691 1692 /++ 1693 Evaluates to the default-initialized value of the given type. 1694 1695 defaultInit should be used in generic code in contexts where the 1696 default-initialized value of a type is needed rather than that type's 1697 $(D init) value. 1698 1699 For most types, the default-initialized value of a type $(I is) its 1700 $(D init) value - i.e. for some type, $(D T), it would normally be 1701 $(D T.init). However, there are some corner cases in the language where a 1702 type's $(D init) value is not its default-initialized value. In particular, 1703 1704 1. If a type is a non-$(K_STATIC) nested struct, it has a context pointer 1705 which refers to the scope in which it's declared. So, its 1706 default-initialized value is its $(D init) value $(I plus) the value for 1707 its context pointer. However, if such a nested struct is explicitly 1708 initialized with just its $(D init) value instead of being 1709 default-initialized or being constructed via a constructor, then its 1710 context pointer is $(K_NULL), potentially leading to segfaults when the 1711 object is used. 1712 2. If a type is a struct for which default initialization has been disabled 1713 using $(D @disable this();), then while its $(D init) value is still used 1714 as the value of the object at the start of a constructor call (as is the 1715 case with any struct), the struct cannot be default-initialized and must 1716 instead be explicitly constructed. So, instead of $(D T.init) being the 1717 default-initialized value, it's just the struct's initial state before 1718 the constructor constructs the object, and the struct does not actually 1719 have a default-initialized value. 1720 1721 In the case of #2, there is no default initialization for the struct, 1722 whereas in the case of #1, there $(I is) default initialization for the 1723 struct but only within the scope where the struct is declared. Outside of 1724 that scope, the compiler does not have access to that scope and therefore 1725 cannot iniitialize the context pointer with a value, so a compilation error 1726 results. And so, either case can make it so that a struct cannot be 1727 default-initialized. 1728 1729 In both cases, an instance of the struct can still be explicitly 1730 initialized with its $(D init) value, but that will usually lead to 1731 incorrect code, because either the object's context pointer will be 1732 $(K_NULL), or it's a type which was designed with the idea that it would 1733 only ever be explicitly constructed. So, while sometimes it's still 1734 appropriate to explicitly use the $(D init) value (e.g. by default, 1735 $(REF1 destroy, object) will set the object to its $(D init) value after 1736 destroying it so that it's in a valid state to have its destructor called 1737 afterwards in cases where the object is still going to be destroyed when it 1738 leaves scope), in general, generic code which needs to explicitly 1739 default-initialize a variable shouldn't use the type's $(D init) value. 1740 1741 For a type, $(D T), which is a struct which does not declare a $(K_STATIC) 1742 $(D opCall), $(D T()) can be used instead of $(D T.init) to get the type's 1743 default-initialized value, and unlike $(D T.init), it will fail to compile 1744 if the object cannot actually be default-initialized (be it because it has 1745 disabled default initialization, or because it's a nested struct outside of 1746 the scope where that struct was declared). So, unlike $(D T.init), it 1747 won't compile in cases where default initialization does not work, and thus 1748 it can't accidentally be used to initialize a struct which cannot be 1749 default-intiialized. Also, for nested structs, $(D T()) will initialize the 1750 context pointer, unlike $(D T.init). So, using $(D T()) normally gives the 1751 actual default-initialized value for the type or fails to compile if the 1752 type cannot be default-initialized. 1753 1754 However, unfortunately, using $(D T()) does not work in generic code, 1755 because it is legal for a struct to declare a $(K_STATIC) $(D opCall) which 1756 takes no arguments, overriding the normal behavior of $(D T()) and making 1757 it so that it's no longer the default-initialized value. Instead, it's 1758 whatever $(K_STATIC) $(D opCall) returns, and $(K_STATIC) $(D opCall) can 1759 return any type, not just $(D T), because even though it looks like a 1760 constructor call, it's not actually a constructor call, and it can return 1761 whatever the programmer felt like - including $(K_VOID). This means that 1762 the only way to consistently get a default-initialized value for a type in 1763 generic code is to actually declare a variable and not give it a value. 1764 1765 So, in order to work around that, defaultInit does that for you. 1766 $(D defaultInit!Foo) evaluates to the default-initialized value of $(D Foo), 1767 but unlike $(D Foo.init), it won't compile when $(D Foo) cannot be 1768 default-initialized. And it won't get hijacked by $(K_STATIC) $(D opCall). 1769 1770 The downside to using such a helper template is that it will not work with 1771 a nested struct even within the scope where that nested struct is declared 1772 (since defaultInit is declared outside of that scope). So, code which needs 1773 to get a default-initialized instance of a nested struct within the scope 1774 where it's declared will either have to simply declare a variable and not 1775 initialize it or use $(D T()) to explicitly get the default-initialized 1776 value. And since this is within the code where the type is declared, it's 1777 fully within the programmer's control to not declare a $(K_STATIC) 1778 $(D opCall) for it. So, it shouldn't be a problem in practice. 1779 +/ 1780 template defaultInit(T) 1781 if (is(typeof({T t;}))) 1782 { 1783 // At present, simply using T.init should work, since all of the cases where 1784 // it wouldn't won't get past the template constraint. However, it's 1785 // possible that that will change at some point in the future, and this 1786 // approach is guaranteed to give whatever the default-initialized value is 1787 // regardless of whether it's T.init. 1788 enum defaultInit = (){ T retval; return retval; }(); 1789 } 1790 1791 /// 1792 @safe unittest 1793 { 1794 static assert(defaultInit!int == 0); 1795 static assert(defaultInit!bool == false); 1796 static assert(defaultInit!(int*) is null); 1797 static assert(defaultInit!(int[]) is null); 1798 static assert(defaultInit!string is null); 1799 static assert(defaultInit!(int[2]) == [0, 0]); 1800 1801 static struct S 1802 { 1803 int i = 42; 1804 } 1805 static assert(defaultInit!S == S(42)); 1806 1807 static assert(defaultInit!Object is null); 1808 1809 interface I 1810 { 1811 bool foo(); 1812 } 1813 static assert(defaultInit!I is null); 1814 1815 static struct NoDefaultInit 1816 { 1817 int i; 1818 @disable this(); 1819 } 1820 1821 // It's not legal to default-initialize NoDefaultInit, because it has 1822 // disabled default initialization. 1823 static assert(!__traits(compiles, defaultInit!NoDefaultInit)); 1824 1825 int var = 2; 1826 struct Nested 1827 { 1828 int i = 40; 1829 1830 int foo() 1831 { 1832 return i + var; 1833 } 1834 } 1835 1836 // defaultInit doesn't have access to this scope and thus cannot 1837 // initialize the nested struct. 1838 static assert(!__traits(compiles, defaultInit!Nested)); 1839 1840 // However, because Nested has no static opCall (and we know it doesn't 1841 // because we're doing this in the same scope where Nested was declared), 1842 // Nested() can be used to get the default-initialized value. 1843 static assert(Nested() == Nested(40)); 1844 1845 Nested nested; 1846 assert(Nested() == nested); 1847 1848 // Both have properly initialized context pointers, 1849 // whereas Nested.init does not. 1850 assert(Nested().foo() == nested.foo()); 1851 1852 // defaultInit does not get hijacked by static opCall. 1853 static struct HasOpCall 1854 { 1855 int i; 1856 1857 static opCall() 1858 { 1859 return HasOpCall(42); 1860 } 1861 1862 static opCall(int i) 1863 { 1864 HasOpCall retval; 1865 retval.i = i; 1866 return retval; 1867 } 1868 } 1869 1870 static assert(defaultInit!HasOpCall == HasOpCall(0)); 1871 static assert(HasOpCall() == HasOpCall(42)); 1872 } 1873 1874 @safe unittest 1875 { 1876 static struct NoCopy 1877 { 1878 int i = 17; 1879 @disable this(this); 1880 } 1881 static assert(defaultInit!NoCopy == NoCopy(17)); 1882 1883 string function() funcPtr; 1884 static assert(defaultInit!(SymbolType!funcPtr) is null); 1885 1886 string delegate() del; 1887 static assert(defaultInit!(SymbolType!del) is null); 1888 1889 int function() @property propFuncPtr; 1890 static assert(defaultInit!(SymbolType!propFuncPtr) is null); 1891 1892 int delegate() @property propDel; 1893 static assert(defaultInit!(SymbolType!propDel) is null); 1894 } 1895 1896 /++ 1897 Evaluates to an $(D AliasSeq) containing the members of an enum type. 1898 1899 The elements of the $(D AliasSeq) are in the same order as they are in the 1900 enum declaration. 1901 1902 An enum can have multiple members with the same value, so if code needs the 1903 enum values to be unique (e.g. if it's generating a switch statement from 1904 them), then $(REF Unique, phobos, sys, meta) can be used to filter out the 1905 duplicate values - e.g. $(D Unique!(isEqual, EnumMembers!E)). 1906 +/ 1907 template EnumMembers(E) 1908 if (is(E == enum)) 1909 { 1910 import phobos.sys.meta : AliasSeq; 1911 1912 alias EnumMembers = AliasSeq!(); 1913 static foreach (member; __traits(allMembers, E)) 1914 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, member)); 1915 } 1916 1917 /// Create an array of enum values. 1918 @safe unittest 1919 { 1920 enum Sqrts : real 1921 { 1922 one = 1, 1923 two = 1.41421, 1924 three = 1.73205 1925 } 1926 auto sqrts = [EnumMembers!Sqrts]; 1927 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]); 1928 } 1929 1930 /++ 1931 A generic function $(D rank(v)) in the following example uses this template 1932 for finding a member $(D e) in an enum type $(D E). 1933 +/ 1934 @safe unittest 1935 { 1936 // Returns i if e is the i-th member of E. 1937 static size_t rank(E)(E e) 1938 if (is(E == enum)) 1939 { 1940 static foreach (i, member; EnumMembers!E) 1941 { 1942 if (e == member) 1943 return i; 1944 } 1945 assert(0, "Not an enum member"); 1946 } 1947 1948 enum Mode 1949 { 1950 read = 1, 1951 write = 2, 1952 map = 4 1953 } 1954 assert(rank(Mode.read) == 0); 1955 assert(rank(Mode.write) == 1); 1956 assert(rank(Mode.map) == 2); 1957 } 1958 1959 /// Use EnumMembers to generate a switch statement using static foreach. 1960 @safe unittest 1961 { 1962 static class Foo 1963 { 1964 string calledMethod; 1965 void foo() @safe { calledMethod = "foo"; } 1966 void bar() @safe { calledMethod = "bar"; } 1967 void baz() @safe { calledMethod = "baz"; } 1968 } 1969 1970 enum FuncName : string { foo = "foo", bar = "bar", baz = "baz" } 1971 1972 auto foo = new Foo; 1973 1974 s: final switch (FuncName.bar) 1975 { 1976 static foreach (member; EnumMembers!FuncName) 1977 { 1978 // Generate a case for each enum value. 1979 case member: 1980 { 1981 // Call foo.{enum value}(). 1982 __traits(getMember, foo, member)(); 1983 break s; 1984 } 1985 } 1986 } 1987 1988 // Since we passed FuncName.bar to the switch statement, the bar member 1989 // function was called. 1990 assert(foo.calledMethod == "bar"); 1991 } 1992 1993 @safe unittest 1994 { 1995 { 1996 enum A { a } 1997 static assert([EnumMembers!A] == [A.a]); 1998 enum B { a, b, c, d, e } 1999 static assert([EnumMembers!B] == [B.a, B.b, B.c, B.d, B.e]); 2000 } 2001 { 2002 enum A : string { a = "alpha", b = "beta" } 2003 static assert([EnumMembers!A] == [A.a, A.b]); 2004 2005 static struct S 2006 { 2007 int value; 2008 int opCmp(S rhs) const nothrow { return value - rhs.value; } 2009 } 2010 enum B : S { a = S(1), b = S(2), c = S(3) } 2011 static assert([EnumMembers!B] == [B.a, B.b, B.c]); 2012 } 2013 { 2014 enum A { a = 0, b = 0, c = 1, d = 1, e } 2015 static assert([EnumMembers!A] == [A.a, A.b, A.c, A.d, A.e]); 2016 } 2017 { 2018 enum E { member, a = 0, b = 0 } 2019 2020 static assert(__traits(isSame, EnumMembers!E[0], E.member)); 2021 static assert(__traits(isSame, EnumMembers!E[1], E.a)); 2022 static assert(__traits(isSame, EnumMembers!E[2], E.b)); 2023 2024 static assert(__traits(identifier, EnumMembers!E[0]) == "member"); 2025 static assert(__traits(identifier, EnumMembers!E[1]) == "a"); 2026 static assert(__traits(identifier, EnumMembers!E[2]) == "b"); 2027 } 2028 } 2029 2030 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums 2031 @safe unittest 2032 { 2033 static string genEnum() 2034 { 2035 string result = "enum TLAs {"; 2036 foreach (c0; '0' .. '2' + 1) 2037 { 2038 foreach (c1; '0' .. '9' + 1) 2039 { 2040 foreach (c2; '0' .. '9' + 1) 2041 { 2042 foreach (c3; '0' .. '9' + 1) 2043 { 2044 result ~= '_'; 2045 result ~= c0; 2046 result ~= c1; 2047 result ~= c2; 2048 result ~= c3; 2049 result ~= ','; 2050 } 2051 } 2052 } 2053 } 2054 result ~= '}'; 2055 return result; 2056 } 2057 mixin(genEnum); 2058 static assert(EnumMembers!TLAs[0] == TLAs._0000); 2059 static assert(EnumMembers!TLAs[$ - 1] == TLAs._2999); 2060 } 2061 2062 /++ 2063 Whether the type $(D From) is implicitly convertible to the type $(D To). 2064 2065 Note that template constraints should be very careful about when they test 2066 for implicit conversions and in general should prefer to either test for an 2067 exact set of types or for types which compile with a particular piece of 2068 code rather than being designed to accept any type which implicitly converts 2069 to a particular type. 2070 2071 This is because having a type pass a template constraint based on an 2072 implicit conversion but then not have the implicit conversion actually take 2073 place (which it won't unless the template does something to force it 2074 internally) can lead to either compilation errors or subtle behavioral 2075 differences - and even when the conversion is done explicitly within a 2076 templated function, since it's not done at the call site, it can still lead 2077 to subtle bugs in some cases (e.g. if slicing a static array is involved). 2078 2079 For situations where code needs to verify that a type is implicitly 2080 convertible based solely on its qualifiers, $(LREF isQualifierConvertible) 2081 would be a more appropriate choice than isImplicitlyConvertible. 2082 2083 Given how trivial the $(D is) expression for isImplicitlyConvertible is - 2084 $(D is(To : From)) - this trait is provided primarily so that it can be 2085 used in conjunction with templates that use a template predicate (such as 2086 many of the templates in phobos.sys.meta). 2087 2088 The single-argument overload makes it so that it can be partially 2089 instantiated with the first argument, which will often be necessary with 2090 template predicates. 2091 2092 See_Also: 2093 $(DDSUBLINK dlang.org/spec/type, implicit-conversions, Spec on implicit conversions) 2094 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 2095 $(LREF isQualifierConvertible) 2096 +/ 2097 enum isImplicitlyConvertible(From, To) = is(From : To); 2098 2099 /++ Ditto +/ 2100 template isImplicitlyConvertible(From) 2101 { 2102 enum isImplicitlyConvertible(To) = is(From : To); 2103 } 2104 2105 /// 2106 @safe unittest 2107 { 2108 static assert( isImplicitlyConvertible!(byte, long)); 2109 static assert( isImplicitlyConvertible!(ushort, long)); 2110 static assert( isImplicitlyConvertible!(int, long)); 2111 static assert( isImplicitlyConvertible!(long, long)); 2112 static assert( isImplicitlyConvertible!(ulong, long)); 2113 2114 static assert( isImplicitlyConvertible!(ubyte, int)); 2115 static assert( isImplicitlyConvertible!(short, int)); 2116 static assert( isImplicitlyConvertible!(int, int)); 2117 static assert( isImplicitlyConvertible!(uint, int)); 2118 static assert(!isImplicitlyConvertible!(long, int)); 2119 static assert(!isImplicitlyConvertible!(ulong, int)); 2120 2121 static assert(!isImplicitlyConvertible!(int, string)); 2122 static assert(!isImplicitlyConvertible!(int, int[])); 2123 static assert(!isImplicitlyConvertible!(int, int*)); 2124 2125 static assert(!isImplicitlyConvertible!(string, int)); 2126 static assert(!isImplicitlyConvertible!(int[], int)); 2127 static assert(!isImplicitlyConvertible!(int*, int)); 2128 2129 // For better or worse, bool and the built-in character types will 2130 // implicitly convert to integer or floating-point types if the target type 2131 // is large enough. Sometimes, this is desirable, whereas at other times, 2132 // it can have very surprising results, so it's one reason why code should 2133 // be very careful when testing for implicit conversions. 2134 static assert( isImplicitlyConvertible!(bool, int)); 2135 static assert( isImplicitlyConvertible!(char, int)); 2136 static assert( isImplicitlyConvertible!(wchar, int)); 2137 static assert( isImplicitlyConvertible!(dchar, int)); 2138 2139 static assert( isImplicitlyConvertible!(bool, ubyte)); 2140 static assert( isImplicitlyConvertible!(char, ubyte)); 2141 static assert(!isImplicitlyConvertible!(wchar, ubyte)); 2142 static assert(!isImplicitlyConvertible!(dchar, ubyte)); 2143 2144 static assert( isImplicitlyConvertible!(bool, double)); 2145 static assert( isImplicitlyConvertible!(char, double)); 2146 static assert( isImplicitlyConvertible!(wchar, double)); 2147 static assert( isImplicitlyConvertible!(dchar, double)); 2148 2149 // Value types can be implicitly converted regardless of their qualifiers 2150 // thanks to the fact that they're copied. 2151 static assert( isImplicitlyConvertible!(int, int)); 2152 static assert( isImplicitlyConvertible!(const int, int)); 2153 static assert( isImplicitlyConvertible!(immutable int, int)); 2154 static assert( isImplicitlyConvertible!(inout int, int)); 2155 2156 static assert( isImplicitlyConvertible!(int, const int)); 2157 static assert( isImplicitlyConvertible!(int, immutable int)); 2158 static assert( isImplicitlyConvertible!(int, inout int)); 2159 2160 // Reference types are far more restrictive about which implicit conversions 2161 // they allow, because qualifiers in D are transitive. 2162 static assert( isImplicitlyConvertible!(int*, int*)); 2163 static assert(!isImplicitlyConvertible!(const int*, int*)); 2164 static assert(!isImplicitlyConvertible!(immutable int*, int*)); 2165 2166 static assert( isImplicitlyConvertible!(int*, const int*)); 2167 static assert( isImplicitlyConvertible!(const int*, const int*)); 2168 static assert( isImplicitlyConvertible!(immutable int*, const int*)); 2169 2170 static assert(!isImplicitlyConvertible!(int*, immutable int*)); 2171 static assert(!isImplicitlyConvertible!(const int*, immutable int*)); 2172 static assert( isImplicitlyConvertible!(immutable int*, immutable int*)); 2173 2174 // Note that inout gets a bit weird, since it's only used with function 2175 // parameters, and it's a stand-in for whatever mutability qualifiers the 2176 // type actually has. So, a function parameter that's inout accepts any 2177 // mutability, but you can't actually implicitly convert to inout, because 2178 // it's unknown within the function what the actual mutability of the type 2179 // is. It will differ depending on the function arguments of a specific 2180 // call to that function, so the same code has to work with all combinations 2181 // of mutability qualifiers. 2182 static assert(!isImplicitlyConvertible!(int*, inout int*)); 2183 static assert(!isImplicitlyConvertible!(const int*, inout int*)); 2184 static assert(!isImplicitlyConvertible!(immutable int*, inout int*)); 2185 static assert( isImplicitlyConvertible!(inout int*, inout int*)); 2186 2187 static assert(!isImplicitlyConvertible!(inout int*, int*)); 2188 static assert( isImplicitlyConvertible!(inout int*, const int*)); 2189 static assert(!isImplicitlyConvertible!(inout int*, immutable int*)); 2190 2191 // Enums implicitly convert to their base type. 2192 enum E : int 2193 { 2194 a = 42 2195 } 2196 static assert( isImplicitlyConvertible!(E, int)); 2197 static assert( isImplicitlyConvertible!(E, long)); 2198 static assert(!isImplicitlyConvertible!(E, int[])); 2199 2200 // Structs only implicit convert to another type via declaring an 2201 // alias this. 2202 static struct S 2203 { 2204 int i; 2205 } 2206 static assert(!isImplicitlyConvertible!(S, int)); 2207 static assert(!isImplicitlyConvertible!(S, long)); 2208 static assert(!isImplicitlyConvertible!(S, string)); 2209 2210 static struct AliasThis 2211 { 2212 int i; 2213 alias this = i; 2214 } 2215 static assert( isImplicitlyConvertible!(AliasThis, int)); 2216 static assert( isImplicitlyConvertible!(AliasThis, long)); 2217 static assert(!isImplicitlyConvertible!(AliasThis, string)); 2218 2219 static struct AliasThis2 2220 { 2221 AliasThis at; 2222 alias this = at; 2223 } 2224 static assert( isImplicitlyConvertible!(AliasThis2, AliasThis)); 2225 static assert( isImplicitlyConvertible!(AliasThis2, int)); 2226 static assert( isImplicitlyConvertible!(AliasThis2, long)); 2227 static assert(!isImplicitlyConvertible!(AliasThis2, string)); 2228 2229 static struct AliasThis3 2230 { 2231 AliasThis2 at; 2232 alias this = at; 2233 } 2234 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2)); 2235 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis)); 2236 static assert( isImplicitlyConvertible!(AliasThis3, int)); 2237 static assert( isImplicitlyConvertible!(AliasThis3, long)); 2238 static assert(!isImplicitlyConvertible!(AliasThis3, string)); 2239 2240 // D does not support implicit conversions via construction. 2241 static struct Cons 2242 { 2243 this(int i) 2244 { 2245 this.i = i; 2246 } 2247 2248 int i; 2249 } 2250 static assert(!isImplicitlyConvertible!(int, Cons)); 2251 2252 // Classes support implicit conversion based on their class and 2253 // interface hierarchies. 2254 static interface I1 {} 2255 static class Base : I1 {} 2256 2257 static interface I2 {} 2258 static class Foo : Base, I2 {} 2259 2260 static class Bar : Base {} 2261 2262 static assert( isImplicitlyConvertible!(Base, Base)); 2263 static assert(!isImplicitlyConvertible!(Base, Foo)); 2264 static assert(!isImplicitlyConvertible!(Base, Bar)); 2265 static assert( isImplicitlyConvertible!(Base, I1)); 2266 static assert(!isImplicitlyConvertible!(Base, I2)); 2267 2268 static assert( isImplicitlyConvertible!(Foo, Base)); 2269 static assert( isImplicitlyConvertible!(Foo, Foo)); 2270 static assert(!isImplicitlyConvertible!(Foo, Bar)); 2271 static assert( isImplicitlyConvertible!(Foo, I1)); 2272 static assert( isImplicitlyConvertible!(Foo, I2)); 2273 2274 static assert( isImplicitlyConvertible!(Bar, Base)); 2275 static assert(!isImplicitlyConvertible!(Bar, Foo)); 2276 static assert( isImplicitlyConvertible!(Bar, Bar)); 2277 static assert( isImplicitlyConvertible!(Bar, I1)); 2278 static assert(!isImplicitlyConvertible!(Bar, I2)); 2279 2280 static assert(!isImplicitlyConvertible!(I1, Base)); 2281 static assert(!isImplicitlyConvertible!(I1, Foo)); 2282 static assert(!isImplicitlyConvertible!(I1, Bar)); 2283 static assert( isImplicitlyConvertible!(I1, I1)); 2284 static assert(!isImplicitlyConvertible!(I1, I2)); 2285 2286 static assert(!isImplicitlyConvertible!(I2, Base)); 2287 static assert(!isImplicitlyConvertible!(I2, Foo)); 2288 static assert(!isImplicitlyConvertible!(I2, Bar)); 2289 static assert(!isImplicitlyConvertible!(I2, I1)); 2290 static assert( isImplicitlyConvertible!(I2, I2)); 2291 2292 // Note that arrays are not implicitly convertible even when their elements 2293 // are implicitly convertible. 2294 static assert(!isImplicitlyConvertible!(ubyte[], uint[])); 2295 static assert(!isImplicitlyConvertible!(Foo[], Base[])); 2296 static assert(!isImplicitlyConvertible!(Bar[], Base[])); 2297 2298 // However, like with pointers, dynamic arrays are convertible based on 2299 // constness. 2300 static assert( isImplicitlyConvertible!(Base[], const Base[])); 2301 static assert( isImplicitlyConvertible!(Base[], const(Base)[])); 2302 static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[])); 2303 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 2304 static assert( isImplicitlyConvertible!(const Base[], const Base[])); 2305 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 2306 } 2307 2308 /++ 2309 isImplicitlyConvertible can be used with partial instantiation so that it 2310 can be passed to a template which takes a unary predicate. 2311 +/ 2312 @safe unittest 2313 { 2314 import phobos.sys.meta : AliasSeq, all, indexOf; 2315 2316 // byte is implicitly convertible to byte, short, int, and long. 2317 static assert(all!(isImplicitlyConvertible!byte, short, int, long)); 2318 2319 // const(char)[] at index 2 is the first type in the AliasSeq which string 2320 // can be implicitly converted to. 2321 alias Types = AliasSeq!(int, char[], const(char)[], string, int*); 2322 static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2); 2323 } 2324 2325 /++ 2326 Whether $(D From) is 2327 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) 2328 to $(D To). 2329 2330 This is testing whether $(D From) and $(D To) are the same type - minus the 2331 qualifiers - and whether the qualifiers on $(D From) can be implicitly 2332 converted to the qualifiers on $(D To). No other implicit conversions are 2333 taken into account. 2334 2335 For instance, $(D const int*) is not implicitly convertible to $(D int*), 2336 because that would violate $(D const). That means that $(D const) is not 2337 qualifier convertible to mutable. And as such, $(I any) $(D const) type 2338 is not qualifier convertible to a mutable type even if it's implicitly 2339 convertible. E.G. $(D const int) is implicitly convertible to $(D int), 2340 because it can be copied to avoid violating $(D const), but it's still not 2341 qualifier convertible, because $(D const) types in general cannot be 2342 implicitly converted to mutable. 2343 2344 The exact types being tested matter, because they need to be the same 2345 (minus the qualifiers) in order to be considered convertible, but beyond 2346 that, all that matters for the conversion is whether those qualifers would 2347 be convertible regardless of which types they were on. So, if you're having 2348 trouble picturing whether $(D From) would be qualifier convertible to 2349 $(D To), then consider which conversions would be allowed from $(D From[]) 2350 to $(D To[]) (and remember that dynamic arrays are only implicitly 2351 convertible based on their qualifers). 2352 2353 The $(DDSUBLINK spec/const3, implicit_qualifier_conversions, spec) provides 2354 a table of which qualifiers can be implcitly converted to which other 2355 qualifers (and of course, there a bunch of examples below). 2356 2357 So, isQualifierConvertible can be used in a case like 2358 $(D isQualifierConvertible!(ReturnType!(typeof(foo(bar))), const char), 2359 which would be testing that the return type of $(D foo(bar)) was $(D char), 2360 $(D const char), or $(D immutable char) (since those are the only types 2361 which are qualifier convertible to $(D const char)). 2362 2363 This is in contrast to 2364 $(D isImplicitlyConvertible!(ReturnType!(typeof(foo(bar))), const char), 2365 which would be $(D true) for $(I any) type which was implicitly convertible 2366 to $(D const char) rather than just $(D char), $(D const char), and 2367 $(D immutable char). 2368 2369 The single-argument overload makes it so that it can be partially 2370 instantiated with the first argument, which will often be necessary with 2371 template predicates. 2372 2373 See_Also: 2374 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 2375 $(LREF isImplicitlyConvertible) 2376 +/ 2377 enum isQualifierConvertible(From, To) = is(immutable From == immutable To) && is(From* : To*); 2378 2379 /++ Ditto +/ 2380 template isQualifierConvertible(From) 2381 { 2382 enum isQualifierConvertible(To) = is(immutable From == immutable To) && is(From* : To*); 2383 } 2384 2385 /// 2386 @safe unittest 2387 { 2388 // i.e. char* -> const char* 2389 static assert( isQualifierConvertible!(char, const char)); 2390 2391 // i.e. const char* -> char* 2392 static assert(!isQualifierConvertible!(const char, char)); 2393 2394 static assert( isQualifierConvertible!(int, int)); 2395 static assert( isQualifierConvertible!(int, const int)); 2396 static assert(!isQualifierConvertible!(int, immutable int)); 2397 2398 static assert(!isQualifierConvertible!(const int, int)); 2399 static assert( isQualifierConvertible!(const int, const int)); 2400 static assert(!isQualifierConvertible!(const int, immutable int)); 2401 2402 static assert(!isQualifierConvertible!(immutable int, int)); 2403 static assert( isQualifierConvertible!(immutable int, const int)); 2404 static assert( isQualifierConvertible!(immutable int, immutable int)); 2405 2406 // Note that inout gets a bit weird, since it's only used with function 2407 // parameters, and it's a stand-in for whatever mutability qualifiers the 2408 // type actually has. So, a function parameter that's inout accepts any 2409 // mutability, but you can't actually implicitly convert to inout, because 2410 // it's unknown within the function what the actual mutability of the type 2411 // is. It will differ depending on the function arguments of a specific 2412 // call to that function, so the same code has to work with all combinations 2413 // of mutability qualifiers. 2414 static assert(!isQualifierConvertible!(int, inout int)); 2415 static assert(!isQualifierConvertible!(const int, inout int)); 2416 static assert(!isQualifierConvertible!(immutable int, inout int)); 2417 static assert( isQualifierConvertible!(inout int, inout int)); 2418 2419 static assert(!isQualifierConvertible!(inout int, int)); 2420 static assert( isQualifierConvertible!(inout int, const int)); 2421 static assert(!isQualifierConvertible!(inout int, immutable int)); 2422 2423 // shared is of course also a qualifier. 2424 static assert(!isQualifierConvertible!(int, shared int)); 2425 static assert(!isQualifierConvertible!(int, const shared int)); 2426 static assert(!isQualifierConvertible!(const int, shared int)); 2427 static assert(!isQualifierConvertible!(const int, const shared int)); 2428 static assert(!isQualifierConvertible!(immutable int, shared int)); 2429 static assert( isQualifierConvertible!(immutable int, const shared int)); 2430 2431 static assert(!isQualifierConvertible!(shared int, int)); 2432 static assert(!isQualifierConvertible!(shared int, const int)); 2433 static assert(!isQualifierConvertible!(shared int, immutable int)); 2434 static assert( isQualifierConvertible!(shared int, shared int)); 2435 static assert( isQualifierConvertible!(shared int, const shared int)); 2436 2437 static assert(!isQualifierConvertible!(const shared int, int)); 2438 static assert(!isQualifierConvertible!(const shared int, const int)); 2439 static assert(!isQualifierConvertible!(const shared int, immutable int)); 2440 static assert(!isQualifierConvertible!(const shared int, shared int)); 2441 static assert( isQualifierConvertible!(const shared int, const shared int)); 2442 2443 // Implicit conversions don't count unless they're based purely on 2444 // qualifiers. 2445 enum E : int 2446 { 2447 a = 1 2448 } 2449 2450 static assert(!isQualifierConvertible!(E, int)); 2451 static assert(!isQualifierConvertible!(E, const int)); 2452 static assert( isQualifierConvertible!(E, E)); 2453 static assert( isQualifierConvertible!(E, const E)); 2454 static assert(!isQualifierConvertible!(E, immutable E)); 2455 2456 static struct AliasThis 2457 { 2458 int i; 2459 alias this = i; 2460 } 2461 2462 static assert(!isQualifierConvertible!(AliasThis, int)); 2463 static assert(!isQualifierConvertible!(AliasThis, const int)); 2464 static assert( isQualifierConvertible!(AliasThis, AliasThis)); 2465 static assert( isQualifierConvertible!(AliasThis, const AliasThis)); 2466 static assert(!isQualifierConvertible!(AliasThis, immutable AliasThis)); 2467 2468 // The qualifiers are irrelevant if the types aren't the same when 2469 // stripped of all qualifers. 2470 static assert(!isQualifierConvertible!(int, long)); 2471 static assert(!isQualifierConvertible!(int, const long)); 2472 static assert(!isQualifierConvertible!(string, const(ubyte)[])); 2473 } 2474 2475 /++ 2476 isQualifierConvertible can be used with partial instantiation so that it 2477 can be passed to a template which takes a unary predicate. 2478 +/ 2479 @safe unittest 2480 { 2481 import phobos.sys.meta : AliasSeq, all, indexOf; 2482 2483 // byte is qualifier convertible to byte and const byte. 2484 static assert(all!(isQualifierConvertible!byte, byte, const byte)); 2485 2486 // const(char[]) at index 2 is the first type in the AliasSeq which string 2487 // is qualifier convertible to. 2488 alias Types = AliasSeq!(int, char[], const(char[]), string, int*); 2489 static assert(indexOf!(isQualifierConvertible!string, Types) == 2); 2490 } 2491 2492 @safe unittest 2493 { 2494 import phobos.sys.meta : AliasSeq; 2495 2496 alias Types = AliasSeq!(int, const int, shared int, inout int, const shared int, 2497 const inout int, inout shared int, const inout shared int, immutable int); 2498 2499 // https://dlang.org/spec/const3.html#implicit_qualifier_conversions 2500 enum _ = 0; 2501 static immutable bool[Types.length][Types.length] conversions = [ 2502 // m c s i cs ci is cis im 2503 [1, 1, _, _, _, _, _, _, _], // mutable 2504 [_, 1, _, _, _, _, _, _, _], // const 2505 [_, _, 1, _, 1, _, _, _, _], // shared 2506 [_, 1, _, 1, _, 1, _, _, _], // inout 2507 [_, _, _, _, 1, _, _, _, _], // const shared 2508 [_, 1, _, _, _, 1, _, _, _], // const inout 2509 [_, _, _, _, 1, _, 1, 1, _], // inout shared 2510 [_, _, _, _, 1, _, _, 1, _], // const inout shared 2511 [_, 1, _, _, 1, 1, _, 1, 1], // immutable 2512 ]; 2513 2514 foreach (i, From; Types) 2515 { 2516 foreach (j, To; Types) 2517 { 2518 static assert(isQualifierConvertible!(From, To) == conversions[i][j], 2519 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`" ~ 2520 " should be `" ~ (conversions[i][j] ? "true`" : "false`")); 2521 } 2522 } 2523 } 2524 2525 /++ 2526 Whether the given values are equal per $(D ==). 2527 2528 All this does is $(D lhs == rhs) but in an eponymous template, so most code 2529 shouldn't use it. It's intended to be used in conjunction with templates 2530 that take a template predicate - such as those in phobos.sys.meta. 2531 2532 The single-argument overload makes it so that it can be partially 2533 instantiated with the first argument, which will often be necessary with 2534 template predicates. 2535 2536 Note that in most cases, even when comparing values at compile time, using 2537 isEqual makes no sense, because you can use CTFE to just compare two values 2538 (or expressions which evaluate to values), but in rare cases where you need 2539 to compare symbols in an $(D AliasSeq) by value with a template predicate 2540 while still leaving them as symbols in an $(D AliasSeq), then isEqual would 2541 be needed. 2542 2543 A prime example of this would be $(D Unique!(isEqual, EnumMembers!MyEnum)), 2544 which results in an $(D AliasSeq) containing the list of members of 2545 $(D MyEnum) but without any duplicate values (e.g. to use when doing code 2546 generation to create a final switch). 2547 2548 Alternatively, code such as $(D [EnumMembers!MyEnum].sort().unique()) could 2549 be used to get a dynamic array of the enum members with no duplicate values 2550 via CTFE, thus avoiding the need for template predicates or anything from 2551 phobos.sys.meta. However, you then have a dynamic array of enum values 2552 rather than an $(D AliasSeq) of symbols for those enum members, which 2553 affects what you can do with type introspection. So, which approach is 2554 better depends on what the code needs to do with the enum members. 2555 2556 In general, however, if code doesn't need an $(D AliasSeq), and an array of 2557 values will do the trick, then it's more efficient to operate on an array of 2558 values with CTFE and avoid using isEqual or other templates to operate on 2559 the values as an $(D AliasSeq). 2560 2561 See_Also: 2562 $(LREF isSameSymbol) 2563 $(LREF isSameType) 2564 +/ 2565 enum isEqual(alias lhs, alias rhs) = lhs == rhs; 2566 2567 /++ Ditto +/ 2568 template isEqual(alias lhs) 2569 { 2570 enum isEqual(alias rhs) = lhs == rhs; 2571 } 2572 2573 /// It acts just like ==, but it's a template. 2574 @safe unittest 2575 { 2576 enum a = 42; 2577 2578 static assert( isEqual!(a, 42)); 2579 static assert( isEqual!(20, 10 + 10)); 2580 2581 static assert(!isEqual!(a, 120)); 2582 static assert(!isEqual!(77, 19 * 7 + 2)); 2583 2584 // b cannot be read at compile time, so it won't work with isEqual. 2585 int b = 99; 2586 static assert(!__traits(compiles, isEqual!(b, 99))); 2587 } 2588 2589 /++ 2590 Comparing some of the differences between an $(D AliasSeq) of enum members 2591 and an array of enum values created from an $(D AliasSeq) of enum members. 2592 +/ 2593 @safe unittest 2594 { 2595 import phobos.sys.meta : AliasSeq, Unique; 2596 2597 enum E 2598 { 2599 a = 0, 2600 b = 22, 2601 c = 33, 2602 d = 0, 2603 e = 256, 2604 f = 33, 2605 g = 7 2606 } 2607 2608 alias uniqueMembers = Unique!(isEqual, EnumMembers!E); 2609 static assert(uniqueMembers.length == 5); 2610 2611 static assert(__traits(isSame, uniqueMembers[0], E.a)); 2612 static assert(__traits(isSame, uniqueMembers[1], E.b)); 2613 static assert(__traits(isSame, uniqueMembers[2], E.c)); 2614 static assert(__traits(isSame, uniqueMembers[3], E.e)); 2615 static assert(__traits(isSame, uniqueMembers[4], E.g)); 2616 2617 static assert(__traits(identifier, uniqueMembers[0]) == "a"); 2618 static assert(__traits(identifier, uniqueMembers[1]) == "b"); 2619 static assert(__traits(identifier, uniqueMembers[2]) == "c"); 2620 static assert(__traits(identifier, uniqueMembers[3]) == "e"); 2621 static assert(__traits(identifier, uniqueMembers[4]) == "g"); 2622 2623 // Same value but different symbol. 2624 static assert(uniqueMembers[0] == E.d); 2625 static assert(!__traits(isSame, uniqueMembers[0], E.d)); 2626 2627 // is expressions compare types, not symbols or values, and these AliasSeqs 2628 // contain the list of symbols for the enum members, not types, so the is 2629 // expression evaluates to false even though the symbols are the same. 2630 static assert(!is(uniqueMembers == AliasSeq!(E.a, E.b, E.c, E.e, E.g))); 2631 2632 // Once the members are converted to an array, the types are the same, and 2633 // the values are the same, but the symbols are not the same. Instead of 2634 // being the symbols E.a, E.b, etc., they're just values with the type E 2635 // which match the values of E.a, E.b, etc. 2636 enum arr = [uniqueMembers]; 2637 static assert(is(typeof(arr) == E[])); 2638 2639 static assert(arr == [E.a, E.b, E.c, E.e, E.g]); 2640 static assert(arr == [E.d, E.b, E.f, E.e, E.g]); 2641 2642 static assert(!__traits(isSame, arr[0], E.a)); 2643 static assert(!__traits(isSame, arr[1], E.b)); 2644 static assert(!__traits(isSame, arr[2], E.c)); 2645 static assert(!__traits(isSame, arr[3], E.e)); 2646 static assert(!__traits(isSame, arr[4], E.g)); 2647 2648 // Since arr[0] is just a value of type E, it's no longer the symbol, E.a, 2649 // even though its type is E, and its value is the same as that of E.a. And 2650 // unlike the actual members of an enum, an element of an array does not 2651 // have an identifier, so __traits(identifier, ...) doesn't work with it. 2652 static assert(!__traits(compiles, __traits(identifier, arr[0]))); 2653 2654 // Similarly, once an enum member from the AliasSeq is assigned to a 2655 // variable, __traits(identifer, ...) operates on the variable, not the 2656 // symbol from the AliasSeq or the value of the variable. 2657 auto var = uniqueMembers[0]; 2658 static assert(__traits(identifier, var) == "var"); 2659 2660 // The same with a manifest constant. 2661 enum constant = uniqueMembers[0]; 2662 static assert(__traits(identifier, constant) == "constant"); 2663 } 2664 2665 /++ 2666 Whether the given symbols are the same symbol. 2667 2668 All this does is $(D __traits(isSame, lhs, rhs)), so most code shouldn't 2669 use it. It's intended to be used in conjunction with templates that take a 2670 template predicate - such as those in phobos.sys.meta. 2671 2672 The single-argument overload makes it so that it can be partially 2673 instantiated with the first argument, which will often be necessary with 2674 template predicates. 2675 2676 See_Also: 2677 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, lhs, rhs))) 2678 $(LREF isEqual) 2679 $(LREF isSameType) 2680 +/ 2681 enum isSameSymbol(alias lhs, alias rhs) = __traits(isSame, lhs, rhs); 2682 2683 /++ Ditto +/ 2684 template isSameSymbol(alias lhs) 2685 { 2686 enum isSameSymbol(alias rhs) = __traits(isSame, lhs, rhs); 2687 } 2688 2689 /// 2690 @safe unittest 2691 { 2692 int i; 2693 int j; 2694 real r; 2695 2696 static assert( isSameSymbol!(i, i)); 2697 static assert(!isSameSymbol!(i, j)); 2698 static assert(!isSameSymbol!(i, r)); 2699 2700 static assert(!isSameSymbol!(j, i)); 2701 static assert( isSameSymbol!(j, j)); 2702 static assert(!isSameSymbol!(j, r)); 2703 2704 static assert(!isSameSymbol!(r, i)); 2705 static assert(!isSameSymbol!(r, j)); 2706 static assert( isSameSymbol!(r, r)); 2707 2708 auto foo() { return 0; } 2709 auto bar() { return 0; } 2710 2711 static assert( isSameSymbol!(foo, foo)); 2712 static assert(!isSameSymbol!(foo, bar)); 2713 static assert(!isSameSymbol!(foo, i)); 2714 2715 static assert(!isSameSymbol!(bar, foo)); 2716 static assert( isSameSymbol!(bar, bar)); 2717 static assert(!isSameSymbol!(bar, i)); 2718 2719 // Types are symbols too. However, in most cases, they should be compared 2720 // as types, not symbols (be it with is expressions or with isSameType), 2721 // because the results aren't consistent between scalar types and 2722 // user-defined types with regards to type qualifiers when they're compared 2723 // as symbols. 2724 static assert( isSameSymbol!(double, double)); 2725 static assert(!isSameSymbol!(double, const double)); 2726 static assert(!isSameSymbol!(double, int)); 2727 static assert( isSameSymbol!(Object, Object)); 2728 static assert( isSameSymbol!(Object, const Object)); 2729 2730 static assert(!isSameSymbol!(i, int)); 2731 static assert( isSameSymbol!(typeof(i), int)); 2732 2733 // Lambdas can be compared with __traits(isSame, ...), 2734 // so they can be compared with isSameSymbol. 2735 static assert( isSameSymbol!(a => a + 42, a => a + 42)); 2736 static assert(!isSameSymbol!(a => a + 42, a => a + 99)); 2737 2738 // Partial instantiation allows it to be used with templates that expect 2739 // a predicate that takes only a single argument. 2740 import phobos.sys.meta : AliasSeq, indexOf; 2741 alias Types = AliasSeq!(i, j, r, int, long, foo); 2742 static assert(indexOf!(isSameSymbol!j, Types) == 1); 2743 static assert(indexOf!(isSameSymbol!int, Types) == 3); 2744 static assert(indexOf!(isSameSymbol!bar, Types) == -1); 2745 } 2746 2747 /++ 2748 Whether the given types are the same type. 2749 2750 All this does is $(D is(T == U)), so most code shouldn't use it. It's 2751 intended to be used in conjunction with templates that take a template 2752 predicate - such as those in phobos.sys.meta. 2753 2754 The single-argument overload makes it so that it can be partially 2755 instantiated with the first argument, which will often be necessary with 2756 template predicates. 2757 2758 See_Also: 2759 $(LREF isEqual) 2760 $(LREF isSameSymbol) 2761 +/ 2762 enum isSameType(T, U) = is(T == U); 2763 2764 /++ Ditto +/ 2765 template isSameType(T) 2766 { 2767 enum isSameType(U) = is(T == U); 2768 } 2769 2770 /// 2771 @safe unittest 2772 { 2773 static assert( isSameType!(long, long)); 2774 static assert(!isSameType!(long, const long)); 2775 static assert(!isSameType!(long, string)); 2776 static assert( isSameType!(string, string)); 2777 2778 int i; 2779 real r; 2780 static assert( isSameType!(int, typeof(i))); 2781 static assert(!isSameType!(int, typeof(r))); 2782 2783 static assert(!isSameType!(real, typeof(i))); 2784 static assert( isSameType!(real, typeof(r))); 2785 2786 // Partial instantiation allows it to be used with templates that expect 2787 // a predicate that takes only a single argument. 2788 import phobos.sys.meta : AliasSeq, indexOf; 2789 alias Types = AliasSeq!(float, string, int, double); 2790 static assert(indexOf!(isSameType!int, Types) == 2); 2791 } 2792 2793 /++ 2794 Evaluates to $(K_TRUE) ifthe given type is a delegate (and to $(K_FALSE) 2795 otherwise). 2796 2797 This is equivalent to $(D is(T == delegate)), so most code shouldn't use 2798 it. It's intended to be used in conjunction with templates that take a 2799 template predicate - such as those in $(MREF phobos, sys, meta). 2800 2801 Note that this does not include implicit conversions or enum types. The 2802 type itself must be a delegate. 2803 2804 Whether taking the address of a function results in a function pointer or a 2805 delegate depends on whether the result includes a context pointer. 2806 2807 Taking the address of a free function or a $(K_STATIC) function gives a 2808 function pointer. Taking the address of a non-$(K_STATIC) nested function 2809 gives a delegate. And the potentially confusing one is non-$(K_STATIC) 2810 member functions, because whether taking their address results in a 2811 function pointer or a delegate depends on whether the address is taken via 2812 the type or via an instance. 2813 2814 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 2815 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 2816 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 2817 of a symbol. 2818 2819 See_Also: 2820 $(LREF isFunction) 2821 $(LREF isFunctionPointer) 2822 $(LREF isReturn) 2823 $(LREF PropertyType) 2824 $(LREF SymbolType) 2825 $(LREF ToFunctionType) 2826 +/ 2827 enum isDelegate(T) = is(T == delegate); 2828 2829 /// 2830 @safe unittest 2831 { 2832 int var; 2833 static assert(!isDelegate!(SymbolType!var)); 2834 static assert(!isDelegate!(PropertyType!var)); 2835 static assert(!isDelegate!(typeof(&var))); 2836 static assert(!is(SymbolType!var == delegate)); 2837 static assert(!is(PropertType!var == delegate)); 2838 static assert(!is(typeof(&var) == delegate)); 2839 2840 static void func() {} 2841 static assert(!isDelegate!(SymbolType!func)); 2842 static assert(!isDelegate!(typeof(&func))); 2843 static assert(!is(SymbolType!func == delegate)); 2844 static assert(!is(typeof(&func) == delegate)); 2845 2846 void funcWithContext() { ++var; } 2847 static assert(!isDelegate!(SymbolType!funcWithContext)); 2848 static assert( isDelegate!(typeof(&funcWithContext))); 2849 static assert(!is(SymbolType!funcWithContext == delegate)); 2850 static assert( is(typeof(&funcWithContext) == delegate)); 2851 2852 int function() funcPtr; 2853 static assert(!isDelegate!(SymbolType!funcPtr)); 2854 static assert(!isDelegate!(PropertyType!funcPtr)); 2855 static assert(!isDelegate!(typeof(&funcPtr))); 2856 static assert(!is(SymbolType!funcPtr == delegate)); 2857 static assert(!is(PropertyType!funcPtr == delegate)); 2858 static assert(!is(typeof(&funcPtr) == delegate)); 2859 2860 int delegate() del; 2861 static assert( isDelegate!(SymbolType!del)); 2862 static assert( isDelegate!(PropertyType!del)); 2863 static assert(!isDelegate!(typeof(&del))); 2864 static assert( is(SymbolType!del == delegate)); 2865 static assert( is(PropertyType!del == delegate)); 2866 static assert(!is(typeof(&del) == delegate)); 2867 2868 @property static int prop() { return 0; } 2869 static assert(!isDelegate!(SymbolType!prop)); 2870 static assert(!isDelegate!(PropertyType!prop)); 2871 static assert(!isDelegate!(typeof(&prop))); 2872 static assert(!is(SymbolType!prop == delegate)); 2873 static assert(!is(PropertyType!prop == delegate)); 2874 static assert(!is(typeof(&prop) == delegate)); 2875 2876 @property int propWithContext() { return var; } 2877 static assert(!isDelegate!(SymbolType!propWithContext)); 2878 static assert(!isDelegate!(PropertyType!propWithContext)); 2879 static assert( isDelegate!(typeof(&propWithContext))); 2880 static assert(!is(SymbolType!propWithContext == delegate)); 2881 static assert(!is(PropertyType!propWithContext == delegate)); 2882 static assert( is(typeof(&propWithContext) == delegate)); 2883 2884 static int function() propFuncPtr() @property { return null; } 2885 static assert(!isDelegate!(SymbolType!propFuncPtr)); 2886 static assert(!isDelegate!(PropertyType!propFuncPtr)); 2887 static assert(!isDelegate!(typeof(&propFuncPtr))); 2888 static assert(!is(SymbolType!propFuncPtr == delegate)); 2889 static assert(!is(PropertyType!propFuncPtr == delegate)); 2890 static assert(!is(typeof(&propFuncPtr) == delegate)); 2891 2892 static int delegate() propDel() @property { return null; } 2893 static assert(!isDelegate!(SymbolType!propDel)); 2894 static assert( isDelegate!(PropertyType!propDel)); 2895 static assert(!isDelegate!(typeof(&propDel))); 2896 static assert(!is(SymbolType!propDel == delegate)); 2897 static assert( is(PropertyType!propDel == delegate)); 2898 static assert(!is(typeof(&propDel) == delegate)); 2899 2900 static struct S 2901 { 2902 void foo() {} 2903 } 2904 static assert(!isDelegate!(SymbolType!(S.foo))); 2905 static assert(!isDelegate!(typeof(&S.foo))); 2906 static assert( isDelegate!(typeof(&S.init.foo))); 2907 static assert(!is(SymbolType!(S.foo) == delegate)); 2908 static assert(!is(typeof(&S.foo) == delegate)); 2909 static assert( is(typeof(&S.init.foo) == delegate)); 2910 2911 struct HasContext 2912 { 2913 void foo() { ++var; } 2914 } 2915 static assert(!isDelegate!(SymbolType!(S.foo))); 2916 static assert(!isDelegate!(typeof(&S.foo))); 2917 static assert( isDelegate!(typeof(&S.init.foo))); 2918 static assert(!is(SymbolType!(S.foo) == delegate)); 2919 static assert(!is(typeof(&S.foo) == delegate)); 2920 static assert( is(typeof(&S.init.foo) == delegate)); 2921 } 2922 2923 /++ 2924 Evaluates to $(K_TRUE) if the given type is a function (and to $(K_FALSE) 2925 otherwise). 2926 2927 This is equivalent to $(D is(T == function)), so most code shouldn't use 2928 it. It's intended to be used in conjunction with templates that take a 2929 template predicate - such as those in $(MREF phobos, sys, meta). 2930 2931 Note that this does not include implicit conversions or enum types. The 2932 type itself must be a function. 2933 2934 It's not currently possible in D to type out the type of a function on its 2935 own, so normally, the only way to get a function type is to get the type of 2936 a symbol which is a function. However, $(LREF ToFunctionType) can be used 2937 to convert a function pointer type to a function type for code that needs 2938 that, though that's likely only to come up in $(K_IS) expressions. 2939 2940 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 2941 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 2942 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 2943 of a symbol. 2944 2945 See_Also: 2946 $(LREF isDelegate) 2947 $(LREF isFunctionPointer) 2948 $(LREF isReturn) 2949 $(LREF PropertyType) 2950 $(LREF SymbolType) 2951 $(LREF ToFunctionType) 2952 +/ 2953 enum isFunction(T) = is(T == function); 2954 2955 /// 2956 @safe unittest 2957 { 2958 int var; 2959 static assert(!isFunction!(SymbolType!var)); 2960 static assert(!isFunction!(PropertyType!var)); 2961 static assert(!isFunction!(typeof(&var))); 2962 static assert(!is(SymbolType!var == function)); 2963 static assert(!is(PropertType!var == function)); 2964 static assert(!is(typeof(&var) == function)); 2965 2966 static void func() {} 2967 static assert( isFunction!(SymbolType!func)); 2968 static assert(!isFunction!(typeof(&func))); 2969 static assert( is(SymbolType!func == function)); 2970 static assert(!is(typeof(&func) == function)); 2971 2972 void funcWithContext() { ++var; } 2973 static assert( isFunction!(SymbolType!funcWithContext)); 2974 static assert(!isFunction!(typeof(&funcWithContext))); 2975 static assert( is(SymbolType!funcWithContext == function)); 2976 static assert(!is(typeof(&funcWithContext) == function)); 2977 2978 int function() funcPtr; 2979 static assert(!isFunction!(SymbolType!funcPtr)); 2980 static assert(!isFunction!(PropertyType!funcPtr)); 2981 static assert(!isFunction!(typeof(&funcPtr))); 2982 static assert(!is(SymbolType!funcPtr == function)); 2983 static assert(!is(PropertyType!funcPtr == function)); 2984 static assert(!is(typeof(&funcPtr) == function)); 2985 2986 int delegate() del; 2987 static assert(!isFunction!(SymbolType!del)); 2988 static assert(!isFunction!(PropertyType!del)); 2989 static assert(!isFunction!(typeof(&del))); 2990 static assert(!is(SymbolType!del == function)); 2991 static assert(!is(PropertyType!del == function)); 2992 static assert(!is(typeof(&del) == function)); 2993 2994 // It's possible to get the pointers to the function and the context from a 2995 // delegate in @system code. 2996 static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr))); 2997 static assert( is(typeof(SymbolType!del.ptr) == void*)); 2998 2999 @property static int prop() { return 0; } 3000 static assert( isFunction!(SymbolType!prop)); 3001 static assert(!isFunction!(PropertyType!prop)); 3002 static assert(!isFunction!(typeof(&prop))); 3003 static assert( is(SymbolType!prop == function)); 3004 static assert(!is(PropertyType!prop == function)); 3005 static assert(!is(typeof(&prop) == function)); 3006 3007 @property int propWithContext() { return var; } 3008 static assert( isFunction!(SymbolType!propWithContext)); 3009 static assert(!isFunction!(PropertyType!propWithContext)); 3010 static assert(!isFunction!(typeof(&propWithContext))); 3011 static assert( is(SymbolType!propWithContext == function)); 3012 static assert(!is(PropertyType!propWithContext == function)); 3013 static assert(!is(typeof(&propWithContext) == function)); 3014 3015 static int function() propFuncPtr() @property { return null; } 3016 static assert( isFunction!(SymbolType!propFuncPtr)); 3017 static assert(!isFunction!(PropertyType!propFuncPtr)); 3018 static assert(!isFunction!(typeof(&propFuncPtr))); 3019 static assert( is(SymbolType!propFuncPtr == function)); 3020 static assert(!is(PropertyType!propFuncPtr == function)); 3021 static assert(!is(typeof(&propFuncPtr) == function)); 3022 3023 static int delegate() propDel() @property { return null; } 3024 static assert( isFunction!(SymbolType!propDel)); 3025 static assert(!isFunction!(PropertyType!propDel)); 3026 static assert(!isFunction!(typeof(&propDel))); 3027 static assert( is(SymbolType!propDel == function)); 3028 static assert(!is(PropertyType!propDel == function)); 3029 static assert(!is(typeof(&propDel) == function)); 3030 3031 static struct S 3032 { 3033 void foo() {} 3034 } 3035 static assert( isFunction!(SymbolType!(S.foo))); 3036 static assert(!isFunction!(typeof(&S.foo))); 3037 static assert(!isFunction!(typeof(&S.init.foo))); 3038 static assert( is(SymbolType!(S.foo) == function)); 3039 static assert(!is(typeof(&S.foo) == function)); 3040 static assert(!is(typeof(&S.init.foo) == function)); 3041 3042 struct HasContext 3043 { 3044 void foo() { ++var; } 3045 } 3046 static assert( isFunction!(SymbolType!(S.foo))); 3047 static assert(!isFunction!(typeof(&S.foo))); 3048 static assert(!isFunction!(typeof(&S.init.foo))); 3049 static assert( is(SymbolType!(S.foo) == function)); 3050 static assert(!is(typeof(&S.foo) == function)); 3051 static assert(!is(typeof(&S.init.foo) == function)); 3052 } 3053 3054 /++ 3055 Evaluates to $(K_TRUE) if the given type is a function pointer (and to 3056 $(K_FALSE) otherwise). 3057 3058 Note that this does not include implicit conversions or enum types. The 3059 type itself must be a function pointer. 3060 3061 Whether taking the address of a function results in a function pointer or a 3062 delegate depends on whether the result includes a context pointer. 3063 3064 Taking the address of a free function or a $(K_STATIC) function gives a 3065 function pointer. Taking the address of a non-$(K_STATIC) nested function 3066 gives a delegate. And the potentially confusing one is non-$(K_STATIC) 3067 member functions, because whether taking their address results in a 3068 function pointer or a delegate depends on whether the address is taken via 3069 the type or via an instance. 3070 3071 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 3072 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 3073 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 3074 of a symbol. 3075 3076 See_Also: 3077 $(LREF isDelegate) 3078 $(LREF isFunction) 3079 $(LREF isReturn) 3080 $(LREF PropertyType) 3081 $(LREF SymbolType) 3082 $(LREF ToFunctionType) 3083 +/ 3084 enum isFunctionPointer(T) = is(T == U*, U) && is(U == function); 3085 3086 /// 3087 @safe unittest 3088 { 3089 int var; 3090 static assert(!isFunctionPointer!(SymbolType!var)); 3091 static assert(!isFunctionPointer!(PropertyType!var)); 3092 static assert(!isFunctionPointer!(typeof(&var))); 3093 3094 static void func() {} 3095 static assert(!isFunctionPointer!(SymbolType!func)); 3096 static assert( isFunctionPointer!(typeof(&func))); 3097 3098 void funcWithContext() { ++var; } 3099 static assert(!isFunctionPointer!(SymbolType!funcWithContext)); 3100 static assert(!isFunctionPointer!(typeof(&funcWithContext))); 3101 3102 int function() funcPtr; 3103 static assert( isFunctionPointer!(SymbolType!funcPtr)); 3104 static assert( isFunctionPointer!(PropertyType!funcPtr)); 3105 static assert(!isFunctionPointer!(typeof(&funcPtr))); 3106 3107 int delegate() del; 3108 static assert(!isFunctionPointer!(SymbolType!del)); 3109 static assert(!isFunctionPointer!(PropertyType!del)); 3110 static assert(!isFunctionPointer!(typeof(&del))); 3111 3112 // It's possible to get the pointers to the function and the context from a 3113 // delegate in @system code. 3114 static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr))); 3115 static assert( is(typeof(SymbolType!del.ptr) == void*)); 3116 3117 @property static int prop() { return 0; } 3118 static assert(!isFunctionPointer!(SymbolType!prop)); 3119 static assert(!isFunctionPointer!(PropertyType!prop)); 3120 static assert( isFunctionPointer!(typeof(&prop))); 3121 3122 @property int propWithContext() { return var; } 3123 static assert(!isFunctionPointer!(SymbolType!propWithContext)); 3124 static assert(!isFunctionPointer!(PropertyType!propWithContext)); 3125 static assert(!isFunctionPointer!(typeof(&propWithContext))); 3126 3127 static int function() propFuncPtr() @property { return null; } 3128 static assert(!isFunctionPointer!(SymbolType!propFuncPtr)); 3129 static assert( isFunctionPointer!(PropertyType!propFuncPtr)); 3130 static assert( isFunctionPointer!(typeof(&propFuncPtr))); 3131 3132 static int delegate() propDel() @property { return null; } 3133 static assert(!isFunctionPointer!(SymbolType!propDel)); 3134 static assert(!isFunctionPointer!(PropertyType!propDel)); 3135 static assert( isFunctionPointer!(typeof(&propDel))); 3136 3137 static struct S 3138 { 3139 void foo() {} 3140 } 3141 static assert(!isFunctionPointer!(SymbolType!(S.foo))); 3142 static assert( isFunctionPointer!(typeof(&S.foo))); 3143 static assert(!isFunctionPointer!(typeof(&S.init.foo))); 3144 3145 struct HasContext 3146 { 3147 void foo() { ++var; } 3148 } 3149 static assert(!isFunctionPointer!(SymbolType!(S.foo))); 3150 static assert( isFunctionPointer!(typeof(&S.foo))); 3151 static assert(!isFunctionPointer!(typeof(&S.init.foo))); 3152 } 3153 3154 /++ 3155 Evaluates to $(K_TRUE) if the given type is a function, function pointer, 3156 or delegate (and to $(K_FALSE) otherwise). 3157 3158 This is equivalent to $(D is(T == return)), so most code shouldn't use 3159 it. It's intended to be used in conjunction with templates that take a 3160 template predicate - such as those in $(MREF phobos, sys, meta). 3161 3162 Note that this does not include implicit conversions or enum types. The 3163 type itself must be a function, function pointer, or delegate. 3164 3165 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 3166 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 3167 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 3168 of a symbol. 3169 3170 See_Also: 3171 $(LREF isDelegate) 3172 $(LREF isFunction) 3173 $(LREF isFunctionPointer) 3174 $(LREF PropertyType) 3175 $(LREF SymbolType) 3176 $(LREF ToFunctionType) 3177 +/ 3178 enum isReturn(T) = is(T == return); 3179 3180 /// 3181 @safe unittest 3182 { 3183 int var; 3184 static assert(!isReturn!(SymbolType!var)); 3185 static assert(!isReturn!(PropertyType!var)); 3186 static assert(!isReturn!(typeof(&var))); 3187 static assert(!is(SymbolType!var == return)); 3188 static assert(!is(PropertType!var == return)); 3189 static assert(!is(typeof(&var) == return)); 3190 3191 static void func() {} 3192 static assert( isReturn!(SymbolType!func)); 3193 static assert( isReturn!(typeof(&func))); 3194 static assert( is(SymbolType!func == return)); 3195 static assert( is(typeof(&func) == return)); 3196 3197 void funcWithContext() { ++var; } 3198 static assert( isReturn!(SymbolType!funcWithContext)); 3199 static assert( isReturn!(typeof(&funcWithContext))); 3200 static assert( is(SymbolType!funcWithContext == return)); 3201 static assert( is(typeof(&funcWithContext) == return)); 3202 3203 int function() funcPtr; 3204 static assert( isReturn!(SymbolType!funcPtr)); 3205 static assert( isReturn!(PropertyType!funcPtr)); 3206 static assert(!isReturn!(typeof(&funcPtr))); 3207 static assert( is(SymbolType!funcPtr == return)); 3208 static assert( is(PropertyType!funcPtr == return)); 3209 static assert(!is(typeof(&funcPtr) == return)); 3210 3211 int delegate() del; 3212 static assert( isReturn!(SymbolType!del)); 3213 static assert( isReturn!(PropertyType!del)); 3214 static assert(!isReturn!(typeof(&del))); 3215 static assert( is(SymbolType!del == return)); 3216 static assert( is(PropertyType!del == return)); 3217 static assert(!is(typeof(&del) == return)); 3218 3219 // It's possible to get the pointers to the function and the context from a 3220 // delegate in @system code. 3221 static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr))); 3222 static assert( is(typeof(SymbolType!del.ptr) == void*)); 3223 3224 @property static int prop() { return 0; } 3225 static assert( isReturn!(SymbolType!prop)); 3226 static assert(!isReturn!(PropertyType!prop)); 3227 static assert( isReturn!(typeof(&prop))); 3228 static assert( is(SymbolType!prop == return)); 3229 static assert(!is(PropertyType!prop == return)); 3230 static assert( is(typeof(&prop) == return)); 3231 3232 @property int propWithContext() { return var; } 3233 static assert( isReturn!(SymbolType!propWithContext)); 3234 static assert(!isReturn!(PropertyType!propWithContext)); 3235 static assert( isReturn!(typeof(&propWithContext))); 3236 static assert( is(SymbolType!propWithContext == return)); 3237 static assert(!is(PropertyType!propWithContext == return)); 3238 static assert( is(typeof(&propWithContext) == return)); 3239 3240 static int function() propFuncPtr() @property { return null; } 3241 static assert( isReturn!(SymbolType!propFuncPtr)); 3242 static assert( isReturn!(PropertyType!propFuncPtr)); 3243 static assert( isReturn!(typeof(&propFuncPtr))); 3244 static assert( is(SymbolType!propFuncPtr == return)); 3245 static assert( is(PropertyType!propFuncPtr == return)); 3246 static assert( is(typeof(&propFuncPtr) == return)); 3247 3248 static int delegate() propDel() @property { return null; } 3249 static assert( isReturn!(SymbolType!propDel)); 3250 static assert( isReturn!(PropertyType!propDel)); 3251 static assert( isReturn!(typeof(&propDel))); 3252 static assert( is(SymbolType!propDel == return)); 3253 static assert( is(PropertyType!propDel == return)); 3254 static assert( is(typeof(&propDel) == return)); 3255 3256 static struct S 3257 { 3258 void foo() {} 3259 } 3260 static assert( isReturn!(SymbolType!(S.foo))); 3261 static assert( isReturn!(typeof(&S.foo))); 3262 static assert( isReturn!(typeof(&S.init.foo))); 3263 static assert( is(SymbolType!(S.foo) == return)); 3264 static assert( is(typeof(&S.foo) == return)); 3265 static assert( is(typeof(&S.init.foo) == return)); 3266 3267 struct HasContext 3268 { 3269 void foo() { ++var; } 3270 } 3271 static assert( isReturn!(SymbolType!(S.foo))); 3272 static assert( isReturn!(typeof(&S.foo))); 3273 static assert( isReturn!(typeof(&S.init.foo))); 3274 static assert( is(SymbolType!(S.foo) == return)); 3275 static assert( is(typeof(&S.foo) == return)); 3276 static assert( is(typeof(&S.init.foo) == return)); 3277 } 3278 3279 /++ 3280 Evaluates to the return type of the given function type, function pointer 3281 type, or delegate type. 3282 3283 Note that $(K_REF) is an attribute / storage class, not part of the type. 3284 So, when the return type is marked with $(K_REF), $(K_REF) is an attribute 3285 of the function and not part of the return type. $(LREF functionAttributes) 3286 can be used to determine whether the return value is returned by $(K_REF). 3287 3288 Also note that in most cases, ReturnType is probably not the best solution. 3289 3290 In situations where a function is used as a getter property, then using 3291 $(LREF PropertyType) would usually make more sense than using ReturnType, 3292 particularly since in such a situation, the property could potentially be a 3293 variable, which would not compile with ReturnType. 3294 3295 In situations where a function may be overloaded, it can often make more 3296 sense to get the type of the expression where the function is called 3297 instead of getting the return type of the function itself - e.g. 3298 $(D typeof(foo(42))) instead of $(D ReturnType!(SymbolType!foo)), since 3299 then that will automatically get the correct overload, whereas with 3300 ReturnType, getting the return type of the correct overload would require 3301 using $(D __traits(getOverloads, foo)) and then selecting the correct 3302 overload. Getting the type of the actual function call can also can be less 3303 verbose and require fewer template instantiations, since a function call is 3304 clearly an expression and thus avoids the need for $(LREF SymbolType). 3305 3306 So, with functions which can be used as getter properties, it's often 3307 better to use $(LREF PropertyType) than to use ReturnType, and with 3308 functions which cannot be used as getter properties, it's often better to 3309 simply get the type of the actual function call. So, ReturnType is 3310 usually not the best choice, but there are of course situations where it's 3311 exactly what's needed (e.g. if code already has the symbol or type for a 3312 specific function overload and needs to get its return type). 3313 3314 See_Also: 3315 $(LREF functionAttributes) 3316 $(LREF PropertyType) 3317 $(LREF SymbolType) 3318 +/ 3319 template ReturnType(T) 3320 if (is(T == return)) 3321 { 3322 static if (is(T R == return)) 3323 alias ReturnType = R; 3324 else 3325 static assert(false, "Somehow, ReturnType was instantiated with a type which has no return type"); 3326 } 3327 3328 /// 3329 @safe unittest 3330 { 3331 void foo(); 3332 static assert(is(ReturnType!(SymbolType!foo) == void)); 3333 3334 int bar(); 3335 static assert(is(ReturnType!(SymbolType!bar) == int)); 3336 3337 // ReturnType requires a type. 3338 static assert(!__traits(compiles, ReturnType!bar)); 3339 3340 // ReturnType requires a function type, function pointer type, or delegate 3341 // type, so the result of PropertyType only works with it if the function 3342 // returns such a type. 3343 static assert(!__traits(compiles, ReturnType!(PropertyType!bar))); 3344 3345 string function(int) funcPtr; 3346 static assert(is(ReturnType!(SymbolType!funcPtr) == string)); 3347 3348 int delegate(string) del; 3349 static assert(is(ReturnType!(SymbolType!del) == int)); 3350 3351 int delegate(string) retDel(); 3352 static assert(is(ReturnType!(SymbolType!retDel) == int delegate(string))); 3353 static assert(is(ReturnType!(PropertyType!retDel) == int)); 3354 static assert(is(ReturnType!(typeof(retDel)) == int delegate(string))); 3355 3356 @property int delegate(string) prop(); 3357 static assert(is(ReturnType!(SymbolType!prop) == int delegate(string))); 3358 static assert(is(ReturnType!(PropertyType!prop) == int)); 3359 static assert(is(ReturnType!(typeof(prop)) == int)); 3360 3361 ref int returnByRef(); 3362 static assert(is(ReturnType!(SymbolType!returnByRef) == int)); 3363 } 3364 3365 /// 3366 @safe unittest 3367 { 3368 static struct S 3369 { 3370 void foo(string); 3371 bool foo(string, int); 3372 string foo(); 3373 3374 @property void bar(int); 3375 @property int bar(); 3376 } 3377 3378 // SymbolType gives the type of the first overload, whereas PropertyType 3379 // gives the type of the overload which can be used as a getter property 3380 // (or fails to compile if there is no such overload). Of course, the 3381 // result of PropertyType won't compile with ReturnType unless the property 3382 // gives a function pointer or delegate. 3383 // __traits(getOverloads, ...) can be used to get specific overloads (or to 3384 // iterate through all of them). 3385 { 3386 static assert( is(ReturnType!(SymbolType!(S.foo)) == void)); 3387 static assert( is(PropertyType!(S.foo) == string)); 3388 3389 static assert( is(typeof(S.init.foo("")) == void)); 3390 static assert( is(typeof(S.init.foo("", 42)) == bool)); 3391 static assert( is(typeof(S.init.foo()) == string)); 3392 3393 alias overloads = __traits(getOverloads, S, "foo"); 3394 3395 // string foo(); 3396 static assert( is(ReturnType!(SymbolType!(overloads[0])) == void)); 3397 3398 // void foo(string); 3399 static assert( is(ReturnType!(SymbolType!(overloads[1])) == bool)); 3400 3401 // void foo(string, int); 3402 static assert( is(ReturnType!(SymbolType!(overloads[2])) == string)); 3403 } 3404 { 3405 static assert( is(ReturnType!(SymbolType!(S.bar)) == void)); 3406 static assert( is(PropertyType!(S.bar) == int)); 3407 3408 // Normal function call syntax can be used with @property functions 3409 // (which is obviously not the intended way to use them, but it does 3410 // provide a way to distinguish between overloads). 3411 static assert( is(typeof(S.init.bar(42)) == void)); 3412 static assert( is(typeof(S.init.bar()) == int)); 3413 3414 static assert( is(typeof(S.init.bar = 42) == void)); 3415 static assert( is(PropertyType!(S.init.bar) == int)); 3416 3417 alias overloads = __traits(getOverloads, S, "bar"); 3418 3419 // @property void bar(int); 3420 static assert( is(ReturnType!(SymbolType!(overloads[0])) == void)); 3421 3422 // @property int bar(); 3423 static assert( is(ReturnType!(SymbolType!(overloads[1])) == int)); 3424 } 3425 } 3426 3427 @safe unittest 3428 { 3429 int func1(string); 3430 static assert(is(ReturnType!(SymbolType!func1) == int)); 3431 static assert(!__traits(compiles, ReturnType!func1)); 3432 3433 const(int) func2(string); 3434 static assert(is(ReturnType!(SymbolType!func2) == const int)); 3435 3436 immutable(int) func3(string); 3437 static assert(is(ReturnType!(SymbolType!func3) == immutable int)); 3438 3439 shared(int) func4(string); 3440 static assert(is(ReturnType!(SymbolType!func4) == shared int)); 3441 3442 const(shared(int)) func5(string); 3443 static assert(is(ReturnType!(SymbolType!func5) == const shared int)); 3444 3445 ref int func6(string); 3446 static assert(is(ReturnType!(SymbolType!func6) == int)); 3447 3448 ref const(int) func7(string); 3449 static assert(is(ReturnType!(SymbolType!func7) == const int)); 3450 3451 static struct S 3452 { 3453 real foo(); 3454 real bar() const; 3455 inout(real) baz() inout; 3456 ref real func() shared; 3457 } 3458 static assert(is(ReturnType!(SymbolType!(S.foo)) == real)); 3459 static assert(is(ReturnType!(SymbolType!(S.bar)) == real)); 3460 static assert(is(ReturnType!(SymbolType!(S.baz)) == inout real)); 3461 static assert(is(ReturnType!(SymbolType!(S.func)) == real)); 3462 3463 static class C 3464 { 3465 byte foo() { assert(0); } 3466 byte bar() const { assert(0); } 3467 inout(byte) baz() inout { assert(0); } 3468 ref byte func() shared { assert(0); } 3469 } 3470 static assert(is(ReturnType!(SymbolType!(C.foo)) == byte)); 3471 static assert(is(ReturnType!(SymbolType!(C.bar)) == byte)); 3472 static assert(is(ReturnType!(SymbolType!(C.baz)) == inout byte)); 3473 static assert(is(ReturnType!(SymbolType!(C.func)) == byte)); 3474 3475 static struct NoCopy 3476 { 3477 @disable this(this); 3478 } 3479 static assert(!__traits(isCopyable, NoCopy)); 3480 3481 NoCopy retNC(); 3482 static assert(is(ReturnType!(SymbolType!retNC) == NoCopy)); 3483 } 3484 3485 /++ 3486 Converts a function type, function pointer type, or delegate type to the 3487 corresponding function type. 3488 3489 For a function, the result is the same as the given type. 3490 3491 For a function pointer or delegate, the result is the same as it would be 3492 for a function with the same return type, the same set of parameters, and 3493 the same set of attributes. 3494 3495 Another way to look at it would be that it's the type that comes from 3496 dereferencing the function pointer. And while it's not technically possible 3497 to dereference a delegate, it's conceptually the same thing, since a 3498 delegate is essentially a fat pointer to a function in the sense that it 3499 contains a pointer to a function and a pointer to the function's context. 3500 The result of ToFunctionType is the type of that function. 3501 3502 Note that code which has a symbol which is a function should use 3503 $(LREF SymbolType) rather than $(K_TYPEOF) to get the type of the function 3504 in order to avoid issues with regards to $(K_PROPERTY) (see the 3505 documentation for $(LREF SymbolType) for details). 3506 3507 See_Also: 3508 $(LREF SymbolType) 3509 +/ 3510 template ToFunctionType(T) 3511 if (is(T == return)) 3512 { 3513 // Function pointers. 3514 static if (is(T == U*, U) && is(U == function)) 3515 alias ToFunctionType = U; 3516 // Delegates. 3517 else static if (is(T U == delegate)) 3518 alias ToFunctionType = U; 3519 // Functions. 3520 else 3521 alias ToFunctionType = T; 3522 } 3523 3524 /// 3525 @safe unittest 3526 { 3527 static string func(int) { return ""; } 3528 auto funcPtr = &func; 3529 3530 static assert( is(ToFunctionType!(SymbolType!func) == SymbolType!func)); 3531 static assert( is(ToFunctionType!(SymbolType!funcPtr) == SymbolType!func)); 3532 static assert(!is(SymbolType!funcPtr == function)); 3533 static assert( is(ToFunctionType!(SymbolType!funcPtr) == function)); 3534 3535 int var; 3536 int funcWithContext(string) { return var; } 3537 auto funcDel = &funcWithContext; 3538 3539 static assert( is(ToFunctionType!(SymbolType!funcWithContext) == 3540 SymbolType!funcWithContext)); 3541 static assert( is(ToFunctionType!(SymbolType!funcDel) == 3542 SymbolType!funcWithContext)); 3543 static assert( is(SymbolType!funcWithContext == function)); 3544 static assert(!is(SymbolType!funcDel == function)); 3545 static assert( is(SymbolType!funcDel == delegate)); 3546 static assert( is(ToFunctionType!(SymbolType!funcDel) == function)); 3547 3548 static @property int prop() { return 0; } 3549 static assert( is(SymbolType!prop == function)); 3550 static assert(!is(SymbolType!prop == delegate)); 3551 static assert( is(SymbolType!prop == return)); 3552 static assert( is(SymbolType!prop == 3553 ToFunctionType!(int function() @property @safe pure 3554 nothrow @nogc))); 3555 static assert( is(ToFunctionType!(SymbolType!prop) == SymbolType!prop)); 3556 3557 // This is an example of why SymbolType should be used rather than typeof 3558 // when using ToFunctionType (or getting the type of any symbol which might 3559 // be a function when you want the actual type of the symbol and don't want 3560 // to end up with its return type instead). 3561 static assert( is(typeof(prop) == int)); 3562 static assert(!is(typeof(prop) == function)); 3563 static assert(!__traits(compiles, ToFunctionType!(typeof(prop)))); 3564 3565 auto propPtr = ∝ 3566 static assert(!is(typeof(propPtr) == function)); 3567 static assert(!is(SymbolType!propPtr == function)); 3568 static assert( isFunctionPointer!(typeof(propPtr))); 3569 static assert( is(ToFunctionType!(SymbolType!propPtr) == function)); 3570 3571 static assert( is(SymbolType!propPtr == 3572 int function() @property @safe pure nothrow @nogc)); 3573 static assert(!is(ToFunctionType!(SymbolType!propPtr) == 3574 int function() @property @safe pure nothrow @nogc)); 3575 static assert( is(ToFunctionType!(SymbolType!propPtr) == 3576 ToFunctionType!(int function() @property @safe pure 3577 nothrow @nogc))); 3578 3579 @property void propWithContext(int i) { var += i; } 3580 static assert( is(SymbolType!propWithContext == function)); 3581 static assert( is(SymbolType!propWithContext == 3582 ToFunctionType!(void function(int) @property @safe pure 3583 nothrow @nogc))); 3584 static assert( is(ToFunctionType!(SymbolType!propWithContext) == 3585 SymbolType!propWithContext)); 3586 3587 // typeof fails to compile with setter properties, complaining about there 3588 // not being enough arguments, because it's treating the function as an 3589 // expression - and since such an expression would call the function, the 3590 // expression isn't valid if there aren't enough function arguments. 3591 static assert(!__traits(compiles, typeof(propWithContext))); 3592 3593 auto propDel = &propWithContext; 3594 static assert(!is(SymbolType!propDel == function)); 3595 static assert( is(SymbolType!propDel == delegate)); 3596 static assert( is(SymbolType!propDel == return)); 3597 static assert( is(ToFunctionType!(SymbolType!propDel) == function)); 3598 static assert( is(ToFunctionType!(SymbolType!propDel) == 3599 SymbolType!propWithContext)); 3600 3601 static assert( is(SymbolType!propDel == 3602 void delegate(int) @property @safe pure nothrow @nogc)); 3603 static assert(!is(ToFunctionType!(SymbolType!propDel) == 3604 void delegate(int) @property @safe pure nothrow @nogc)); 3605 static assert(!is(ToFunctionType!(SymbolType!propDel) == 3606 void function(int) @property @safe pure nothrow @nogc)); 3607 static assert( is(ToFunctionType!(SymbolType!propDel) == 3608 ToFunctionType!(void function(int) @property @safe pure 3609 nothrow @nogc))); 3610 3611 // Delegates have a funcptr property and a ptr property (which can only be 3612 // used in @system code) which give the pointer to the function and the 3613 // pointer to the context respectively. 3614 static assert( is(ToFunctionType!(SymbolType!propDel) == 3615 typeof(*SymbolType!propDel.funcptr))); 3616 static assert( is(typeof(SymbolType!propDel.ptr) == void*)); 3617 3618 static struct S 3619 { 3620 string foo(int); 3621 string bar(int, int); 3622 @property void prop(string); 3623 } 3624 3625 static assert( is(ToFunctionType!(SymbolType!(S.foo)) == 3626 ToFunctionType!(string function(int)))); 3627 static assert( is(ToFunctionType!(SymbolType!(S.bar)) == 3628 ToFunctionType!(string function(int, int)))); 3629 static assert( is(ToFunctionType!(SymbolType!(S.prop)) == 3630 ToFunctionType!(void function(string) @property))); 3631 } 3632 3633 @safe unittest 3634 { 3635 // Unfortunately, in this case, we get linker errors when taking the address 3636 // of the functions if we avoid inference by not giving function bodies. 3637 // So if we don't want to list all of those attributes in the tests, we have 3638 // to stop the inference in another way. 3639 static int var; 3640 static void killAttributes() @system { ++var; throw new Exception("message"); } 3641 3642 static struct S 3643 { 3644 int func1() { killAttributes(); return 0; } 3645 void func2(int) { killAttributes(); } 3646 3647 static int func3() { killAttributes(); return 0; } 3648 static void func4(int) { killAttributes(); } 3649 3650 @property int func5() { killAttributes(); return 0; } 3651 @property void func6(int) { killAttributes(); } 3652 } 3653 3654 static assert( is(SymbolType!(S.func1) == ToFunctionType!(int function()))); 3655 static assert( is(SymbolType!(S.func2) == ToFunctionType!(void function(int)))); 3656 static assert( is(SymbolType!(S.func3) == ToFunctionType!(int function()))); 3657 static assert( is(SymbolType!(S.func4) == ToFunctionType!(void function(int)))); 3658 static assert( is(SymbolType!(S.func5) == ToFunctionType!(int function() @property))); 3659 static assert( is(SymbolType!(S.func6) == ToFunctionType!(void function(int) @property))); 3660 3661 static assert( is(ToFunctionType!(SymbolType!(S.func1)) == ToFunctionType!(int function()))); 3662 static assert( is(ToFunctionType!(SymbolType!(S.func2)) == ToFunctionType!(void function(int)))); 3663 static assert( is(ToFunctionType!(SymbolType!(S.func3)) == ToFunctionType!(int function()))); 3664 static assert( is(ToFunctionType!(SymbolType!(S.func4)) == ToFunctionType!(void function(int)))); 3665 static assert( is(ToFunctionType!(SymbolType!(S.func5)) == ToFunctionType!(int function() @property))); 3666 static assert( is(ToFunctionType!(SymbolType!(S.func6)) == 3667 ToFunctionType!(void function(int) @property))); 3668 3669 auto ptr1 = &S.init.func1; 3670 auto ptr2 = &S.init.func2; 3671 auto ptr3 = &S.func3; 3672 auto ptr4 = &S.func4; 3673 auto ptr5 = &S.init.func5; 3674 auto ptr6 = &S.init.func6; 3675 3676 // For better or worse, static member functions can be accessed through 3677 // instance of the type as well as through the type. 3678 auto ptr3Instance = &S.init.func3; 3679 auto ptr4Instance = &S.init.func4; 3680 3681 static assert( is(SymbolType!ptr1 == int delegate())); 3682 static assert( is(SymbolType!ptr2 == void delegate(int))); 3683 static assert( is(SymbolType!ptr3 == int function())); 3684 static assert( is(SymbolType!ptr4 == void function(int))); 3685 static assert( is(SymbolType!ptr5 == int delegate() @property)); 3686 static assert( is(SymbolType!ptr6 == void delegate(int) @property)); 3687 3688 static assert( is(SymbolType!ptr3Instance == int function())); 3689 static assert( is(SymbolType!ptr4Instance == void function(int))); 3690 3691 static assert( is(ToFunctionType!(SymbolType!ptr1) == ToFunctionType!(int function()))); 3692 static assert( is(ToFunctionType!(SymbolType!ptr2) == ToFunctionType!(void function(int)))); 3693 static assert( is(ToFunctionType!(SymbolType!ptr3) == ToFunctionType!(int function()))); 3694 static assert( is(ToFunctionType!(SymbolType!ptr4) == ToFunctionType!(void function(int)))); 3695 static assert( is(ToFunctionType!(SymbolType!ptr5) == ToFunctionType!(int function() @property))); 3696 static assert( is(ToFunctionType!(SymbolType!ptr6) == ToFunctionType!(void function(int) @property))); 3697 3698 static assert( is(ToFunctionType!(SymbolType!ptr3Instance) == ToFunctionType!(int function()))); 3699 static assert( is(ToFunctionType!(SymbolType!ptr4Instance) == ToFunctionType!(void function(int)))); 3700 } 3701 3702 /++ 3703 Evaluates to an $(D AliasSeq) of the names (as $(D string)s) of the member 3704 variables of an aggregate type (i.e. a struct, class, interface, or union). 3705 3706 These are fields which take up memory space within an instance of the type 3707 (i.e. not enums / manifest constants, since they don't take up memory 3708 space, and not static member variables, since they don't take up memory 3709 space within an instance). 3710 3711 Hidden fields (like the virtual function table pointer or the context 3712 pointer for nested types) are not included. 3713 3714 For classes, only the direct member variables are included and not those 3715 of any base classes. 3716 3717 For interfaces, the result of FieldNames is always empty, because 3718 interfaces cannot have member variables. However, because interfaces are 3719 aggregate types, they work with FieldNames for consistency so that code 3720 that's written to work on aggregate types doesn't have to worry about 3721 whether it's dealing with an interface. 3722 3723 See_Also: 3724 $(LREF FieldSymbols) 3725 $(LREF FieldTypes) 3726 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 3727 +/ 3728 template FieldNames(T) 3729 if (isAggregateType!T) 3730 { 3731 import phobos.sys.meta : AliasSeq; 3732 3733 static if (is(T == struct) && __traits(isNested, T)) 3734 private alias Fields = AliasSeq!(T.tupleof[0 .. $ - 1]); 3735 else 3736 private alias Fields = T.tupleof; 3737 3738 alias FieldNames = AliasSeq!(); 3739 static foreach (Field; Fields) 3740 FieldNames = AliasSeq!(FieldNames, Field.stringof); 3741 } 3742 3743 /// 3744 @safe unittest 3745 { 3746 import phobos.sys.meta : AliasSeq; 3747 3748 struct S 3749 { 3750 int x; 3751 float y; 3752 } 3753 static assert(FieldNames!S == AliasSeq!("x", "y")); 3754 3755 // Since the AliasSeq contains values, all of which are of the same type, 3756 // it can be used to create a dynamic array, which would be more 3757 // efficient than operating on an AliasSeq in the cases where an 3758 // AliasSeq is not necessary. 3759 static assert([FieldNames!S] == ["x", "y"]); 3760 3761 class C 3762 { 3763 // static variables are not included. 3764 static int var; 3765 3766 // Manifest constants are not included. 3767 enum lang = "dlang"; 3768 3769 // Functions are not included, even if they're @property functions. 3770 @property int foo() { return 42; } 3771 3772 string s; 3773 int i; 3774 int[] arr; 3775 } 3776 static assert(FieldNames!C == AliasSeq!("s", "i", "arr")); 3777 3778 static assert([FieldNames!C] == ["s", "i", "arr"]); 3779 3780 // Only direct member variables are included. Member variables from any base 3781 // classes are not. 3782 class D : C 3783 { 3784 real r; 3785 } 3786 static assert(FieldNames!D == AliasSeq!"r"); 3787 3788 static assert([FieldNames!D] == ["r"]); 3789 3790 // FieldNames will always be empty for an interface, since it's not legal 3791 // for interfaces to have member variables. 3792 interface I 3793 { 3794 } 3795 static assert(FieldNames!I.length == 0); 3796 3797 union U 3798 { 3799 int i; 3800 double d; 3801 long l; 3802 S s; 3803 } 3804 static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s")); 3805 3806 static assert([FieldNames!U] == ["i", "d", "l", "s"]);; 3807 3808 // FieldNames only operates on aggregate types. 3809 static assert(!__traits(compiles, FieldNames!int)); 3810 static assert(!__traits(compiles, FieldNames!(S*))); 3811 static assert(!__traits(compiles, FieldNames!(C[]))); 3812 } 3813 3814 @safe unittest 3815 { 3816 import phobos.sys.meta : AliasSeq; 3817 3818 { 3819 static struct S0 {} 3820 static assert(FieldNames!S0.length == 0); 3821 3822 static struct S1 { int a; } 3823 static assert(FieldNames!S1 == AliasSeq!"a"); 3824 3825 static struct S2 { int a; string b; } 3826 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 3827 3828 static struct S3 { int a; string b; real c; } 3829 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 3830 } 3831 { 3832 int i; 3833 struct S0 { void foo() { i = 0; }} 3834 static assert(FieldNames!S0.length == 0); 3835 static assert(__traits(isNested, S0)); 3836 3837 struct S1 { int a; void foo() { i = 0; } } 3838 static assert(FieldNames!S1 == AliasSeq!"a"); 3839 static assert(__traits(isNested, S1)); 3840 3841 struct S2 { int a; string b; void foo() { i = 0; } } 3842 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 3843 static assert(__traits(isNested, S2)); 3844 3845 struct S3 { int a; string b; real c; void foo() { i = 0; } } 3846 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 3847 static assert(__traits(isNested, S3)); 3848 } 3849 { 3850 static class C0 {} 3851 static assert(FieldNames!C0.length == 0); 3852 3853 static class C1 { int a; } 3854 static assert(FieldNames!C1 == AliasSeq!"a"); 3855 3856 static class C2 { int a; string b; } 3857 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 3858 3859 static class C3 { int a; string b; real c; } 3860 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 3861 3862 static class D0 : C3 {} 3863 static assert(FieldNames!D0.length == 0); 3864 3865 static class D1 : C3 { bool x; } 3866 static assert(FieldNames!D1 == AliasSeq!"x"); 3867 3868 static class D2 : C3 { bool x; int* y; } 3869 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 3870 3871 static class D3 : C3 { bool x; int* y; short[] z; } 3872 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 3873 } 3874 { 3875 int i; 3876 class C0 { void foo() { i = 0; }} 3877 static assert(FieldNames!C0.length == 0); 3878 static assert(__traits(isNested, C0)); 3879 3880 class C1 { int a; void foo() { i = 0; } } 3881 static assert(FieldNames!C1 == AliasSeq!"a"); 3882 static assert(__traits(isNested, C1)); 3883 3884 class C2 { int a; string b; void foo() { i = 0; } } 3885 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 3886 static assert(__traits(isNested, C2)); 3887 3888 class C3 { int a; string b; real c; void foo() { i = 0; } } 3889 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 3890 static assert(__traits(isNested, C3)); 3891 3892 class D0 : C3 {} 3893 static assert(FieldNames!D0.length == 0); 3894 static assert(__traits(isNested, D0)); 3895 3896 class D1 : C3 { bool x; } 3897 static assert(FieldNames!D1 == AliasSeq!"x"); 3898 static assert(__traits(isNested, D1)); 3899 3900 class D2 : C3 { bool x; int* y; } 3901 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 3902 static assert(__traits(isNested, D2)); 3903 3904 class D3 : C3 { bool x; int* y; short[] z; } 3905 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 3906 static assert(__traits(isNested, D3)); 3907 } 3908 { 3909 static union U0 {} 3910 static assert(FieldNames!U0.length == 0); 3911 3912 static union U1 { int a; } 3913 static assert(FieldNames!U1 == AliasSeq!"a"); 3914 3915 static union U2 { int a; string b; } 3916 static assert(FieldNames!U2 == AliasSeq!("a", "b")); 3917 3918 static union U3 { int a; string b; real c; } 3919 static assert(FieldNames!U3 == AliasSeq!("a", "b", "c")); 3920 } 3921 { 3922 static struct S 3923 { 3924 enum e = 42; 3925 static str = "foobar"; 3926 3927 string name() { return "foo"; } 3928 3929 int[] arr; 3930 3931 struct Inner1 { int i; } 3932 3933 static struct Inner2 { long gnol; } 3934 3935 union { int a; string b; } 3936 3937 alias Foo = Inner1; 3938 } 3939 3940 static assert(FieldNames!S == AliasSeq!("arr", "a", "b")); 3941 static assert(FieldNames!(const S) == AliasSeq!("arr", "a", "b")); 3942 static assert(FieldNames!(S.Inner1) == AliasSeq!"i"); 3943 static assert(FieldNames!(S.Inner2) == AliasSeq!"gnol"); 3944 } 3945 } 3946 3947 /++ 3948 Evaluates to an $(D AliasSeq) of the symbols for the member variables of an 3949 aggregate type (i.e. a struct, class, interface, or union). 3950 3951 These are fields which take up memory space within an instance of the type 3952 (i.e. not enums / manifest constants, since they don't take up memory 3953 space, and not static member variables, since they don't take up memory 3954 space within an instance). 3955 3956 Hidden fields (like the virtual function table pointer or the context 3957 pointer for nested types) are not included. 3958 3959 For classes, only the direct member variables are included and not those 3960 of any base classes. 3961 3962 For interfaces, the result of FieldSymbols is always empty, because 3963 interfaces cannot have member variables. However, because interfaces are 3964 aggregate types, they work with FieldSymbols for consistency so that code 3965 that's written to work on aggregate types doesn't have to worry about 3966 whether it's dealing with an interface. 3967 3968 In most cases, $(D FieldSymbols!T) has the same result as $(D T.tupleof). 3969 The difference is that for nested structs with a context pointer, 3970 $(D T.tupleof) includes the context pointer, whereas $(D FieldSymbols!T) 3971 does not. For non-nested structs, and for classes, interfaces, and unions, 3972 $(D FieldSymbols!T) and $(D T.tupleof) are the same. 3973 3974 So, for most cases, $(D T.tupleof) is sufficient and avoids instantiating 3975 an additional template, but FieldSymbols is provided so that the code that 3976 needs to avoid including context pointers in the list of fields can do so 3977 without the programmer having to figure how to do that correctly. It also 3978 provides a template that's equivalent to what $(LREF FieldNames) and 3979 $(LREF FieldTypes) do in terms of which fields it gives (the difference of 3980 course then being whether you get the symbols, names, or types for the 3981 fields), whereas the behavior for $(D tupleof) is subtly different. 3982 3983 See_Also: 3984 $(LREF FieldNames) 3985 $(LREF FieldTypes) 3986 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 3987 $(DDSUBLINK spec/traits, isNested, $(D __traits(isNested, ...))). 3988 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, ...))). 3989 +/ 3990 template FieldSymbols(T) 3991 if (isAggregateType!T) 3992 { 3993 static if (is(T == struct) && __traits(isNested, T)) 3994 { 3995 import phobos.sys.meta : AliasSeq; 3996 alias FieldSymbols = AliasSeq!(T.tupleof[0 .. $ - 1]); 3997 } 3998 else 3999 alias FieldSymbols = T.tupleof; 4000 } 4001 4002 /// 4003 @safe unittest 4004 { 4005 import phobos.sys.meta : AliasSeq; 4006 4007 struct S 4008 { 4009 int x; 4010 float y; 4011 } 4012 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.x, S.y))); 4013 4014 // FieldSymbols!S and S.tupleof are the same, because S is not nested. 4015 static assert(__traits(isSame, FieldSymbols!S, S.tupleof)); 4016 4017 // Note that type qualifiers _should_ be passed on to the result, but due 4018 // to https://issues.dlang.org/show_bug.cgi?id=24516, they aren't. 4019 // FieldTypes does not have this problem, because it aliases the types 4020 // rather than the symbols, so if you need the types from the symbols, you 4021 // should use either FieldTypes or tupleof until the compiler bug has been 4022 // fixed (and if you use tupleof, you need to avoid aliasing the result 4023 // before getting the types from it). 4024 static assert(is(typeof(FieldSymbols!S[0]) == int)); 4025 4026 // These currently fail when they shouldn't: 4027 //static assert(is(typeof(FieldSymbols!(const S)[0]) == const int)); 4028 //static assert(is(typeof(FieldSymbols!(shared S)[0]) == shared int)); 4029 4030 class C 4031 { 4032 // static variables are not included. 4033 static int var; 4034 4035 // Manifest constants are not included. 4036 enum lang = "dlang"; 4037 4038 // Functions are not included, even if they're @property functions. 4039 @property int foo() { return 42; } 4040 4041 string s; 4042 int i; 4043 int[] arr; 4044 } 4045 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.s, C.i, C.arr))); 4046 4047 // FieldSymbols!C and C.tupleof have the same symbols, because they are 4048 // always the same for classes. 4049 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 4050 4051 // Only direct member variables are included. Member variables from any base 4052 // classes are not. 4053 class D : C 4054 { 4055 real r; 4056 } 4057 static assert(__traits(isSame, FieldSymbols!D, AliasSeq!(D.r))); 4058 static assert(__traits(isSame, FieldSymbols!D, D.tupleof)); 4059 4060 // FieldSymbols will always be empty for an interface, since it's not legal 4061 // for interfaces to have member variables. 4062 interface I 4063 { 4064 } 4065 static assert(FieldSymbols!I.length == 0); 4066 static assert(I.tupleof.length == 0); 4067 4068 union U 4069 { 4070 int i; 4071 double d; 4072 long l; 4073 S s; 4074 } 4075 static assert(__traits(isSame, FieldSymbols!U, AliasSeq!(U.i, U.d, U.l, U.s))); 4076 4077 // FieldSymbols!C and C.tupleof have the same symbols, because they are 4078 // always the same for unions. 4079 static assert(__traits(isSame, FieldSymbols!U, U.tupleof)); 4080 4081 // FieldSymbols only operates on aggregate types. 4082 static assert(!__traits(compiles, FieldSymbols!int)); 4083 static assert(!__traits(compiles, FieldSymbols!(S*))); 4084 static assert(!__traits(compiles, FieldSymbols!(C[]))); 4085 } 4086 4087 /// Some examples with nested types. 4088 @safe unittest 4089 { 4090 import phobos.sys.meta : AliasSeq; 4091 4092 int outside; 4093 4094 struct S 4095 { 4096 long l; 4097 string s; 4098 4099 void foo() { outside = 2; } 4100 } 4101 static assert(__traits(isNested, S)); 4102 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.l, S.s))); 4103 4104 // FieldSymbols!S and S.tupleof are not the same, because S is nested, and 4105 // the context pointer to the outer scope is included in S.tupleof, whereas 4106 // it is excluded from FieldSymbols!S. 4107 static assert(__traits(isSame, S.tupleof[0 .. $ - 1], AliasSeq!(S.l, S.s))); 4108 static assert(S.tupleof[$ - 1].stringof == "this"); 4109 4110 class C 4111 { 4112 bool b; 4113 int* ptr; 4114 4115 void foo() { outside = 7; } 4116 } 4117 static assert(__traits(isNested, C)); 4118 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.b, C.ptr))); 4119 4120 // FieldSymbols!C and C.tupleof have the same symbols, because they are 4121 // always the same for classes. No context pointer is provided as part of 4122 // tupleof for nested classes. 4123 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 4124 4125 // __traits(isNested, ...) is never true for interfaces or unions, since 4126 // they cannot have a context pointer to an outer scope. So, tupleof and 4127 // FieldSymbols will always be the same for interfaces and unions. 4128 } 4129 4130 @safe unittest 4131 { 4132 import phobos.sys.meta : AliasSeq; 4133 4134 { 4135 static struct S0 {} 4136 static assert(FieldSymbols!S0.length == 0); 4137 4138 static struct S1 { int a; } 4139 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 4140 4141 static struct S2 { int a; string b; } 4142 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 4143 4144 static struct S3 { int a; string b; real c; } 4145 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 4146 } 4147 { 4148 int i; 4149 struct S0 { void foo() { i = 0; }} 4150 static assert(FieldSymbols!S0.length == 0); 4151 static assert(__traits(isNested, S0)); 4152 4153 struct S1 { int a; void foo() { i = 0; } } 4154 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 4155 static assert(__traits(isNested, S1)); 4156 4157 struct S2 { int a; string b; void foo() { i = 0; } } 4158 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 4159 static assert(__traits(isNested, S2)); 4160 4161 struct S3 { int a; string b; real c; void foo() { i = 0; } } 4162 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 4163 static assert(__traits(isNested, S3)); 4164 } 4165 { 4166 static class C0 {} 4167 static assert(FieldSymbols!C0.length == 0); 4168 4169 static class C1 { int a; } 4170 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 4171 4172 static class C2 { int a; string b; } 4173 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 4174 4175 static class C3 { int a; string b; real c; } 4176 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 4177 4178 static class D0 : C3 {} 4179 static assert(FieldSymbols!D0.length == 0); 4180 4181 static class D1 : C3 { bool x; } 4182 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 4183 4184 static class D2 : C3 { bool x; int* y; } 4185 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 4186 4187 static class D3 : C3 { bool x; int* y; short[] z; } 4188 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 4189 } 4190 { 4191 int i; 4192 class C0 { void foo() { i = 0; }} 4193 static assert(FieldSymbols!C0.length == 0); 4194 static assert(__traits(isNested, C0)); 4195 4196 class C1 { int a; void foo() { i = 0; } } 4197 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 4198 static assert(__traits(isNested, C1)); 4199 4200 class C2 { int a; string b; void foo() { i = 0; } } 4201 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 4202 static assert(__traits(isNested, C2)); 4203 4204 class C3 { int a; string b; real c; void foo() { i = 0; } } 4205 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 4206 static assert(__traits(isNested, C3)); 4207 4208 class D0 : C3 {} 4209 static assert(FieldSymbols!D0.length == 0); 4210 static assert(__traits(isNested, D0)); 4211 4212 class D1 : C3 { bool x; } 4213 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 4214 static assert(__traits(isNested, D1)); 4215 4216 class D2 : C3 { bool x; int* y; } 4217 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 4218 static assert(__traits(isNested, D2)); 4219 4220 class D3 : C3 { bool x; int* y; short[] z; } 4221 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 4222 static assert(__traits(isNested, D3)); 4223 } 4224 { 4225 static union U0 {} 4226 static assert(FieldSymbols!U0.length == 0); 4227 4228 static union U1 { int a; } 4229 static assert(__traits(isSame, FieldSymbols!U1, AliasSeq!(U1.a))); 4230 4231 static union U2 { int a; string b; } 4232 static assert(__traits(isSame, FieldSymbols!U2, AliasSeq!(U2.a, U2.b))); 4233 4234 static union U3 { int a; string b; real c; } 4235 static assert(__traits(isSame, FieldSymbols!U3, AliasSeq!(U3.a, U3.b, U3.c))); 4236 } 4237 { 4238 static struct S 4239 { 4240 enum e = 42; 4241 static str = "foobar"; 4242 4243 string name() { return "foo"; } 4244 4245 int[] arr; 4246 4247 struct Inner1 { int i; } 4248 4249 static struct Inner2 { long gnol; } 4250 4251 union { int a; string b; } 4252 4253 alias Foo = Inner1; 4254 } 4255 4256 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.arr, S.a, S.b))); 4257 static assert(__traits(isSame, FieldSymbols!(const S), AliasSeq!(S.arr, S.a, S.b))); 4258 static assert(__traits(isSame, FieldSymbols!(S.Inner1), AliasSeq!(S.Inner1.i))); 4259 static assert(__traits(isSame, FieldSymbols!(S.Inner2), AliasSeq!(S.Inner2.gnol))); 4260 } 4261 } 4262 4263 /++ 4264 Evaluates to an $(D AliasSeq) of the types of the member variables of an 4265 aggregate type (i.e. a struct, class, interface, or union). 4266 4267 These are fields which take up memory space within an instance of the type 4268 (i.e. not enums / manifest constants, since they don't take up memory 4269 space, and not static member variables, since they don't take up memory 4270 space within an instance). 4271 4272 Hidden fields (like the virtual function table pointer or the context 4273 pointer for nested types) are not included. 4274 4275 For classes, only the direct member variables are included and not those 4276 of any base classes. 4277 4278 For interfaces, the result of FieldTypes is always empty, because 4279 interfaces cannot have member variables. However, because interfaces are 4280 aggregate types, they work with FieldTypes for consistency so that code 4281 that's written to work on aggregate types doesn't have to worry about 4282 whether it's dealing with an interface. 4283 4284 See_Also: 4285 $(LREF FieldNames) 4286 $(LREF FieldSymbols) 4287 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 4288 +/ 4289 template FieldTypes(T) 4290 if (isAggregateType!T) 4291 { 4292 static if (is(T == struct) && __traits(isNested, T)) 4293 alias FieldTypes = typeof(T.tupleof[0 .. $ - 1]); 4294 else 4295 alias FieldTypes = typeof(T.tupleof); 4296 } 4297 4298 /// 4299 @safe unittest 4300 { 4301 import phobos.sys.meta : AliasSeq; 4302 4303 struct S 4304 { 4305 int x; 4306 float y; 4307 } 4308 static assert(is(FieldTypes!S == AliasSeq!(int, float))); 4309 4310 // Type qualifers will be passed on to the result. 4311 static assert(is(FieldTypes!(const S) == AliasSeq!(const int, const float))); 4312 static assert(is(FieldTypes!(shared S) == AliasSeq!(shared int, shared float))); 4313 4314 class C 4315 { 4316 // static variables are not included. 4317 static int var; 4318 4319 // Manifest constants are not included. 4320 enum lang = "dlang"; 4321 4322 // Functions are not included, even if they're @property functions. 4323 @property int foo() { return 42; } 4324 4325 string s; 4326 int i; 4327 int[] arr; 4328 } 4329 static assert(is(FieldTypes!C == AliasSeq!(string, int, int[]))); 4330 4331 // Only direct member variables are included. Member variables from any base 4332 // classes are not. 4333 class D : C 4334 { 4335 real r; 4336 } 4337 static assert(is(FieldTypes!D == AliasSeq!real)); 4338 4339 // FieldTypes will always be empty for an interface, since it's not legal 4340 // for interfaces to have member variables. 4341 interface I 4342 { 4343 } 4344 static assert(FieldTypes!I.length == 0); 4345 4346 union U 4347 { 4348 int i; 4349 double d; 4350 long l; 4351 S s; 4352 } 4353 static assert(is(FieldTypes!U == AliasSeq!(int, double, long, S))); 4354 4355 // FieldTypes only operates on aggregate types. 4356 static assert(!__traits(compiles, FieldTypes!int)); 4357 static assert(!__traits(compiles, FieldTypes!(S*))); 4358 static assert(!__traits(compiles, FieldTypes!(C[]))); 4359 } 4360 4361 @safe unittest 4362 { 4363 import phobos.sys.meta : AliasSeq; 4364 4365 { 4366 static struct S0 {} 4367 static assert(FieldTypes!S0.length == 0); 4368 4369 static struct S1 { int a; } 4370 static assert(is(FieldTypes!S1 == AliasSeq!int)); 4371 4372 static struct S2 { int a; string b; } 4373 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 4374 4375 static struct S3 { int a; string b; real c; } 4376 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 4377 } 4378 { 4379 int i; 4380 struct S0 { void foo() { i = 0; }} 4381 static assert(FieldTypes!S0.length == 0); 4382 static assert(__traits(isNested, S0)); 4383 4384 struct S1 { int a; void foo() { i = 0; } } 4385 static assert(is(FieldTypes!S1 == AliasSeq!int)); 4386 static assert(__traits(isNested, S1)); 4387 4388 struct S2 { int a; string b; void foo() { i = 0; } } 4389 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 4390 static assert(__traits(isNested, S2)); 4391 4392 struct S3 { int a; string b; real c; void foo() { i = 0; } } 4393 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 4394 static assert(__traits(isNested, S3)); 4395 } 4396 { 4397 static class C0 {} 4398 static assert(FieldTypes!C0.length == 0); 4399 4400 static class C1 { int a; } 4401 static assert(is(FieldTypes!C1 == AliasSeq!int)); 4402 4403 static class C2 { int a; string b; } 4404 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 4405 4406 static class C3 { int a; string b; real c; } 4407 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 4408 4409 static class D0 : C3 {} 4410 static assert(FieldTypes!D0.length == 0); 4411 4412 static class D1 : C3 { bool x; } 4413 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 4414 4415 static class D2 : C3 { bool x; int* y; } 4416 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 4417 4418 static class D3 : C3 { bool x; int* y; short[] z; } 4419 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 4420 } 4421 { 4422 int i; 4423 class C0 { void foo() { i = 0; }} 4424 static assert(FieldTypes!C0.length == 0); 4425 static assert(__traits(isNested, C0)); 4426 4427 class C1 { int a; void foo() { i = 0; } } 4428 static assert(is(FieldTypes!C1 == AliasSeq!int)); 4429 static assert(__traits(isNested, C1)); 4430 4431 class C2 { int a; string b; void foo() { i = 0; } } 4432 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 4433 static assert(__traits(isNested, C2)); 4434 4435 class C3 { int a; string b; real c; void foo() { i = 0; } } 4436 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 4437 static assert(__traits(isNested, C3)); 4438 4439 class D0 : C3 {} 4440 static assert(FieldTypes!D0.length == 0); 4441 static assert(__traits(isNested, D0)); 4442 4443 class D1 : C3 { bool x; } 4444 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 4445 static assert(__traits(isNested, D1)); 4446 4447 class D2 : C3 { bool x; int* y; } 4448 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 4449 static assert(__traits(isNested, D2)); 4450 4451 class D3 : C3 { bool x; int* y; short[] z; } 4452 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 4453 static assert(__traits(isNested, D3)); 4454 } 4455 { 4456 static union U0 {} 4457 static assert(FieldTypes!U0.length == 0); 4458 4459 static union U1 { int a; } 4460 static assert(is(FieldTypes!U1 == AliasSeq!int)); 4461 4462 static union U2 { int a; string b; } 4463 static assert(is(FieldTypes!U2 == AliasSeq!(int, string))); 4464 4465 static union U3 { int a; string b; real c; } 4466 static assert(is(FieldTypes!U3 == AliasSeq!(int, string, real))); 4467 } 4468 { 4469 static struct S 4470 { 4471 enum e = 42; 4472 static str = "foobar"; 4473 4474 string name() { return "foo"; } 4475 4476 int[] arr; 4477 4478 struct Inner1 { int i; } 4479 4480 static struct Inner2 { long gnol; } 4481 4482 union { int a; string b; } 4483 4484 alias Foo = Inner1; 4485 } 4486 4487 static assert(is(FieldTypes!S == AliasSeq!(int[], int, string))); 4488 static assert(is(FieldTypes!(const S) == AliasSeq!(const(int[]), const int, const string))); 4489 static assert(is(FieldTypes!(S.Inner1) == AliasSeq!int)); 4490 static assert(is(FieldTypes!(S.Inner2) == AliasSeq!long)); 4491 } 4492 } 4493 4494 /++ 4495 Whether assigning to a variable of the given type involves either a 4496 user-defined $(D opAssign) or a compiler-generated $(D opAssign) rather than 4497 using the default assignment behavior (which would use $(D memcpy)). The 4498 $(D opAssign) must accept the same type (with compatible qualifiers) as the 4499 type which the $(D opAssign) is declared on for it to count for 4500 hasComplexAssignment. 4501 4502 The compiler will generate an $(D opAssign) for a struct when a member 4503 variable of that struct defines an $(D opAssign). It will also generate one 4504 when the struct has a postblit constructor or destructor (and those can be 4505 either user-defined or compiler-generated). 4506 4507 However, due to $(BUGZILLA 24834), the compiler does not currently generate 4508 an $(D opAssign) for structs that define a copy constructor, and so 4509 hasComplexAssignment is $(D false) for such types unless they have an 4510 explicit $(D opAssign), or the compiler generates one due to a member 4511 variable having an $(D opAssign). 4512 4513 Note that hasComplexAssignment is also $(D true) for static arrays whose 4514 element type has an $(D opAssign), since while the static array itself does 4515 not have an $(D opAssign), the compiler must use the $(D opAssign) of the 4516 elements when assigning to the static array. 4517 4518 Due to $(BUGZILLA 24833), enums never have complex assignment even if their 4519 base type does. Their $(D opAssign) is never called, resulting in incorrect 4520 behavior for such enums. So, because the compiler does not treat them as 4521 having complex assignment, hasComplexAssignment is $(D false) for them. 4522 4523 No other types (including class references, pointers, and unions) 4524 ever have an $(D opAssign) and thus hasComplexAssignment is never $(D true) 4525 for them. It is particularly important to note that unions never have an 4526 $(D opAssign), so if a struct contains a union which contains one or more 4527 members which have an $(D opAssign), that struct will have to have a 4528 user-defined $(D opAssign) which explicitly assigns to the correct member 4529 of the union if you don't want the current value of the union to simply be 4530 memcopied when assigning to the struct. 4531 4532 One big reason that code would need to worry about hasComplexAssignment is 4533 if void initialization is used anywhere. While it might be okay to assign 4534 to uninitialized memory for a type where assignment does a memcopy, 4535 assigning to uninitialized memory will cause serious issues with any 4536 $(D opAssign) which looks at the object before assigning to it (e.g. 4537 because the type uses reference counting). In such cases, 4538 $(REF copyEmplace, core, sys, lifetime) needs to be used instead of 4539 assignment. 4540 4541 See_Also: 4542 $(LREF hasComplexCopying) 4543 $(LREF hasComplexDestruction) 4544 $(DDSUBLINK spec/operatoroverloading, assignment, 4545 The language spec for overloading assignment) 4546 $(DDSUBLINK spec/struct, assign-overload, 4547 The language spec for $(D opAssign) on structs) 4548 +/ 4549 template hasComplexAssignment(T) 4550 { 4551 import core.internal.traits : hasElaborateAssign; 4552 alias hasComplexAssignment = hasElaborateAssign!T; 4553 } 4554 4555 /// 4556 @safe unittest 4557 { 4558 static assert(!hasComplexAssignment!int); 4559 static assert(!hasComplexAssignment!real); 4560 static assert(!hasComplexAssignment!string); 4561 static assert(!hasComplexAssignment!(int[])); 4562 static assert(!hasComplexAssignment!(int[42])); 4563 static assert(!hasComplexAssignment!(int[string])); 4564 static assert(!hasComplexAssignment!Object); 4565 4566 static struct NoOpAssign 4567 { 4568 int i; 4569 } 4570 static assert(!hasComplexAssignment!NoOpAssign); 4571 4572 // For complex assignment, the parameter type must match the type of the 4573 // struct (with compatible qualifiers), but refness does not matter (though 4574 // it will obviously affect whether rvalues will be accepted as well as 4575 // whether non-copyable types will be accepted). 4576 static struct HasOpAssign 4577 { 4578 void opAssign(HasOpAssign) {} 4579 } 4580 static assert( hasComplexAssignment!HasOpAssign); 4581 static assert(!hasComplexAssignment!(const(HasOpAssign))); 4582 4583 static struct HasOpAssignRef 4584 { 4585 void opAssign(ref HasOpAssignRef) {} 4586 } 4587 static assert( hasComplexAssignment!HasOpAssignRef); 4588 static assert(!hasComplexAssignment!(const(HasOpAssignRef))); 4589 4590 static struct HasOpAssignAutoRef 4591 { 4592 void opAssign()(auto ref HasOpAssignAutoRef) {} 4593 } 4594 static assert( hasComplexAssignment!HasOpAssignAutoRef); 4595 static assert(!hasComplexAssignment!(const(HasOpAssignAutoRef))); 4596 4597 // Assigning a mutable value works when opAssign takes const, because 4598 // mutable implicitly converts to const, but assigning to a const variable 4599 // does not work, so normally, a const object is not considered to have 4600 // complex assignment. 4601 static struct HasOpAssignC 4602 { 4603 void opAssign(const HasOpAssignC) {} 4604 } 4605 static assert( hasComplexAssignment!HasOpAssignC); 4606 static assert(!hasComplexAssignment!(const(HasOpAssignC))); 4607 4608 // If opAssign is const, then assigning to a const variable will work, and a 4609 // const object will have complex assignment. However, such a type would 4610 // not normally make sense, since it can't actually be mutated by opAssign. 4611 static struct HasConstOpAssignC 4612 { 4613 void opAssign(const HasConstOpAssignC) const {} 4614 } 4615 static assert( hasComplexAssignment!HasConstOpAssignC); 4616 static assert( hasComplexAssignment!(const(HasConstOpAssignC))); 4617 4618 // For a type to have complex assignment, the types must match aside from 4619 // the qualifiers. So, an opAssign which takes another type does not count 4620 // as complex assignment. 4621 static struct OtherOpAssign 4622 { 4623 void opAssign(int) {} 4624 } 4625 static assert(!hasComplexAssignment!OtherOpAssign); 4626 4627 // The return type doesn't matter for complex assignment, though normally, 4628 // opAssign should either return a reference to the this reference (so that 4629 // assignments can be chained) or void. 4630 static struct HasOpAssignWeirdRet 4631 { 4632 int opAssign(HasOpAssignWeirdRet) { return 42; } 4633 } 4634 static assert( hasComplexAssignment!HasOpAssignWeirdRet); 4635 4636 // The compiler will generate an assignment operator if a member variable 4637 // has one. 4638 static struct HasMemberWithOpAssign 4639 { 4640 HasOpAssign s; 4641 } 4642 static assert( hasComplexAssignment!HasMemberWithOpAssign); 4643 4644 // The compiler will generate an assignment operator if the type has a 4645 // postblit constructor or a destructor. 4646 static struct HasDtor 4647 { 4648 ~this() {} 4649 } 4650 static assert( hasComplexAssignment!HasDtor); 4651 4652 // If a struct has @disabled opAssign (and thus assigning to a variable of 4653 // that type will result in a compilation error), then 4654 // hasComplexAssignment is false. 4655 // Code that wants to check whether assignment works will need to test that 4656 // assigning to a variable of that type compiles (which could need to test 4657 // both an lvalue and an rvalue depending on the exact sort of assignment 4658 // the code is actually going to do). 4659 static struct DisabledOpAssign 4660 { 4661 @disable void opAssign(DisabledOpAssign); 4662 } 4663 static assert(!hasComplexAssignment!DisabledOpAssign); 4664 static assert(!__traits(compiles, { DisabledOpAssign s; 4665 s = rvalueOf!DisabledOpAssign; 4666 s = lvalueOf!DisabledOpAssign; })); 4667 static assert(!is(typeof({ DisabledOpAssign s; 4668 s = rvalueOf!DisabledOpAssign; 4669 s = lvalueOf!DisabledOpAssign; }))); 4670 4671 // Static arrays have complex assignment if their elements do. 4672 static assert( hasComplexAssignment!(HasOpAssign[1])); 4673 4674 // Static arrays with no elements do not have complex assignment, because 4675 // there's nothing to assign to. 4676 static assert(!hasComplexAssignment!(HasOpAssign[0])); 4677 4678 // Dynamic arrays do not have complex assignment, because assigning to them 4679 // just slices them rather than assigning to their elements. Assigning to 4680 // an array with a slice operation - e.g. arr[0 .. 5] = other[0 .. 5]; - 4681 // does use opAssign if the elements have it, but since assigning to the 4682 // array itself does not, hasComplexAssignment is false for dynamic arrays. 4683 static assert(!hasComplexAssignment!(HasOpAssign[])); 4684 4685 // Classes and unions do not have complex assignment even if they have 4686 // members which do. 4687 class C 4688 { 4689 HasOpAssign s; 4690 } 4691 static assert(!hasComplexAssignment!C); 4692 4693 union U 4694 { 4695 HasOpAssign s; 4696 } 4697 static assert(!hasComplexAssignment!U); 4698 4699 // https://issues.dlang.org/show_bug.cgi?id=24833 4700 // This static assertion fails, because the compiler 4701 // currently ignores assignment operators for enum types. 4702 enum E : HasOpAssign { a = HasOpAssign.init } 4703 //static assert( hasComplexAssignment!E); 4704 } 4705 4706 @safe unittest 4707 { 4708 import phobos.sys.meta : AliasSeq; 4709 4710 { 4711 struct S1 { int i; } 4712 struct S2 { real r; } 4713 struct S3 { string s; } 4714 struct S4 { int[] arr; } 4715 struct S5 { int[0] arr; } 4716 struct S6 { int[42] arr; } 4717 struct S7 { int[string] aa; } 4718 4719 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 4720 { 4721 static assert(!hasComplexAssignment!T); 4722 static assert(!hasComplexAssignment!(T[0])); 4723 static assert(!hasComplexAssignment!(T[42])); 4724 static assert(!hasComplexAssignment!(T[])); 4725 } 4726 } 4727 4728 // Basic variations of opAssign. 4729 { 4730 static struct S { void opAssign(S) {} } 4731 static assert( hasComplexAssignment!S); 4732 4733 static struct S2 { S s; } 4734 static assert( hasComplexAssignment!S2); 4735 } 4736 { 4737 static struct S { void opAssign(ref S) {} } 4738 static assert( hasComplexAssignment!S); 4739 4740 static struct S2 { S s; } 4741 static assert( hasComplexAssignment!S2); 4742 } 4743 { 4744 static struct S { void opAssign()(auto ref S) {} } 4745 static assert( hasComplexAssignment!S); 4746 4747 static struct S2 { S s; } 4748 static assert( hasComplexAssignment!S2); 4749 } 4750 { 4751 static struct S { ref opAssign(S) { return this; } } 4752 static assert( hasComplexAssignment!S); 4753 4754 static struct S2 { S s; } 4755 static assert( hasComplexAssignment!S2); 4756 } 4757 { 4758 static struct S { ref opAssign(ref S) { return this; } } 4759 static assert( hasComplexAssignment!S); 4760 4761 static struct S2 { S s; } 4762 static assert( hasComplexAssignment!S2); 4763 } 4764 { 4765 static struct S { ref opAssign()(auto ref S) { return this; } } 4766 static assert( hasComplexAssignment!S); 4767 4768 static struct S2 { S s; } 4769 static assert( hasComplexAssignment!S2); 4770 } 4771 { 4772 static struct S { ref opAssign(T)(auto ref T) { return this; } } 4773 static assert( hasComplexAssignment!S); 4774 4775 static struct S2 { S s; } 4776 static assert( hasComplexAssignment!S2); 4777 } 4778 4779 // Non-complex opAssign. 4780 { 4781 static struct S { ref opAssign(int) { return this; } } 4782 static assert(!hasComplexAssignment!S); 4783 4784 static struct S2 { S s; } 4785 static assert(!hasComplexAssignment!S2); 4786 } 4787 { 4788 struct Other {} 4789 static struct S { ref opAssign(Other) { return this; } } 4790 static assert(!hasComplexAssignment!S); 4791 4792 static struct S2 { S s; } 4793 static assert(!hasComplexAssignment!S2); 4794 } 4795 4796 // Multiple opAssigns. 4797 { 4798 static struct S 4799 { 4800 void opAssign(S) {} 4801 void opAssign(int) {} 4802 } 4803 static assert( hasComplexAssignment!S); 4804 4805 static struct S2 { S s; } 4806 static assert( hasComplexAssignment!S2); 4807 } 4808 { 4809 // This just flips the order of the previous test to catch potential 4810 // bugs related to the order of declaration, since that's occasionally 4811 // popped up in the compiler in other contexts. 4812 static struct S 4813 { 4814 void opAssign(int) {} 4815 void opAssign(S) {} 4816 } 4817 static assert( hasComplexAssignment!S); 4818 4819 static struct S2 { S s; } 4820 static assert( hasComplexAssignment!S2); 4821 } 4822 { 4823 static struct S 4824 { 4825 void opAssign(S) {} 4826 void opAssign(ref S) {} 4827 void opAssign(const ref S) {} 4828 } 4829 static assert( hasComplexAssignment!S); 4830 4831 static struct S2 { S s; } 4832 static assert( hasComplexAssignment!S2); 4833 } 4834 4835 // Make sure that @disabled alternate opAssigns don't cause issues. 4836 { 4837 static struct S 4838 { 4839 void opAssign(S) {} 4840 @disable void opAssign(ref S) {} 4841 } 4842 static assert( hasComplexAssignment!S); 4843 4844 // See https://issues.dlang.org/show_bug.cgi?id=24854 4845 // The compiler won't generate any opAssign (even if it theoretically 4846 // can) if the member variable has an @disabled opAssign which counts as 4847 // complex assignment. 4848 static struct S2 { S s; } 4849 static assert(!hasComplexAssignment!S2); 4850 } 4851 { 4852 static struct S 4853 { 4854 void opAssign(T)(T) {} 4855 @disable void opAssign(T)(ref T) {} 4856 } 4857 static assert( hasComplexAssignment!S); 4858 4859 static struct S2 { S s; } 4860 static assert(!hasComplexAssignment!S2); 4861 } 4862 { 4863 static struct S 4864 { 4865 @disable void opAssign(S) {} 4866 void opAssign(ref S) {} 4867 } 4868 static assert( hasComplexAssignment!S); 4869 4870 static struct S2 { S s; } 4871 static assert(!hasComplexAssignment!S2); 4872 } 4873 { 4874 static struct S 4875 { 4876 @disable void opAssign(T)(T) {} 4877 void opAssign(T)(ref T) {} 4878 } 4879 static assert( hasComplexAssignment!S); 4880 4881 static struct S2 { S s; } 4882 static assert(!hasComplexAssignment!S2); 4883 } 4884 { 4885 static struct S 4886 { 4887 void opAssign(S) {} 4888 @disable void opAssign(int) {} 4889 } 4890 static assert( hasComplexAssignment!S); 4891 4892 static struct S2 { S s; } 4893 static assert( hasComplexAssignment!S2); 4894 } 4895 { 4896 // The same as the previous test but in reverse order just to catch 4897 // compiler bugs related to the order of declaration. 4898 static struct S 4899 { 4900 @disable void opAssign(int) {} 4901 void opAssign(S) {} 4902 } 4903 static assert( hasComplexAssignment!S); 4904 4905 static struct S2 { S s; } 4906 static assert( hasComplexAssignment!S2); 4907 } 4908 4909 // Generated opAssign due to other functions. 4910 { 4911 static struct S { this(this) {} } 4912 static assert( hasComplexAssignment!S); 4913 4914 static struct S2 { S s; } 4915 static assert( hasComplexAssignment!S2); 4916 } 4917 // https://issues.dlang.org/show_bug.cgi?id=24834 4918 /+ 4919 { 4920 static struct S { this(ref S) {} } 4921 static assert( hasComplexAssignment!S); 4922 4923 static struct S2 { S s; } 4924 static assert( hasComplexAssignment!S2); 4925 } 4926 +/ 4927 { 4928 static struct S { ~this() {} } 4929 static assert( hasComplexAssignment!S); 4930 4931 static struct S2 { S s; } 4932 static assert( hasComplexAssignment!S2); 4933 } 4934 4935 { 4936 static struct S 4937 { 4938 this(this) {} 4939 @disable void opAssign()(auto ref S) {} 4940 } 4941 static assert(!hasComplexAssignment!S); 4942 4943 static struct S2 { S s; } 4944 static assert(!hasComplexAssignment!S2); 4945 } 4946 { 4947 static struct S 4948 { 4949 this(this) {} 4950 void opAssign()(auto ref S) {} 4951 @disable void opAssign(int) {} 4952 } 4953 static assert( hasComplexAssignment!S); 4954 4955 static struct S2 { S s; } 4956 static assert( hasComplexAssignment!S2); 4957 } 4958 4959 // Static arrays 4960 { 4961 static struct S { void opAssign(S) {} } 4962 static assert( hasComplexAssignment!S); 4963 4964 static assert(!hasComplexAssignment!(S[0])); 4965 static assert( hasComplexAssignment!(S[12])); 4966 static assert(!hasComplexAssignment!(S[])); 4967 4968 static struct S2 { S[42] s; } 4969 static assert( hasComplexAssignment!S2); 4970 } 4971 } 4972 4973 /++ 4974 Whether copying an object of the given type involves either a user-defined 4975 copy / postblit constructor or a compiler-generated copy / postblit 4976 constructor rather than using the default copying behavior (which would use 4977 $(D memcpy)). 4978 4979 The compiler will generate a copy / postblit constructor for a struct when 4980 a member variable of that struct defines a copy / postblit constructor. 4981 4982 Note that hasComplexCopying is also $(D true) for static arrays whose 4983 element type has a copy constructor or postblit constructor, since while 4984 the static array itself does not have a copy constructor or postblit 4985 constructor, the compiler must use the copy / postblit constructor of the 4986 elements when copying the static array. 4987 4988 Due to $(BUGZILLA 24833), enums never have complex copying even if their 4989 base type does. Their copy / postblit constructor is never called, 4990 resulting in incorrect behavior for such enums. So, because the compiler 4991 does not treat them as having complex copying, hasComplexCopying is 4992 $(D false) for them. 4993 4994 No other types (including class references, pointers, and unions) ever have 4995 a copy constructor or postblit constructor and thus hasComplexCopying is 4996 never $(D true) for them. It is particularly important to note that unions 4997 never have a copy constructor or postblit constructor, so if a struct 4998 contains a union which contains one or more members which have a copy 4999 constructor or postblit constructor, that struct will have to have a 5000 user-defined copy constructor or posthblit constructor which explicitly 5001 copies the correct member of the union if you don't want the current value 5002 of the union to simply be memcopied when copying the struct. 5003 5004 If a particular piece of code cares about the existence of a copy 5005 constructor or postblit constructor specifically rather than if a type has 5006 one or the other, the traits 5007 $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T))) 5008 and 5009 $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) can 5010 be used, though note that they will not be true for static arrays. 5011 5012 See_Also: 5013 $(LREF hasComplexAssignment) 5014 $(LREF hasComplexDestruction) 5015 $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T))) 5016 $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) 5017 $(DDSUBLINK spec/traits, isCopyable, $(D __traits(isCopyable, T))) 5018 $(DDSUBLINK spec/structs, struct-copy-constructor, The language spec for copy constructors) 5019 $(DDSUBLINK spec/structs, struct-postblit, The language spec for postblit constructors) 5020 +/ 5021 template hasComplexCopying(T) 5022 { 5023 import core.internal.traits : hasElaborateCopyConstructor; 5024 alias hasComplexCopying = hasElaborateCopyConstructor!T; 5025 } 5026 5027 /// 5028 @safe unittest 5029 { 5030 static assert(!hasComplexCopying!int); 5031 static assert(!hasComplexCopying!real); 5032 static assert(!hasComplexCopying!string); 5033 static assert(!hasComplexCopying!(int[])); 5034 static assert(!hasComplexCopying!(int[42])); 5035 static assert(!hasComplexCopying!(int[string])); 5036 static assert(!hasComplexCopying!Object); 5037 5038 static struct NoCopyCtor1 5039 { 5040 int i; 5041 } 5042 static assert(!hasComplexCopying!NoCopyCtor1); 5043 static assert(!__traits(hasCopyConstructor, NoCopyCtor1)); 5044 static assert(!__traits(hasPostblit, NoCopyCtor1)); 5045 5046 static struct NoCopyCtor2 5047 { 5048 int i; 5049 5050 this(int i) 5051 { 5052 this.i = i; 5053 } 5054 } 5055 static assert(!hasComplexCopying!NoCopyCtor2); 5056 static assert(!__traits(hasCopyConstructor, NoCopyCtor2)); 5057 static assert(!__traits(hasPostblit, NoCopyCtor2)); 5058 5059 struct HasCopyCtor 5060 { 5061 this(ref HasCopyCtor) 5062 { 5063 } 5064 } 5065 static assert( hasComplexCopying!HasCopyCtor); 5066 static assert( __traits(hasCopyConstructor, HasCopyCtor)); 5067 static assert(!__traits(hasPostblit, HasCopyCtor)); 5068 5069 // hasComplexCopying does not take constness into account. 5070 // Code that wants to check whether copying works will need to test 5071 // __traits(isCopyable, T) or test that copying compiles. 5072 static assert( hasComplexCopying!(const HasCopyCtor)); 5073 static assert( __traits(hasCopyConstructor, const HasCopyCtor)); 5074 static assert(!__traits(hasPostblit, const HasCopyCtor)); 5075 static assert(!__traits(isCopyable, const HasCopyCtor)); 5076 static assert(!__traits(compiles, { const HasCopyCtor h; 5077 auto h2 = h; })); 5078 static assert(!is(typeof({ const HasCopyCtor h1; 5079 auto h2 = h1; }))); 5080 5081 // An rvalue constructor is not a copy constructor. 5082 struct HasRValueCtor 5083 { 5084 this(HasRValueCtor) 5085 { 5086 } 5087 } 5088 static assert(!hasComplexCopying!HasRValueCtor); 5089 static assert(!__traits(hasCopyConstructor, HasRValueCtor)); 5090 static assert(!__traits(hasPostblit, HasRValueCtor)); 5091 5092 struct HasPostblit 5093 { 5094 this(this) 5095 { 5096 } 5097 } 5098 static assert( hasComplexCopying!HasPostblit); 5099 static assert(!__traits(hasCopyConstructor, HasPostblit)); 5100 static assert( __traits(hasPostblit, HasPostblit)); 5101 5102 // The compiler will generate a copy constructor if a member variable 5103 // has one. 5104 static struct HasMemberWithCopyCtor 5105 { 5106 HasCopyCtor s; 5107 } 5108 static assert( hasComplexCopying!HasMemberWithCopyCtor); 5109 5110 // The compiler will generate a postblit constructor if a member variable 5111 // has one. 5112 static struct HasMemberWithPostblit 5113 { 5114 HasPostblit s; 5115 } 5116 static assert( hasComplexCopying!HasMemberWithPostblit); 5117 5118 // If a struct has @disabled copying, hasComplexCopying is still true. 5119 // Code that wants to check whether copying works will need to test 5120 // __traits(isCopyable, T) or test that copying compiles. 5121 static struct DisabledCopying 5122 { 5123 @disable this(this); 5124 @disable this(ref DisabledCopying); 5125 } 5126 static assert( hasComplexCopying!DisabledCopying); 5127 static assert(!__traits(isCopyable, DisabledCopying)); 5128 static assert(!__traits(compiles, { DisabledCopying dc1; 5129 auto dc2 = dc1; })); 5130 static assert(!is(typeof({ DisabledCopying dc1; 5131 auto dc2 = dc1; }))); 5132 5133 // Static arrays have complex copying if their elements do. 5134 static assert( hasComplexCopying!(HasCopyCtor[1])); 5135 static assert( hasComplexCopying!(HasPostblit[1])); 5136 5137 // Static arrays with no elements do not have complex copying, because 5138 // there's nothing to copy. 5139 static assert(!hasComplexCopying!(HasCopyCtor[0])); 5140 static assert(!hasComplexCopying!(HasPostblit[0])); 5141 5142 // Dynamic arrays do not have complex copying, because copying them 5143 // just slices them rather than copying their elements. 5144 static assert(!hasComplexCopying!(HasCopyCtor[])); 5145 static assert(!hasComplexCopying!(HasPostblit[])); 5146 5147 // Classes and unions do not have complex copying even if they have 5148 // members which do. 5149 class C 5150 { 5151 HasCopyCtor s; 5152 } 5153 static assert(!hasComplexCopying!C); 5154 5155 union U 5156 { 5157 HasCopyCtor s; 5158 } 5159 static assert(!hasComplexCopying!U); 5160 5161 // https://issues.dlang.org/show_bug.cgi?id=24833 5162 // This static assertion fails, because the compiler 5163 // currently ignores assignment operators for enum types. 5164 enum E : HasCopyCtor { a = HasCopyCtor.init } 5165 //static assert( hasComplexCopying!E); 5166 } 5167 5168 @safe unittest 5169 { 5170 import phobos.sys.meta : AliasSeq; 5171 5172 { 5173 struct S1 { int i; } 5174 struct S2 { real r; } 5175 struct S3 { string s; } 5176 struct S4 { int[] arr; } 5177 struct S5 { int[0] arr; } 5178 struct S6 { int[42] arr; } 5179 struct S7 { int[string] aa; } 5180 5181 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 5182 { 5183 static assert(!hasComplexCopying!T); 5184 static assert(!hasComplexCopying!(T[0])); 5185 static assert(!hasComplexCopying!(T[42])); 5186 static assert(!hasComplexCopying!(T[])); 5187 } 5188 } 5189 5190 // Basic variations of copy constructors. 5191 { 5192 static struct S { this(ref S) {} } 5193 static assert( hasComplexCopying!S); 5194 5195 static struct S2 { S s; } 5196 static assert( hasComplexCopying!S2); 5197 } 5198 { 5199 static struct S { this(const ref S) const {} } 5200 static assert( hasComplexCopying!S); 5201 5202 static struct S2 { S s; } 5203 static assert( hasComplexCopying!S2); 5204 } 5205 { 5206 static struct S 5207 { 5208 this(ref S) {} 5209 this(const ref S) const {} 5210 } 5211 static assert( hasComplexCopying!S); 5212 5213 static struct S2 { S s; } 5214 static assert( hasComplexCopying!S2); 5215 } 5216 { 5217 static struct S { this(inout ref S) inout {} } 5218 static assert( hasComplexCopying!S); 5219 5220 static struct S2 { S s; } 5221 static assert( hasComplexCopying!S2); 5222 } 5223 { 5224 static struct S { this(scope ref S) {} } 5225 static assert( hasComplexCopying!S); 5226 5227 static struct S2 { S s; } 5228 static assert( hasComplexCopying!S2); 5229 } 5230 { 5231 static struct S { this(scope ref S) scope {} } 5232 static assert( hasComplexCopying!S); 5233 5234 static struct S2 { S s; } 5235 static assert( hasComplexCopying!S2); 5236 } 5237 { 5238 static struct S { this(ref S) @safe {} } 5239 static assert( hasComplexCopying!S); 5240 5241 static struct S2 { S s; } 5242 static assert( hasComplexCopying!S2); 5243 } 5244 { 5245 static struct S { this(ref S) nothrow {} } 5246 static assert( hasComplexCopying!S); 5247 5248 static struct S2 { S s; } 5249 static assert( hasComplexCopying!S2); 5250 } 5251 { 5252 static struct S { this(scope inout ref S) inout scope @safe pure nothrow @nogc {} } 5253 static assert( hasComplexCopying!S); 5254 5255 static struct S2 { S s; } 5256 static assert( hasComplexCopying!S2); 5257 } 5258 5259 // Basic variations of postblit constructors. 5260 { 5261 static struct S { this(this) {} } 5262 static assert( hasComplexCopying!S); 5263 5264 static struct S2 { S s; } 5265 static assert( hasComplexCopying!S2); 5266 } 5267 { 5268 static struct S { this(this) scope @safe pure nothrow @nogc {} } 5269 static assert( hasComplexCopying!S); 5270 5271 static struct S2 { S s; } 5272 static assert( hasComplexCopying!S2); 5273 } 5274 5275 // Rvalue constructors. 5276 { 5277 static struct S { this(S) {} } 5278 static assert(!hasComplexCopying!S); 5279 5280 static struct S2 { S s; } 5281 static assert(!hasComplexCopying!S2); 5282 } 5283 { 5284 static struct S { this(const S) const {} } 5285 static assert(!hasComplexCopying!S); 5286 5287 static struct S2 { S s; } 5288 static assert(!hasComplexCopying!S2); 5289 } 5290 { 5291 static struct S 5292 { 5293 this(S) {} 5294 this(const S) const {} 5295 } 5296 static assert(!hasComplexCopying!S); 5297 5298 static struct S2 { S s; } 5299 static assert(!hasComplexCopying!S2); 5300 } 5301 { 5302 static struct S { this(inout S) inout {} } 5303 static assert(!hasComplexCopying!S); 5304 5305 static struct S2 { S s; } 5306 static assert(!hasComplexCopying!S2); 5307 } 5308 { 5309 static struct S { this(S) @safe {} } 5310 static assert(!hasComplexCopying!S); 5311 5312 static struct S2 { S s; } 5313 static assert(!hasComplexCopying!S2); 5314 } 5315 { 5316 static struct S { this(S) nothrow {} } 5317 static assert(!hasComplexCopying!S); 5318 5319 static struct S2 { S s; } 5320 static assert(!hasComplexCopying!S2); 5321 } 5322 { 5323 static struct S { this(inout S) inout @safe pure nothrow @nogc {} } 5324 static assert(!hasComplexCopying!S); 5325 5326 static struct S2 { S s; } 5327 static assert(!hasComplexCopying!S2); 5328 } 5329 5330 // @disabled copy constructors. 5331 { 5332 static struct S { @disable this(ref S) {} } 5333 static assert( hasComplexCopying!S); 5334 5335 static struct S2 { S s; } 5336 static assert( hasComplexCopying!S2); 5337 } 5338 { 5339 static struct S { @disable this(const ref S) const {} } 5340 static assert( hasComplexCopying!S); 5341 5342 static struct S2 { S s; } 5343 static assert( hasComplexCopying!S2); 5344 } 5345 { 5346 static struct S 5347 { 5348 @disable this(ref S) {} 5349 this(const ref S) const {} 5350 } 5351 static assert( hasComplexCopying!S); 5352 5353 static struct S2 { S s; } 5354 static assert( hasComplexCopying!S2); 5355 } 5356 { 5357 static struct S 5358 { 5359 this(ref S) {} 5360 @disable this(const ref S) const {} 5361 } 5362 static assert( hasComplexCopying!S); 5363 5364 static struct S2 { S s; } 5365 static assert( hasComplexCopying!S2); 5366 } 5367 { 5368 static struct S 5369 { 5370 @disable this(ref S) {} 5371 @disable this(const ref S) const {} 5372 } 5373 static assert( hasComplexCopying!S); 5374 5375 static struct S2 { S s; } 5376 static assert( hasComplexCopying!S2); 5377 } 5378 5379 // Static arrays 5380 { 5381 static struct S { this(ref S) {} } 5382 static assert( hasComplexCopying!S); 5383 5384 static assert(!hasComplexCopying!(S[0])); 5385 static assert( hasComplexCopying!(S[12])); 5386 static assert(!hasComplexCopying!(S[])); 5387 5388 static struct S2 { S[42] s; } 5389 static assert( hasComplexCopying!S2); 5390 } 5391 { 5392 static struct S { this(this) {} } 5393 static assert( hasComplexCopying!S); 5394 5395 static assert(!hasComplexCopying!(S[0])); 5396 static assert( hasComplexCopying!(S[12])); 5397 static assert(!hasComplexCopying!(S[])); 5398 5399 static struct S2 { S[42] s; } 5400 static assert( hasComplexCopying!S2); 5401 } 5402 } 5403 5404 /++ 5405 Whether the given type has either a user-defined destructor or a 5406 compiler-generated destructor. 5407 5408 The compiler will generate a destructor for a struct when a member variable 5409 of that struct defines a destructor. 5410 5411 Note that hasComplexDestruction is also $(D true) for static arrays whose 5412 element type has a destructor, since while the static array itself does not 5413 have a destructor, the compiler must use the destructor of the elements 5414 when destroying the static array. 5415 5416 Due to $(BUGZILLA 24833), enums never have complex destruction even if their 5417 base type does. Their destructor is never called, resulting in incorrect 5418 behavior for such enums. So, because the compiler does not treat them as 5419 having complex destruction, hasComplexDestruction is $(D false) for them. 5420 5421 Note that while the $(DDSUBLINK spec/class, destructors, language spec) 5422 currently refers to $(D ~this()) on classes as destructors (whereas the 5423 runtime refers to them as finalizers, and they're arguably finalizers 5424 rather than destructors given how they work), classes are not considered to 5425 have complex destruction. Under normal circumstances, it's just the GC or 5426 $(REF1 destroy, object) which calls the destructor / finalizer on a class 5427 (and it's not guaranteed that a class destructor / finalizer will even ever 5428 be called), which is in stark contrast to structs, which normally live on 5429 the stack and need to be destroyed when they leave scope. So, 5430 hasComplexDestruction is concerned with whether that type will have a 5431 destructor that's run when it leaves scope and not with what happens when 5432 the GC destroys an object prior to freeing its memory. 5433 5434 No other types (including pointers and unions) ever have a destructor and 5435 thus hasComplexDestruction is never $(D true) for them. It is particularly 5436 important to note that unions never have a destructor, so if a struct 5437 contains a union which contains one or more members which have a 5438 destructor, that struct will have to have a user-defined destructor which 5439 explicitly calls $(REF1 destroy, object) on the correct member of the 5440 union if you want the object in question to be destroyed properly. 5441 5442 See_Also: 5443 $(LREF hasComplexAssignment) 5444 $(LREF hasComplexCopying) 5445 $(REF destroy, object) 5446 $(DDSUBLINK spec/structs, struct-destructor, The language spec for destructors) 5447 $(DDSUBLINK spec/class, destructors, The language spec for class finalizers) 5448 +/ 5449 template hasComplexDestruction(T) 5450 { 5451 import core.internal.traits : hasElaborateDestructor; 5452 alias hasComplexDestruction = hasElaborateDestructor!T; 5453 } 5454 5455 /// 5456 @safe unittest 5457 { 5458 static assert(!hasComplexDestruction!int); 5459 static assert(!hasComplexDestruction!real); 5460 static assert(!hasComplexDestruction!string); 5461 static assert(!hasComplexDestruction!(int[])); 5462 static assert(!hasComplexDestruction!(int[42])); 5463 static assert(!hasComplexDestruction!(int[string])); 5464 static assert(!hasComplexDestruction!Object); 5465 5466 static struct NoDtor 5467 { 5468 int i; 5469 } 5470 static assert(!hasComplexDestruction!NoDtor); 5471 5472 struct HasDtor 5473 { 5474 ~this() {} 5475 } 5476 static assert( hasComplexDestruction!HasDtor); 5477 5478 // The compiler will generate a destructor if a member variable has one. 5479 static struct HasMemberWithDtor 5480 { 5481 HasDtor s; 5482 } 5483 static assert( hasComplexDestruction!HasMemberWithDtor); 5484 5485 // If a struct has @disabled destruction, hasComplexDestruction is still 5486 // true. Code that wants to check whether destruction works can either 5487 // test for whether the __xdtor member is disabled, or it can test whether 5488 // code that will destroy the object compiles. That being said, a disabled 5489 // destructor probably isn't very common in practice, because about all that 5490 // such a type is good for is being allocated on the heap. 5491 static struct DisabledDtor 5492 { 5493 @disable ~this() {} 5494 } 5495 static assert( hasComplexDestruction!DisabledDtor); 5496 static assert( __traits(isDisabled, 5497 __traits(getMember, DisabledDtor, "__xdtor"))); 5498 5499 // A type with a disabled destructor cannot be created on the stack or used 5500 // in any way that would ever trigger a destructor, making it pretty much 5501 // useless outside of providing a way to force a struct to be allocated on 5502 // the heap - though that could be useful in some situations, since it 5503 // it makes it possible to have a type that has to be a reference type but 5504 // which doesn't have the overhead of a class. 5505 static assert(!__traits(compiles, { DisabledDtor d; })); 5506 static assert( __traits(compiles, { auto d = new DisabledDtor; })); 5507 5508 // Static arrays have complex destruction if their elements do. 5509 static assert( hasComplexDestruction!(HasDtor[1])); 5510 5511 // Static arrays with no elements do not have complex destruction, because 5512 // there's nothing to destroy. 5513 static assert(!hasComplexDestruction!(HasDtor[0])); 5514 5515 // Dynamic arrays do not have complex destruction, because their elements 5516 // are contained in the memory that the dynamic array is a slice of and not 5517 // in the dynamic array itself, so there's nothing to destroy when a 5518 // dynamic array leaves scope. 5519 static assert(!hasComplexDestruction!(HasDtor[])); 5520 5521 // Classes and unions do not have complex copying even if they have 5522 // members which do. 5523 class C 5524 { 5525 HasDtor s; 5526 } 5527 static assert(!hasComplexDestruction!C); 5528 5529 union U 5530 { 5531 HasDtor s; 5532 } 5533 static assert(!hasComplexDestruction!U); 5534 5535 // https://issues.dlang.org/show_bug.cgi?id=24833 5536 // This static assertion fails, because the compiler 5537 // currently ignores assignment operators for enum types. 5538 enum E : HasDtor { a = HasDtor.init } 5539 //static assert( hasComplexDestruction!E); 5540 } 5541 5542 @safe unittest 5543 { 5544 import phobos.sys.meta : AliasSeq; 5545 5546 { 5547 struct S1 { int i; } 5548 struct S2 { real r; } 5549 struct S3 { string s; } 5550 struct S4 { int[] arr; } 5551 struct S5 { int[0] arr; } 5552 struct S6 { int[42] arr; } 5553 struct S7 { int[string] aa; } 5554 5555 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 5556 { 5557 static assert(!hasComplexDestruction!T); 5558 static assert(!hasComplexDestruction!(T[0])); 5559 static assert(!hasComplexDestruction!(T[42])); 5560 static assert(!hasComplexDestruction!(T[])); 5561 } 5562 } 5563 5564 // Basic variations of destructors. 5565 { 5566 static struct S { ~this() {} } 5567 static assert( hasComplexDestruction!S); 5568 5569 static struct S2 { S s; } 5570 static assert( hasComplexDestruction!S2); 5571 } 5572 { 5573 static struct S { ~this() const {} } 5574 static assert( hasComplexDestruction!S); 5575 5576 static struct S2 { S s; } 5577 static assert( hasComplexDestruction!S2); 5578 } 5579 { 5580 static struct S { ~this() @safe {} } 5581 static assert( hasComplexDestruction!S); 5582 5583 static struct S2 { S s; } 5584 static assert( hasComplexDestruction!S2); 5585 } 5586 { 5587 static struct S { ~this() @safe pure nothrow @nogc {} } 5588 static assert( hasComplexDestruction!S); 5589 5590 static struct S2 { S s; } 5591 static assert( hasComplexDestruction!S2); 5592 } 5593 5594 // @disabled destructors. 5595 { 5596 static struct S { @disable ~this() {} } 5597 static assert( __traits(isDisabled, 5598 __traits(getMember, S, "__xdtor"))); 5599 5600 static struct S2 { S s; } 5601 static assert( hasComplexDestruction!S2); 5602 static assert( __traits(isDisabled, 5603 __traits(getMember, S2, "__xdtor"))); 5604 } 5605 5606 // Static arrays 5607 { 5608 static struct S { ~this() {} } 5609 static assert( hasComplexDestruction!S); 5610 5611 static assert(!hasComplexDestruction!(S[0])); 5612 static assert( hasComplexDestruction!(S[12])); 5613 static assert(!hasComplexDestruction!(S[])); 5614 5615 static struct S2 { S[42] s; } 5616 static assert( hasComplexDestruction!S2); 5617 } 5618 } 5619 5620 /++ 5621 Evaluates to $(D true) if the given type is one or more of the following, 5622 or if it's a struct, union, or static array which contains one or more of 5623 the following: 5624 5625 $(OL $(LI A raw pointer) 5626 $(LI A class reference) 5627 $(LI An interface reference) 5628 $(LI A dynamic array) 5629 $(LI An associative array) 5630 $(LI A delegate) 5631 $(LI A struct with a 5632 $(DDSUBLINK spec/traits, isNested, $(D context pointer)).)) 5633 5634 Note that function pointers are not considered to have indirections, because 5635 they do not point to any data (whereas a delegate has a context pointer 5636 and therefore has data that it points to). 5637 5638 Also, while static arrays do not have indirections unless their element 5639 type has indirections, static arrays with an element type of $(D void) are 5640 considered to have indirections by hasIndirections, because it's unknown 5641 what type their elements actually are, so they $(I might) have 5642 indirections, and thus, the conservative approach is to assume that they do 5643 have indirections. 5644 5645 Static arrays with length 0 do not have indirections no matter what their 5646 element type is, since they don't actually have any elements. 5647 +/ 5648 version (StdDdoc) template hasIndirections(T) 5649 { 5650 import core.internal.traits : _hasIndirections = hasIndirections; 5651 alias hasIndirections = _hasIndirections!T; 5652 } 5653 else 5654 { 5655 import core.internal.traits : _hasIndirections = hasIndirections; 5656 alias hasIndirections = _hasIndirections; 5657 } 5658 5659 /// 5660 @safe unittest 5661 { 5662 static class C {} 5663 static interface I {} 5664 5665 static assert( hasIndirections!(int*)); 5666 static assert( hasIndirections!C); 5667 static assert( hasIndirections!I); 5668 static assert( hasIndirections!(int[])); 5669 static assert( hasIndirections!(int[string])); 5670 static assert( hasIndirections!(void delegate())); 5671 static assert( hasIndirections!(string delegate(int))); 5672 5673 static assert(!hasIndirections!(void function())); 5674 static assert(!hasIndirections!int); 5675 5676 static assert(!hasIndirections!(ubyte[9])); 5677 static assert( hasIndirections!(ubyte[9]*)); 5678 static assert( hasIndirections!(ubyte*[9])); 5679 static assert(!hasIndirections!(ubyte*[0])); 5680 static assert( hasIndirections!(ubyte[])); 5681 5682 static assert( hasIndirections!(void[])); 5683 static assert( hasIndirections!(void[42])); 5684 5685 static struct NoContext 5686 { 5687 int i; 5688 } 5689 5690 int local; 5691 5692 struct HasContext 5693 { 5694 int foo() { return local; } 5695 } 5696 5697 struct HasMembersWithIndirections 5698 { 5699 int* ptr; 5700 } 5701 5702 static assert(!hasIndirections!NoContext); 5703 static assert( hasIndirections!HasContext); 5704 static assert( hasIndirections!HasMembersWithIndirections); 5705 5706 union U1 5707 { 5708 int i; 5709 float f; 5710 } 5711 static assert(!hasIndirections!U1); 5712 5713 union U2 5714 { 5715 int i; 5716 int[] arr; 5717 } 5718 static assert( hasIndirections!U2); 5719 } 5720 5721 // hasIndirections with types which aren't aggregate types. 5722 @safe unittest 5723 { 5724 import phobos.sys.meta : AliasSeq; 5725 5726 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 5727 5728 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 5729 float, double, real, char, wchar, dchar, int function(string), void)) 5730 { 5731 mixin testWithQualifiers!(T, false); 5732 mixin testWithQualifiers!(T*, true); 5733 mixin testWithQualifiers!(T[], true); 5734 5735 mixin testWithQualifiers!(T[42], is(T == void)); 5736 mixin testWithQualifiers!(T[0], false); 5737 5738 mixin testWithQualifiers!(T*[42], true); 5739 mixin testWithQualifiers!(T*[0], false); 5740 5741 mixin testWithQualifiers!(T[][42], true); 5742 mixin testWithQualifiers!(T[][0], false); 5743 } 5744 5745 foreach (T; AliasSeq!(int[int], int delegate(string))) 5746 { 5747 mixin testWithQualifiers!(T, true); 5748 mixin testWithQualifiers!(T*, true); 5749 mixin testWithQualifiers!(T[], true); 5750 5751 mixin testWithQualifiers!(T[42], true); 5752 mixin testWithQualifiers!(T[0], false); 5753 5754 mixin testWithQualifiers!(T*[42], true); 5755 mixin testWithQualifiers!(T*[0], false); 5756 5757 mixin testWithQualifiers!(T[][42], true); 5758 mixin testWithQualifiers!(T[][0], false); 5759 } 5760 } 5761 5762 // hasIndirections with structs. 5763 @safe unittest 5764 { 5765 import phobos.sys.meta : AliasSeq; 5766 5767 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 5768 5769 { 5770 struct S {} 5771 mixin testWithQualifiers!(S, false); 5772 } 5773 { 5774 static struct S {} 5775 mixin testWithQualifiers!(S, false); 5776 } 5777 { 5778 struct S { void foo() {} } 5779 mixin testWithQualifiers!(S, true); 5780 } 5781 { 5782 static struct S { void foo() {} } 5783 mixin testWithQualifiers!(S, false); 5784 } 5785 5786 // Structs with members which aren't aggregate types and don't have indirections. 5787 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 5788 float, double, real, char, wchar, dchar, int function(string))) 5789 { 5790 // No indirections. 5791 { 5792 struct S { T member; } 5793 mixin testWithQualifiers!(S, false); 5794 } 5795 { 5796 struct S { const T member; } 5797 mixin testWithQualifiers!(S, false); 5798 } 5799 { 5800 struct S { immutable T member; } 5801 mixin testWithQualifiers!(S, false); 5802 } 5803 { 5804 struct S { shared T member; } 5805 mixin testWithQualifiers!(S, false); 5806 } 5807 5808 { 5809 static struct S { T member; void foo() {} } 5810 mixin testWithQualifiers!(S, false); 5811 } 5812 { 5813 static struct S { const T member; void foo() {} } 5814 mixin testWithQualifiers!(S, false); 5815 } 5816 { 5817 static struct S { immutable T member; void foo() {} } 5818 mixin testWithQualifiers!(S, false); 5819 } 5820 { 5821 static struct S { shared T member; void foo() {} } 5822 mixin testWithQualifiers!(S, false); 5823 } 5824 5825 // Has context pointer. 5826 { 5827 struct S { T member; void foo() {} } 5828 mixin testWithQualifiers!(S, true); 5829 } 5830 { 5831 struct S { const T member; void foo() {} } 5832 mixin testWithQualifiers!(S, true); 5833 } 5834 { 5835 struct S { immutable T member; void foo() {} } 5836 mixin testWithQualifiers!(S, true); 5837 } 5838 { 5839 struct S { shared T member; void foo() {} } 5840 mixin testWithQualifiers!(S, true); 5841 } 5842 5843 { 5844 T local; 5845 struct S { void foo() { auto v = local; } } 5846 mixin testWithQualifiers!(S, true); 5847 } 5848 { 5849 const T local; 5850 struct S { void foo() { auto v = local; } } 5851 mixin testWithQualifiers!(S, true); 5852 } 5853 { 5854 immutable T local; 5855 struct S { void foo() { auto v = local; } } 5856 mixin testWithQualifiers!(S, true); 5857 } 5858 { 5859 shared T local; 5860 struct S { void foo() @trusted { auto v = cast() local; } } 5861 mixin testWithQualifiers!(S, true); 5862 } 5863 5864 // Pointers. 5865 { 5866 struct S { T* member; } 5867 mixin testWithQualifiers!(S, true); 5868 } 5869 { 5870 struct S { const(T)* member; } 5871 mixin testWithQualifiers!(S, true); 5872 } 5873 { 5874 struct S { const T* member; } 5875 mixin testWithQualifiers!(S, true); 5876 } 5877 { 5878 struct S { immutable T* member; } 5879 mixin testWithQualifiers!(S, true); 5880 } 5881 { 5882 struct S { shared T* member; } 5883 mixin testWithQualifiers!(S, true); 5884 } 5885 5886 // Dynamic arrays. 5887 { 5888 struct S { T[] member; } 5889 mixin testWithQualifiers!(S, true); 5890 } 5891 { 5892 struct S { const(T)[] member; } 5893 mixin testWithQualifiers!(S, true); 5894 } 5895 { 5896 struct S { const T[] member; } 5897 mixin testWithQualifiers!(S, true); 5898 } 5899 { 5900 struct S { immutable T[] member; } 5901 mixin testWithQualifiers!(S, true); 5902 } 5903 { 5904 struct S { shared T[] member; } 5905 mixin testWithQualifiers!(S, true); 5906 } 5907 5908 // Static arrays. 5909 { 5910 struct S { T[1] member; } 5911 mixin testWithQualifiers!(S, false); 5912 } 5913 { 5914 struct S { const(T)[1] member; } 5915 mixin testWithQualifiers!(S, false); 5916 } 5917 { 5918 struct S { const T[1] member; } 5919 mixin testWithQualifiers!(S, false); 5920 } 5921 { 5922 struct S { immutable T[1] member; } 5923 mixin testWithQualifiers!(S, false); 5924 } 5925 { 5926 struct S { shared T[1] member; } 5927 mixin testWithQualifiers!(S, false); 5928 } 5929 5930 // Static arrays of pointers. 5931 { 5932 struct S { T*[1] member; } 5933 mixin testWithQualifiers!(S, true); 5934 } 5935 { 5936 struct S { const(T)*[1] member; } 5937 mixin testWithQualifiers!(S, true); 5938 } 5939 { 5940 struct S { const(T*)[1] member; } 5941 mixin testWithQualifiers!(S, true); 5942 } 5943 { 5944 struct S { const T*[1] member; } 5945 mixin testWithQualifiers!(S, true); 5946 } 5947 { 5948 struct S { immutable T*[1] member; } 5949 mixin testWithQualifiers!(S, true); 5950 } 5951 { 5952 struct S { shared T*[1] member; } 5953 mixin testWithQualifiers!(S, true); 5954 } 5955 5956 { 5957 struct S { T*[0] member; } 5958 mixin testWithQualifiers!(S, false); 5959 } 5960 { 5961 struct S { const(T)*[0] member; } 5962 mixin testWithQualifiers!(S, false); 5963 } 5964 { 5965 struct S { const(T*)[0] member; } 5966 mixin testWithQualifiers!(S, false); 5967 } 5968 { 5969 struct S { const T*[0] member; } 5970 mixin testWithQualifiers!(S, false); 5971 } 5972 { 5973 struct S { immutable T*[0] member; } 5974 mixin testWithQualifiers!(S, false); 5975 } 5976 { 5977 struct S { shared T*[0] member; } 5978 mixin testWithQualifiers!(S, false); 5979 } 5980 5981 // Static arrays of dynamic arrays. 5982 { 5983 struct S { T[][1] member; } 5984 mixin testWithQualifiers!(S, true); 5985 } 5986 { 5987 struct S { const(T)[][1] member; } 5988 mixin testWithQualifiers!(S, true); 5989 } 5990 { 5991 struct S { const(T[])[1] member; } 5992 mixin testWithQualifiers!(S, true); 5993 } 5994 { 5995 struct S { const T[][1] member; } 5996 mixin testWithQualifiers!(S, true); 5997 } 5998 { 5999 struct S { immutable T[][1] member; } 6000 mixin testWithQualifiers!(S, true); 6001 } 6002 { 6003 struct S { shared T[][1] member; } 6004 mixin testWithQualifiers!(S, true); 6005 } 6006 6007 { 6008 struct S { T[][0] member; } 6009 mixin testWithQualifiers!(S, false); 6010 } 6011 { 6012 struct S { const(T)[][0] member; } 6013 mixin testWithQualifiers!(S, false); 6014 } 6015 { 6016 struct S { const(T[])[0] member; } 6017 mixin testWithQualifiers!(S, false); 6018 } 6019 { 6020 struct S { const T[][0] member; } 6021 mixin testWithQualifiers!(S, false); 6022 } 6023 { 6024 struct S { immutable T[][0] member; } 6025 mixin testWithQualifiers!(S, false); 6026 } 6027 { 6028 struct S { shared T[][0] member; } 6029 mixin testWithQualifiers!(S, false); 6030 } 6031 } 6032 6033 // Structs with arrays of void. 6034 { 6035 { 6036 static struct S { void[] member; } 6037 mixin testWithQualifiers!(S, true); 6038 } 6039 { 6040 static struct S { void[1] member; } 6041 mixin testWithQualifiers!(S, true); 6042 } 6043 { 6044 static struct S { void[0] member; } 6045 mixin testWithQualifiers!(S, false); 6046 } 6047 } 6048 6049 // Structs with multiple members, testing pointer types. 6050 { 6051 static struct S { int i; bool b; } 6052 mixin testWithQualifiers!(S, false); 6053 } 6054 { 6055 static struct S { int* i; bool b; } 6056 mixin testWithQualifiers!(S, true); 6057 } 6058 { 6059 static struct S { int i; bool* b; } 6060 mixin testWithQualifiers!(S, true); 6061 } 6062 { 6063 static struct S { int* i; bool* b; } 6064 mixin testWithQualifiers!(S, true); 6065 } 6066 6067 // Structs with multiple members, testing dynamic arrays. 6068 { 6069 static struct S { int[] arr; } 6070 mixin testWithQualifiers!(S, true); 6071 } 6072 { 6073 static struct S { int i; int[] arr; } 6074 mixin testWithQualifiers!(S, true); 6075 } 6076 { 6077 static struct S { int[] arr; int i; } 6078 mixin testWithQualifiers!(S, true); 6079 } 6080 6081 // Structs with multiple members, testing static arrays. 6082 { 6083 static struct S { int[1] arr; } 6084 mixin testWithQualifiers!(S, false); 6085 } 6086 { 6087 static struct S { int i; int[1] arr; } 6088 mixin testWithQualifiers!(S, false); 6089 } 6090 { 6091 static struct S { int[1] arr; int i; } 6092 mixin testWithQualifiers!(S, false); 6093 } 6094 6095 { 6096 static struct S { int*[0] arr; } 6097 mixin testWithQualifiers!(S, false); 6098 } 6099 { 6100 static struct S { int i; int*[0] arr; } 6101 mixin testWithQualifiers!(S, false); 6102 } 6103 { 6104 static struct S { int*[0] arr; int i; } 6105 mixin testWithQualifiers!(S, false); 6106 } 6107 6108 { 6109 static struct S { string[42] arr; } 6110 mixin testWithQualifiers!(S, true); 6111 } 6112 { 6113 static struct S { int i; string[42] arr; } 6114 mixin testWithQualifiers!(S, true); 6115 } 6116 { 6117 static struct S { string[42] arr; int i; } 6118 mixin testWithQualifiers!(S, true); 6119 } 6120 6121 // Structs with associative arrays. 6122 { 6123 static struct S { int[string] aa; } 6124 mixin testWithQualifiers!(S, true); 6125 } 6126 { 6127 static struct S { int i; int[string] aa; } 6128 mixin testWithQualifiers!(S, true); 6129 } 6130 { 6131 static struct S { int[string] aa; int i; } 6132 mixin testWithQualifiers!(S, true); 6133 } 6134 6135 { 6136 static struct S { int[42][int] aa; } 6137 mixin testWithQualifiers!(S, true); 6138 } 6139 { 6140 static struct S { int[0][int] aa; } 6141 mixin testWithQualifiers!(S, true); 6142 } 6143 6144 // Structs with classes. 6145 { 6146 class C {} 6147 struct S { C c; } 6148 mixin testWithQualifiers!(S, true); 6149 } 6150 { 6151 interface I {} 6152 struct S { I i; } 6153 mixin testWithQualifiers!(S, true); 6154 } 6155 6156 // Structs with delegates. 6157 { 6158 struct S { void delegate() d; } 6159 mixin testWithQualifiers!(S, true); 6160 } 6161 { 6162 struct S { int delegate(int) d; } 6163 mixin testWithQualifiers!(S, true); 6164 } 6165 6166 // Structs multiple layers deep. 6167 { 6168 struct S1 { int i; } 6169 struct S2 { S1 s; } 6170 struct S3 { S2 s; } 6171 struct S4 { S3 s; } 6172 struct S5 { S4 s; } 6173 struct S6 { S5 s; } 6174 struct S7 { S6[0] s; } 6175 struct S8 { S7 s; } 6176 struct S9 { S8 s; } 6177 struct S10 { S9 s; } 6178 mixin testWithQualifiers!(S1, false); 6179 mixin testWithQualifiers!(S2, false); 6180 mixin testWithQualifiers!(S3, false); 6181 mixin testWithQualifiers!(S4, false); 6182 mixin testWithQualifiers!(S5, false); 6183 mixin testWithQualifiers!(S6, false); 6184 mixin testWithQualifiers!(S7, false); 6185 mixin testWithQualifiers!(S8, false); 6186 mixin testWithQualifiers!(S9, false); 6187 mixin testWithQualifiers!(S10, false); 6188 } 6189 { 6190 struct S1 { int* i; } 6191 struct S2 { S1 s; } 6192 struct S3 { S2 s; } 6193 struct S4 { S3 s; } 6194 struct S5 { S4 s; } 6195 struct S6 { S5 s; } 6196 struct S7 { S6[0] s; } 6197 struct S8 { S7 s; } 6198 struct S9 { S8 s; } 6199 struct S10 { S9 s; } 6200 mixin testWithQualifiers!(S1, true); 6201 mixin testWithQualifiers!(S2, true); 6202 mixin testWithQualifiers!(S3, true); 6203 mixin testWithQualifiers!(S4, true); 6204 mixin testWithQualifiers!(S5, true); 6205 mixin testWithQualifiers!(S6, true); 6206 mixin testWithQualifiers!(S7, false); 6207 mixin testWithQualifiers!(S8, false); 6208 mixin testWithQualifiers!(S9, false); 6209 mixin testWithQualifiers!(S10, false); 6210 } 6211 } 6212 6213 // hasIndirections with unions. 6214 @safe unittest 6215 { 6216 import phobos.sys.meta : AliasSeq; 6217 6218 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 6219 6220 { 6221 union U {} 6222 mixin testWithQualifiers!(U, false); 6223 } 6224 { 6225 static union U {} 6226 mixin testWithQualifiers!(U, false); 6227 } 6228 6229 // Unions with members which aren't aggregate types and don't have indirections. 6230 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 6231 float, double, real, char, wchar, dchar, int function(string))) 6232 { 6233 // No indirections. 6234 { 6235 union U { T member; } 6236 mixin testWithQualifiers!(U, false); 6237 } 6238 { 6239 union U { const T member; } 6240 mixin testWithQualifiers!(U, false); 6241 } 6242 { 6243 union U { immutable T member; } 6244 mixin testWithQualifiers!(U, false); 6245 } 6246 { 6247 union U { shared T member; } 6248 mixin testWithQualifiers!(U, false); 6249 } 6250 6251 // Pointers. 6252 { 6253 union U { T* member; } 6254 mixin testWithQualifiers!(U, true); 6255 } 6256 { 6257 union U { const(T)* member; } 6258 mixin testWithQualifiers!(U, true); 6259 } 6260 { 6261 union U { const T* member; } 6262 mixin testWithQualifiers!(U, true); 6263 } 6264 { 6265 union U { immutable T* member; } 6266 mixin testWithQualifiers!(U, true); 6267 } 6268 { 6269 union U { shared T* member; } 6270 mixin testWithQualifiers!(U, true); 6271 } 6272 6273 // Dynamic arrays. 6274 { 6275 union U { T[] member; } 6276 mixin testWithQualifiers!(U, true); 6277 } 6278 { 6279 union U { const(T)[] member; } 6280 mixin testWithQualifiers!(U, true); 6281 } 6282 { 6283 union U { const T[] member; } 6284 mixin testWithQualifiers!(U, true); 6285 } 6286 { 6287 union U { immutable T[] member; } 6288 mixin testWithQualifiers!(U, true); 6289 } 6290 { 6291 union U { shared T[] member; } 6292 mixin testWithQualifiers!(U, true); 6293 } 6294 6295 // Static arrays. 6296 { 6297 union U { T[1] member; } 6298 mixin testWithQualifiers!(U, false); 6299 } 6300 { 6301 union U { const(T)[1] member; } 6302 mixin testWithQualifiers!(U, false); 6303 } 6304 { 6305 union U { const T[1] member; } 6306 mixin testWithQualifiers!(U, false); 6307 } 6308 { 6309 union U { immutable T[1] member; } 6310 mixin testWithQualifiers!(U, false); 6311 } 6312 { 6313 union U { shared T[1] member; } 6314 mixin testWithQualifiers!(U, false); 6315 } 6316 6317 // Static arrays of pointers. 6318 { 6319 union U { T*[1] member; } 6320 mixin testWithQualifiers!(U, true); 6321 } 6322 { 6323 union U { const(T)*[1] member; } 6324 mixin testWithQualifiers!(U, true); 6325 } 6326 { 6327 union U { const(T*)[1] member; } 6328 mixin testWithQualifiers!(U, true); 6329 } 6330 { 6331 union U { const T*[1] member; } 6332 mixin testWithQualifiers!(U, true); 6333 } 6334 { 6335 union U { immutable T*[1] member; } 6336 mixin testWithQualifiers!(U, true); 6337 } 6338 { 6339 union U { shared T*[1] member; } 6340 mixin testWithQualifiers!(U, true); 6341 } 6342 6343 { 6344 union U { T*[0] member; } 6345 mixin testWithQualifiers!(U, false); 6346 } 6347 { 6348 union U { const(T)*[0] member; } 6349 mixin testWithQualifiers!(U, false); 6350 } 6351 { 6352 union U { const(T*)[0] member; } 6353 mixin testWithQualifiers!(U, false); 6354 } 6355 { 6356 union U { const T*[0] member; } 6357 mixin testWithQualifiers!(U, false); 6358 } 6359 { 6360 union U { immutable T*[0] member; } 6361 mixin testWithQualifiers!(U, false); 6362 } 6363 { 6364 union U { shared T*[0] member; } 6365 mixin testWithQualifiers!(U, false); 6366 } 6367 6368 // Static arrays of dynamic arrays. 6369 { 6370 union U { T[][1] member; } 6371 mixin testWithQualifiers!(U, true); 6372 } 6373 { 6374 union U { const(T)[][1] member; } 6375 mixin testWithQualifiers!(U, true); 6376 } 6377 { 6378 union U { const(T[])[1] member; } 6379 mixin testWithQualifiers!(U, true); 6380 } 6381 { 6382 union U { const T[][1] member; } 6383 mixin testWithQualifiers!(U, true); 6384 } 6385 { 6386 union U { immutable T[][1] member; } 6387 mixin testWithQualifiers!(U, true); 6388 } 6389 { 6390 union U { shared T[][1] member; } 6391 mixin testWithQualifiers!(U, true); 6392 } 6393 6394 { 6395 union U { T[][0] member; } 6396 mixin testWithQualifiers!(U, false); 6397 } 6398 { 6399 union U { const(T)[][0] member; } 6400 mixin testWithQualifiers!(U, false); 6401 } 6402 { 6403 union U { const(T[])[0] member; } 6404 mixin testWithQualifiers!(U, false); 6405 } 6406 { 6407 union U { const T[][0] member; } 6408 mixin testWithQualifiers!(U, false); 6409 } 6410 { 6411 union U { immutable T[][0] member; } 6412 mixin testWithQualifiers!(U, false); 6413 } 6414 { 6415 union U { shared T[][0] member; } 6416 mixin testWithQualifiers!(U, false); 6417 } 6418 } 6419 6420 // Unions with arrays of void. 6421 { 6422 { 6423 static union U { void[] member; } 6424 mixin testWithQualifiers!(U, true); 6425 } 6426 { 6427 static union U { void[1] member; } 6428 mixin testWithQualifiers!(U, true); 6429 } 6430 { 6431 static union U { void[0] member; } 6432 mixin testWithQualifiers!(U, false); 6433 } 6434 } 6435 6436 // Unions with multiple members, testing pointer types. 6437 { 6438 static union U { int i; bool b; } 6439 mixin testWithQualifiers!(U, false); 6440 } 6441 { 6442 static union U { int* i; bool b; } 6443 mixin testWithQualifiers!(U, true); 6444 } 6445 { 6446 static union U { int i; bool* b; } 6447 mixin testWithQualifiers!(U, true); 6448 } 6449 { 6450 static union U { int* i; bool* b; } 6451 mixin testWithQualifiers!(U, true); 6452 } 6453 6454 // Unions with multiple members, testing dynamic arrays. 6455 { 6456 static union U { int[] arr; } 6457 mixin testWithQualifiers!(U, true); 6458 } 6459 { 6460 static union U { int i; int[] arr; } 6461 mixin testWithQualifiers!(U, true); 6462 } 6463 { 6464 static union U { int[] arr; int i; } 6465 mixin testWithQualifiers!(U, true); 6466 } 6467 6468 // Unions with multiple members, testing static arrays. 6469 { 6470 static union U { int[1] arr; } 6471 mixin testWithQualifiers!(U, false); 6472 } 6473 { 6474 static union U { int i; int[1] arr; } 6475 mixin testWithQualifiers!(U, false); 6476 } 6477 { 6478 static union U { int[1] arr; int i; } 6479 mixin testWithQualifiers!(U, false); 6480 } 6481 6482 { 6483 static union U { int*[0] arr; } 6484 mixin testWithQualifiers!(U, false); 6485 } 6486 { 6487 static union U { int i; int*[0] arr; } 6488 mixin testWithQualifiers!(U, false); 6489 } 6490 { 6491 static union U { int*[0] arr; int i; } 6492 mixin testWithQualifiers!(U, false); 6493 } 6494 6495 { 6496 static union U { string[42] arr; } 6497 mixin testWithQualifiers!(U, true); 6498 } 6499 { 6500 static union U { int i; string[42] arr; } 6501 mixin testWithQualifiers!(U, true); 6502 } 6503 { 6504 static union U { string[42] arr; int i; } 6505 mixin testWithQualifiers!(U, true); 6506 } 6507 6508 // Unions with associative arrays. 6509 { 6510 static union U { int[string] aa; } 6511 mixin testWithQualifiers!(U, true); 6512 } 6513 { 6514 static union U { int i; int[string] aa; } 6515 mixin testWithQualifiers!(U, true); 6516 } 6517 { 6518 static union U { int[string] aa; int i; } 6519 mixin testWithQualifiers!(U, true); 6520 } 6521 6522 { 6523 static union U { int[42][int] aa; } 6524 mixin testWithQualifiers!(U, true); 6525 } 6526 { 6527 static union U { int[0][int] aa; } 6528 mixin testWithQualifiers!(U, true); 6529 } 6530 6531 // Unions with classes. 6532 { 6533 class C {} 6534 union U { C c; } 6535 mixin testWithQualifiers!(U, true); 6536 } 6537 { 6538 interface I {} 6539 union U { I i; } 6540 mixin testWithQualifiers!(U, true); 6541 } 6542 6543 // Unions with delegates. 6544 { 6545 union U { void delegate() d; } 6546 mixin testWithQualifiers!(U, true); 6547 } 6548 { 6549 union U { int delegate(int) d; } 6550 mixin testWithQualifiers!(U, true); 6551 } 6552 6553 // Unions multiple layers deep. 6554 { 6555 union U1 { int i; } 6556 union U2 { U1 s; } 6557 union U3 { U2 s; } 6558 union U4 { U3 s; } 6559 union U5 { U4 s; } 6560 union U6 { U5 s; } 6561 union U7 { U6[0] s; } 6562 union U8 { U7 s; } 6563 union U9 { U8 s; } 6564 union U10 { U9 s; } 6565 mixin testWithQualifiers!(U1, false); 6566 mixin testWithQualifiers!(U2, false); 6567 mixin testWithQualifiers!(U3, false); 6568 mixin testWithQualifiers!(U4, false); 6569 mixin testWithQualifiers!(U5, false); 6570 mixin testWithQualifiers!(U6, false); 6571 mixin testWithQualifiers!(U7, false); 6572 mixin testWithQualifiers!(U8, false); 6573 mixin testWithQualifiers!(U9, false); 6574 mixin testWithQualifiers!(U10, false); 6575 } 6576 { 6577 union U1 { int* i; } 6578 union U2 { U1 s; } 6579 union U3 { U2 s; } 6580 union U4 { U3 s; } 6581 union U5 { U4 s; } 6582 union U6 { U5 s; } 6583 union U7 { U6[0] s; } 6584 union U8 { U7 s; } 6585 union U9 { U8 s; } 6586 union U10 { U9 s; } 6587 mixin testWithQualifiers!(U1, true); 6588 mixin testWithQualifiers!(U2, true); 6589 mixin testWithQualifiers!(U3, true); 6590 mixin testWithQualifiers!(U4, true); 6591 mixin testWithQualifiers!(U5, true); 6592 mixin testWithQualifiers!(U6, true); 6593 mixin testWithQualifiers!(U7, false); 6594 mixin testWithQualifiers!(U8, false); 6595 mixin testWithQualifiers!(U9, false); 6596 mixin testWithQualifiers!(U10, false); 6597 } 6598 } 6599 6600 // hasIndirections with classes and interfaces 6601 @safe unittest 6602 { 6603 import phobos.sys.meta : AliasSeq; 6604 6605 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 6606 6607 { 6608 class C {} 6609 mixin testWithQualifiers!(C, true); 6610 } 6611 6612 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 6613 float, double, real, char, wchar, dchar, int function(string), 6614 int[int], string delegate(int))) 6615 { 6616 { 6617 class C { T member; } 6618 mixin testWithQualifiers!(C, true); 6619 } 6620 { 6621 class C { const T member; } 6622 mixin testWithQualifiers!(C, true); 6623 } 6624 { 6625 class C { immutable T member; } 6626 mixin testWithQualifiers!(C, true); 6627 } 6628 { 6629 class C { shared T member; } 6630 mixin testWithQualifiers!(C, true); 6631 } 6632 } 6633 6634 { 6635 interface I {} 6636 mixin testWithQualifiers!(I, true); 6637 } 6638 } 6639 6640 /++ 6641 Takes a type which is an associative array and evaluates to the type of the 6642 keys in that associative array. 6643 6644 See_Also: 6645 $(LREF ValueType) 6646 +/ 6647 alias KeyType(V : V[K], K) = K; 6648 6649 /// 6650 @safe unittest 6651 { 6652 static assert(is(KeyType!(int[string]) == string)); 6653 static assert(is(KeyType!(string[int]) == int)); 6654 6655 static assert(is(KeyType!(string[const int]) == const int)); 6656 static assert(is(KeyType!(const int[string]) == string)); 6657 6658 struct S 6659 { 6660 int i; 6661 } 6662 6663 string[S] aa1; 6664 static assert(is(KeyType!(typeof(aa1)) == S)); 6665 6666 S[string] aa2; 6667 static assert(is(KeyType!(typeof(aa2)) == string)); 6668 6669 KeyType!(typeof(aa1)) key1 = S(42); 6670 KeyType!(typeof(aa2)) key2 = "foo"; 6671 6672 // Key types with indirections have their inner layers treated as const 6673 // by the compiler, because the values of keys can't change, or the hash 6674 // value could change, putting the associative array in an invalid state. 6675 static assert(is(KeyType!(bool[string[]]) == const(string)[])); 6676 static assert(is(KeyType!(bool[int*]) == const(int)*)); 6677 6678 // If the given type is not an AA, then KeyType won't compile. 6679 static assert(!__traits(compiles, KeyType!int)); 6680 static assert(!__traits(compiles, KeyType!(int[]))); 6681 } 6682 6683 /++ 6684 Takes a type which is an associative array and evaluates to the type of the 6685 values in that associative array. 6686 6687 See_Also: 6688 $(LREF KeyType) 6689 +/ 6690 alias ValueType(V : V[K], K) = V; 6691 6692 /// 6693 @safe unittest 6694 { 6695 static assert(is(ValueType!(int[string]) == int)); 6696 static assert(is(ValueType!(string[int]) == string)); 6697 6698 static assert(is(ValueType!(string[const int]) == string)); 6699 static assert(is(ValueType!(const int[string]) == const int)); 6700 6701 struct S 6702 { 6703 int i; 6704 } 6705 6706 string[S] aa1; 6707 static assert(is(ValueType!(typeof(aa1)) == string)); 6708 6709 S[string] aa2; 6710 static assert(is(ValueType!(typeof(aa2)) == S)); 6711 6712 ValueType!(typeof(aa1)) value1 = "foo"; 6713 ValueType!(typeof(aa2)) value2 = S(42); 6714 6715 // If the given type is not an AA, then ValueType won't compile. 6716 static assert(!__traits(compiles, ValueType!int)); 6717 static assert(!__traits(compiles, ValueType!(int[]))); 6718 } 6719 6720 /++ 6721 Evaluates to the original / ultimate base type of an enum type - or for 6722 non-enum types, it evaluates to the type that it's given. 6723 6724 If the base type of the given enum type is not an enum, then the result of 6725 OriginalType is its direct base type. However, if the base type of the 6726 given enum is also an enum, then OriginalType gives the ultimate base type 6727 - that is, it keeps getting the base type for each succesive enum in the 6728 chain until it gets to a base type that isn't an enum, and that's the 6729 result. So, the result will never be an enum type. 6730 6731 If the given type has any qualifiers, the result will have those same 6732 qualifiers. 6733 +/ 6734 version (StdDdoc) template OriginalType(T) 6735 { 6736 import core.internal.traits : CoreOriginalType = OriginalType; 6737 alias OriginalType = CoreOriginalType!T; 6738 } 6739 else 6740 { 6741 import core.internal.traits : CoreOriginalType = OriginalType; 6742 alias OriginalType = CoreOriginalType; 6743 } 6744 6745 /// 6746 @safe unittest 6747 { 6748 enum E { a, b, c } 6749 static assert(is(OriginalType!E == int)); 6750 6751 enum F : E { x = E.a } 6752 static assert(is(OriginalType!F == int)); 6753 6754 enum G : F { y = F.x } 6755 static assert(is(OriginalType!G == int)); 6756 static assert(is(OriginalType!(const G) == const int)); 6757 static assert(is(OriginalType!(immutable G) == immutable int)); 6758 static assert(is(OriginalType!(shared G) == shared int)); 6759 6760 enum C : char { a = 'a', b = 'b' } 6761 static assert(is(OriginalType!C == char)); 6762 6763 enum D : string { d = "dlang" } 6764 static assert(is(OriginalType!D == string)); 6765 6766 static assert(is(OriginalType!int == int)); 6767 static assert(is(OriginalType!(const long) == const long)); 6768 static assert(is(OriginalType!string == string)); 6769 6770 // OriginalType gets the base type of enums and for all other types gives 6771 // the same type back. It does nothing special for other types - like 6772 // classes - where one could talk about the type having a base type. 6773 class Base {} 6774 class Derived : Base {} 6775 static assert(is(OriginalType!Base == Base)); 6776 static assert(is(OriginalType!Derived == Derived)); 6777 } 6778 6779 /++ 6780 PropertyType evaluates to the type of the symbol as an expression (i.e. the 6781 type of the expression when the symbol is used in an expression by itself), 6782 and SymbolType evaluates to the type of the given symbol as a symbol (i.e. 6783 the type of the symbol itself). 6784 6785 Unlike with $(K_TYPEOF), $(K_PROPERTY) has no effect on the result of 6786 either PropertyType or SymbolType. 6787 6788 TLDR, PropertyType should be used when code is going to use a symbol as if 6789 it were a getter property (without caring whether the symbol is a variable 6790 or a function), and the code needs to know the type of that property and 6791 $(I not) the type of the symbol itself (since with functions, they're not 6792 the same thing). So, it's treating the symbol as an expression on its own 6793 and giving the type of that expression rather than giving the type of the 6794 symbol itself. And it's named PropertyType rather than something like 6795 $(D ExpressionType), because it's used in situations where the code is 6796 treating the symbol as a getter property, and it does not operate on 6797 expressions in general. SymbolType should then be used in situations where 6798 the code needs to know the type of the symbol itself. 6799 6800 As for why PropertyType and SymbolType are necessary, and $(K_TYPEOF) is 6801 not sufficient, $(K_TYPEOF) gives both the types of symbols and the types 6802 of expressions. When it's given something that's clearly an expression - 6803 e.g. $(D typeof(foo + bar)) or $(D typeof(foo())), then the result is the 6804 type of that expression. However, when $(K_TYPEOF) is given a symbol, what 6805 $(K_TYPEOF) does depends on the symbol, which can make using it correctly 6806 in generic code difficult. 6807 6808 For symbols that don't have types, naturally, $(K_TYPEOF) doesn't even 6809 compile (e.g. $(D typeof(int)) won't compile, because in D, types don't 6810 themselves have types), so the question is what happens with $(K_TYPEOF) 6811 and symbols which do have types. 6812 6813 For symbols which have types and are not functions, what $(K_TYPEOF) does 6814 is straightforward, because there is no difference between the type of the 6815 symbol and the type of the expression - e.g. if $(D foo) is a variable of 6816 type $(K_INT), then $(D typeof(foo)) would be $(K_INT), because the 6817 variable itself is of type $(K_INT), and if the variable is used as an 6818 expression (e.g. when it's returned from a function or passed to a 6819 function), then that expression is also of type $(K_INT). 6820 6821 However, for functions (particularly functions which don't require 6822 arguments), things aren't as straightforward. Should $(D typeof(foo)) give 6823 the type of the function itself or the type of the expression? If parens 6824 always had to be used when calling a function, then $(D typeof(foo)) would 6825 clearly be the type of the function itself, whereas $(D typeof(foo())) 6826 would be the type of the expression (which would be the return type of the 6827 function so long as $(D foo) could be called with no arguments, and it 6828 wouldn't compile otherwise, because the expression would be invalid). 6829 However, because parens are optional when calling a function that has no 6830 arguments, $(D typeof(foo)) is ambiguous. There's no way to know which the 6831 programmer actually intended, but the compiler has to either make it an 6832 error or choose between giving the type of the symbol or the type of the 6833 expression. 6834 6835 So, the issue here is functions which can be treated as getter properties, 6836 because they can be called without parens and thus syntactically look 6837 exactly like a variable when they're used. Any function which requires 6838 arguments (including when a function is used as a setter property) does not 6839 have this problem, because it isn't a valid expression when used on its own 6840 (it needs to be assigned to or called with parens in order to be a valid 6841 expression). 6842 6843 What the compiler currently does when it encounters this ambiguity depends 6844 on the $(K_PROPERTY) attribute. If the function does not have the 6845 $(K_PROPERTY) attribute, then $(D typeof(foo)) will give the type of the 6846 symbol - e.g. $(D int()) if the signature for $(D foo) were $(D int foo()). 6847 However, if the function $(I does) have the $(K_PROPERTY) attribute, then 6848 $(D typeof(foo)) will give the type of the expression. So, if $(D foo) were 6849 $(D @property int foo()), then $(D typeof(foo)) would give $(K_INT) rather 6850 than $(D int()). The idea behind this is that $(K_PROPERTY) functions are 6851 supposed to act like variables, and using $(K_TYPEOF) on a variable of type 6852 $(K_INT) would give $(K_INT), not $(D int()). So, with this behavior of 6853 $(K_TYPEOF), a $(K_PROPERTY) function is closer to being a drop-in 6854 replacement for a variable. 6855 6856 The problem with this though is two-fold. One, it means that $(K_TYPEOF) 6857 cannot be relied on to give the type of the symbol when given a symbol on 6858 its own, forcing code that needs the actual type of the symbol to work 6859 around $(K_PROPERTY). And two, because parens are optional on functions 6860 which can be called without arguments, whether the function is marked with 6861 $(K_PROPERTY) or not is irrevelant to whether the symbol is going to be 6862 used as if it were a variable, and so it's irrelevant to code that's trying 6863 to get the type of the expression when the symbol is used like a getter 6864 property. If optional parens were removed from the language (as was 6865 originally the intent when $(K_PROPERTY) was introduced), then that would 6866 fix the second problem, but it would still leave the first problem. 6867 6868 So, $(K_PROPERTY) is solving the problem in the wrong place. It's the code 6869 doing the type introspection which needs to decide whether to get the type 6870 of a symbol as if it were a getter property or whether to get the type of 6871 the symbol itself. It's the type introspection code which knows which is 6872 relevant for what it's doing, and a function could be used both in code 6873 which needs to treat it as a getter property and in code which needs to get 6874 the type of the symbol itself (e.g. because it needs to get the attributes 6875 on the function). 6876 6877 All of this means that $(K_TYPEOF) by itself is unreliable when used on a 6878 symbol. In practice, the programmer needs to indicate whether they want the 6879 type of the symbol itself or the type of the symbol as a getter property in 6880 an expression, and leaving it up to $(K_TYPEOF) is simply too error-prone. 6881 So, ideally, $(K_TYPEOF) would be split up into two separate constructs, 6882 but that would involve adding more keywords (and break a lot of existing 6883 code if $(K_TYPEOF) were actually removed). 6884 6885 So, phobos.sys.traits provides SymbolType and PropertyType. They're both 6886 traits that take a symbol and give the type for that symbol. However, 6887 SymbolType gives the type of the symbol itself, whereas PropertyType gives 6888 the type of the symbol as if it were used as a getter property in an 6889 expression. Neither is affected by whether the symbol is marked with 6890 $(K_PROPERTY). So, code that needs to get information about the symbol 6891 itself should use SymbolType rather than $(K_TYPEOF) or PropertyType, 6892 whereas code that needs to get the type of the symbol as a getter property 6893 within an expression should use PropertyType. 6894 6895 The use of $(K_TYPEOF) should then be restricted to situations where code 6896 is getting the type of an expression which isn't a symbol (or code where 6897 it's already known that the symbol isn't a function). Also, since 6898 template alias parameters only accept symbols, any expressions which aren't 6899 symbols won't compile with SymbolType or PropertyType anyway. 6900 6901 SymbolType and PropertyType must be given a symbol which has a type (so, 6902 not something like a type or an uninstantiated template). Symbols 6903 which don't have types will fail the template constraint. 6904 6905 For both SymbolType and PropertyType, if they are given a symbol which has 6906 a type, and that symbol is not a function, the result will be the same as 6907 $(K_TYPEOF) (since in such cases, the type of the symbol and the type of 6908 the expression are the same). The difference comes in with functions. 6909 6910 When SymbolType is given any symbol which is a function, the result will be 6911 the type of the function itself regardless of whether the function is 6912 marked with $(K_PROPERTY). This makes it so that in all situations where 6913 the type of the symbol is needed, SymbolType can be used to get the type of 6914 the symbol without having to worry about whether it's a function marked 6915 with $(K_PROPERTY). 6916 6917 When PropertyType is given any function which can be used as a getter 6918 property, the result will be the type of the symbol as an expression - i.e. 6919 the return type of the function (in effect, this means that it treats all 6920 functions as if they were marked with $(K_PROPERTY)). Whether the function 6921 is actually marked with $(K_PROPERTY) or not is irrelevant. 6922 6923 If PropertyType is given any function which which cannot be used as a 6924 getter property (i.e. it requires arguments or returns $(K_VOID)), the 6925 template constraint will reject it, and PropertyType will fail to compile. 6926 This is equivalent to what $(K_TYPEOF) does when it's given a $(K_PROPERTY) 6927 function which is a setter, since it's not a valid expression on its own. 6928 6929 So, for $(D PropertyType!foo), if $(D foo) is a function, the result is 6930 equivalent to $(D typeof(foo())) (and for non-functions, it's equivalent to 6931 $(D typeof(foo))). 6932 6933 To summarize, SymbolType should be used when code needs to get the type of 6934 the symbol itself; PropertyType should be used when code needs to get the 6935 type of the symbol when it's used in an expression as a getter property 6936 (generally because the code doesn't care whether the symbol is a variable 6937 or a function); and $(K_TYPEOF) should be used when getting the type of an 6938 expression which is not a symbol. 6939 6940 See_Also: 6941 $(DDSUBLINK spec/type, typeof, The language spec for typeof) 6942 +/ 6943 template PropertyType(alias sym) 6944 if (is(typeof(sym)) && (!is(typeof(sym) == return) || 6945 (is(typeof(sym())) && !is(typeof(sym()) == void)))) 6946 { 6947 // This handles functions which don't have a context pointer. 6948 static if (is(typeof(&sym) == T*, T) && is(T == function)) 6949 { 6950 // Note that we can't use is(T R == return) to get the return type, 6951 // because the first overload isn't necessarily the getter function, 6952 // and is(T R == return) will give us the first overload if the function 6953 // doesn't have @property on it (whereas if it does have @property, it 6954 // will give use the getter if there is one). However, we at least know 6955 // that there's a getter function, because the template constraint 6956 // validates that sym() compiles (and returns something) if it's a 6957 // function, function pointer, or delegate. 6958 alias PropertyType = typeof(sym()); 6959 } 6960 // This handles functions which do have a context pointer. 6961 else static if (is(typeof(&sym) T == delegate) && is(T R == return)) 6962 { 6963 // See the comment above for why we can't get the return type the 6964 // normal way. 6965 alias PropertyType = typeof(sym()); 6966 } 6967 // This handles everything which isn't a function. 6968 else 6969 alias PropertyType = typeof(sym); 6970 } 6971 6972 /++ Ditto +/ 6973 template SymbolType(alias sym) 6974 if (!is(sym)) 6975 { 6976 // This handles functions which don't have a context pointer. 6977 static if (is(typeof(&sym) == T*, T) && is(T == function)) 6978 alias SymbolType = T; 6979 // This handles functions which do have a context pointer. 6980 else static if (is(typeof(&sym) T == delegate)) 6981 alias SymbolType = T; 6982 // This handles everything which isn't a function. 6983 else 6984 alias SymbolType = typeof(sym); 6985 } 6986 6987 /// 6988 @safe unittest 6989 { 6990 int i; 6991 static assert( is(SymbolType!i == int)); 6992 static assert( is(PropertyType!i == int)); 6993 static assert( is(typeof(i) == int)); 6994 6995 string str; 6996 static assert( is(SymbolType!str == string)); 6997 static assert( is(PropertyType!str == string)); 6998 static assert( is(typeof(str) == string)); 6999 7000 // ToFunctionType is used here to get around the fact that we don't have a 7001 // way to write out function types in is expressions (whereas we can write 7002 // out the type of a function pointer), which is a consequence of not being 7003 // able to declare variables with a function type (as opposed to a function 7004 // pointer type). That being said, is expressions are pretty much the only 7005 // place where writing out a function type would make sense. 7006 7007 // The function type has more attributes than the function declaration, 7008 // because the attributes are inferred for nested functions. 7009 7010 static string func() { return ""; } 7011 static assert( is(SymbolType!func == 7012 ToFunctionType!(string function() 7013 @safe pure nothrow @nogc))); 7014 static assert( is(PropertyType!func == string)); 7015 static assert( is(typeof(func) == SymbolType!func)); 7016 7017 int function() funcPtr; 7018 static assert( is(SymbolType!funcPtr == int function())); 7019 static assert( is(PropertyType!funcPtr == int function())); 7020 static assert( is(typeof(funcPtr) == int function())); 7021 7022 int delegate() del; 7023 static assert( is(SymbolType!del == int delegate())); 7024 static assert( is(PropertyType!del == int delegate())); 7025 static assert( is(typeof(del) == int delegate())); 7026 7027 @property static int prop() { return 0; } 7028 static assert( is(SymbolType!prop == 7029 ToFunctionType!(int function() 7030 @property @safe pure nothrow @nogc))); 7031 static assert( is(PropertyType!prop == int)); 7032 static assert( is(typeof(prop) == PropertyType!prop)); 7033 7034 // Functions which cannot be used as getter properties (i.e. they require 7035 // arguments and/or return void) do not compile with PropertyType. 7036 static int funcWithArg(int i) { return i; } 7037 static assert( is(SymbolType!funcWithArg == 7038 ToFunctionType!(int function(int) 7039 @safe pure nothrow @nogc))); 7040 static assert(!__traits(compiles, PropertyType!funcWithArg)); 7041 static assert( is(typeof(funcWithArg) == SymbolType!funcWithArg)); 7042 7043 // Setter @property functions also don't work with typeof, because typeof 7044 // gets the type of the expression rather than the type of the symbol when 7045 // the symbol is a function with @property, and a setter property is not a 7046 // valid expression on its own. 7047 @property static void prop2(int) {} 7048 static assert( is(SymbolType!prop2 == 7049 ToFunctionType!(void function(int) 7050 @property @safe pure nothrow @nogc))); 7051 static assert(!__traits(compiles, PropertyType!prop2)); 7052 static assert(!__traits(compiles, typeof(prop2))); 7053 7054 // Expressions which aren't symbols don't work with alias parameters and 7055 // thus don't work with SymbolType or PropertyType. 7056 static assert(!__traits(compiles, PropertyType!(i + 42))); 7057 static assert(!__traits(compiles, SymbolType!(i + 42))); 7058 static assert( is(typeof(i + 42) == int)); 7059 7060 // typeof will work with a function that takes arguments so long as it's 7061 // used in a proper expression. 7062 static assert( is(typeof(funcWithArg(42)) == int)); 7063 static assert( is(typeof(prop2 = 42) == void)); 7064 static assert( is(typeof(prop2(42)) == void)); 7065 } 7066 7067 /++ 7068 With templated types or functions, a specific instantiation should be 7069 passed to SymbolType or PropertyType, not the symbol for the template 7070 itself. If $(K_TYPEOF), SymbolType, or PropertyType is used on a template 7071 (rather than an instantiation of the template), the result will be 7072 $(K_VOID), because the template itself does not have a type. 7073 +/ 7074 @safe unittest 7075 { 7076 static T func(T)() { return T.init; } 7077 7078 static assert(is(SymbolType!func == void)); 7079 static assert(is(PropertyType!func == void)); 7080 static assert(is(typeof(func) == void)); 7081 7082 static assert(is(SymbolType!(func!int) == 7083 ToFunctionType!(int function() 7084 @safe pure nothrow @nogc))); 7085 static assert(is(PropertyType!(func!int) == int)); 7086 static assert(is(typeof(func!int) == SymbolType!(func!int))); 7087 7088 static assert(is(SymbolType!(func!string) == 7089 ToFunctionType!(string function() 7090 @safe pure nothrow @nogc))); 7091 static assert(is(PropertyType!(func!string) == string)); 7092 static assert(is(typeof(func!string) == SymbolType!(func!string))); 7093 } 7094 7095 /++ 7096 If a function is overloaded, then when using it as a symbol to pass to 7097 $(K_TYPEOF), the compiler typically selects the first overload. However, if 7098 the functions are marked with $(K_PROPERTY), and one of the overloads is a 7099 getter property, then $(K_TYPEOF) will select the getter property (or fail 7100 to compile if they're all setter properties). This is because it's getting 7101 the type of the function as an expression rather than doing introspection 7102 on the function itself. 7103 7104 SymbolType always gives the type of the first overload (effectively ignoring 7105 $(K_PROPERTY)), and PropertyType always gives the getter ovrerload 7106 (effectively treating all functions as if they had $(K_PROPERTY)). 7107 7108 If code needs to get the symbol for a specific overload, then 7109 $(DDSUBLINK spec/traits, getOverloads, $(D __traits(getOverloads, ...)) 7110 must be used. 7111 7112 In general, $(D getOverloads) should be used when using SymbolType, since 7113 there's no guarantee that the first one is the correct one (and often, code 7114 will need to check all of the overloads), whereas with PropertyType, it 7115 doesn't usually make sense to get specific overloads, because there can 7116 only ever be one overload which works as a getter property, and using 7117 PropertyType on the symbol for the function will give that overload if it's 7118 present, regardless of which overload is first (and it will fail to compile 7119 if there is no overload which can be called as a getter). 7120 +/ 7121 @safe unittest 7122 { 7123 static struct S 7124 { 7125 string foo(); 7126 void foo(string); 7127 bool foo(string, int); 7128 7129 @property void bar(int); 7130 @property int bar(); 7131 } 7132 7133 { 7134 static assert( is(SymbolType!(S.foo) == 7135 ToFunctionType!(string function()))); 7136 static assert( is(PropertyType!(S.foo) == string)); 7137 static assert( is(typeof(S.foo) == SymbolType!(S.foo))); 7138 7139 alias overloads = __traits(getOverloads, S, "foo"); 7140 7141 // string foo(); 7142 static assert( is(SymbolType!(overloads[0]) == function)); 7143 static assert( is(PropertyType!(overloads[0]) == string)); 7144 static assert( is(typeof(overloads[0]) == function)); 7145 7146 static assert( is(SymbolType!(overloads[0]) == 7147 ToFunctionType!(string function()))); 7148 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7149 7150 // void foo(string); 7151 static assert( is(SymbolType!(overloads[1]) == function)); 7152 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7153 static assert( is(typeof(overloads[1]) == function)); 7154 7155 static assert( is(SymbolType!(overloads[1]) == 7156 ToFunctionType!(void function(string)))); 7157 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7158 7159 // void foo(string, int); 7160 static assert( is(SymbolType!(overloads[2]) == function)); 7161 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7162 static assert( is(typeof(overloads[2]) == function)); 7163 7164 static assert( is(SymbolType!(overloads[2]) == 7165 ToFunctionType!(bool function(string, int)))); 7166 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7167 } 7168 { 7169 static assert( is(SymbolType!(S.bar) == 7170 ToFunctionType!(void function(int) @property))); 7171 static assert( is(PropertyType!(S.bar) == int)); 7172 static assert( is(typeof(S.bar) == PropertyType!(S.bar))); 7173 7174 alias overloads = __traits(getOverloads, S, "bar"); 7175 7176 // @property void bar(int); 7177 static assert( is(SymbolType!(overloads[0]) == function)); 7178 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7179 static assert(!__traits(compiles, typeof(overloads[0]))); 7180 7181 static assert( is(SymbolType!(overloads[0]) == 7182 ToFunctionType!(void function(int) @property))); 7183 7184 // @property int bar(); 7185 static assert( is(SymbolType!(overloads[1]) == function)); 7186 static assert( is(PropertyType!(overloads[1]) == int)); 7187 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 7188 7189 static assert( is(SymbolType!(overloads[1]) == 7190 ToFunctionType!(int function() @property))); 7191 } 7192 } 7193 7194 @safe unittest 7195 { 7196 { 7197 string str; 7198 int i; 7199 7200 static assert(!__traits(compiles, SymbolType!int)); 7201 static assert(!__traits(compiles, SymbolType!(str ~ "more str"))); 7202 static assert(!__traits(compiles, SymbolType!(i + 42))); 7203 static assert(!__traits(compiles, SymbolType!(&i))); 7204 7205 static assert(!__traits(compiles, PropertyType!int)); 7206 static assert(!__traits(compiles, PropertyType!(str ~ "more str"))); 7207 static assert(!__traits(compiles, PropertyType!(i + 42))); 7208 static assert(!__traits(compiles, PropertyType!(&i))); 7209 } 7210 7211 static assert( is(SymbolType!42 == int)); 7212 static assert( is(SymbolType!"dlang" == string)); 7213 7214 int var; 7215 7216 int funcWithContext() { return var; } 7217 static assert( is(SymbolType!funcWithContext == 7218 ToFunctionType!(int function() 7219 @safe pure nothrow @nogc))); 7220 static assert( is(PropertyType!funcWithContext == int)); 7221 static assert( is(typeof(funcWithContext) == SymbolType!funcWithContext)); 7222 7223 @property int propWithContext() { return var; } 7224 static assert( is(SymbolType!propWithContext == function)); 7225 static assert( is(SymbolType!propWithContext == 7226 ToFunctionType!(int function() @property @safe pure nothrow @nogc))); 7227 static assert( is(PropertyType!propWithContext == int)); 7228 static assert( is(typeof(propWithContext) == PropertyType!propWithContext)); 7229 7230 // For those who might be confused by this sort of declaration, this is a 7231 // property function which returns a function pointer that takes no 7232 // arguments and returns int, which gets an even uglier signature when 7233 // writing out the type for a pointer to such a property function. 7234 static int function() propFuncPtr() @property { return null; } 7235 static assert( is(SymbolType!propFuncPtr == function)); 7236 static assert( is(SymbolType!propFuncPtr == 7237 ToFunctionType!(int function() function() @property @safe pure nothrow @nogc))); 7238 static assert( is(PropertyType!propFuncPtr == int function())); 7239 static assert( is(typeof(propFuncPtr) == PropertyType!propFuncPtr)); 7240 7241 static int delegate() propDel() @property { return null; } 7242 static assert( is(SymbolType!propDel == function)); 7243 static assert( is(SymbolType!propDel == 7244 ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc))); 7245 static assert( is(PropertyType!propDel == int delegate())); 7246 static assert( is(typeof(propDel) == PropertyType!propDel)); 7247 7248 int function() propFuncPtrWithContext() @property { ++var; return null; } 7249 static assert( is(SymbolType!propFuncPtrWithContext == function)); 7250 static assert( is(SymbolType!propFuncPtrWithContext == 7251 ToFunctionType!(int function() function() @property @safe pure nothrow @nogc))); 7252 static assert( is(PropertyType!propFuncPtrWithContext == int function())); 7253 static assert( is(typeof(propFuncPtrWithContext) == PropertyType!propFuncPtrWithContext)); 7254 7255 int delegate() propDelWithContext() @property { ++var; return null; } 7256 static assert( is(SymbolType!propDelWithContext == function)); 7257 static assert( is(SymbolType!propDelWithContext == 7258 ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc))); 7259 static assert( is(PropertyType!propDelWithContext == int delegate())); 7260 static assert( is(typeof(propDelWithContext) == PropertyType!propDelWithContext)); 7261 7262 const int ci; 7263 static assert( is(SymbolType!ci == const int)); 7264 static assert( is(PropertyType!ci == const int)); 7265 static assert( is(typeof(ci) == PropertyType!ci)); 7266 7267 shared int si; 7268 static assert( is(SymbolType!si == shared int)); 7269 static assert( is(PropertyType!si == shared int)); 7270 static assert( is(typeof(si) == PropertyType!si)); 7271 7272 static struct S 7273 { 7274 int i; 7275 @disable this(this); 7276 } 7277 static assert(!__traits(isCopyable, S)); 7278 7279 S s; 7280 static assert( is(SymbolType!s == S)); 7281 static assert( is(PropertyType!s == S)); 7282 static assert( is(typeof(s) == SymbolType!s)); 7283 7284 static ref S foo(); 7285 static void bar(ref S); 7286 7287 static @property ref S bob(); 7288 static @property void sally(ref S); 7289 7290 // The aliases are due to https://github.com/dlang/dmd/issues/17505 7291 // Apparently, aliases are special-cased to work with function pointer 7292 // signatures which return by ref, and we can't do it elsewhere. 7293 alias FooPtr = ref S function(); 7294 static assert( is(SymbolType!foo == ToFunctionType!FooPtr)); 7295 static assert( is(PropertyType!foo == S)); 7296 static assert( is(typeof(foo) == SymbolType!foo)); 7297 7298 static assert( is(SymbolType!bar == ToFunctionType!(void function(ref S)))); 7299 static assert(!__traits(compiles, PropertyType!bar)); 7300 static assert( is(typeof(bar) == SymbolType!bar)); 7301 7302 alias BobPtr = ref S function() @property; 7303 static assert( is(SymbolType!bob == ToFunctionType!BobPtr)); 7304 static assert( is(PropertyType!bob == S)); 7305 static assert( is(typeof(bob) == S)); 7306 static assert( is(typeof(bob) == PropertyType!bob)); 7307 7308 static assert( is(SymbolType!sally == ToFunctionType!(void function(ref S) @property))); 7309 static assert(!__traits(compiles, PropertyType!sally)); 7310 static assert(!__traits(compiles, typeof(sally))); 7311 7312 string defaultArgs1(int i = 0); 7313 void defaultArgs2(string, int i = 0); 7314 7315 static assert( is(SymbolType!defaultArgs1 == ToFunctionType!(string function(int)))); 7316 static assert( is(PropertyType!defaultArgs1 == string)); 7317 static assert( is(typeof(defaultArgs1) == SymbolType!defaultArgs1)); 7318 7319 static assert( is(SymbolType!defaultArgs2 == ToFunctionType!(void function(string, int)))); 7320 static assert(!__traits(compiles, PropertyType!defaultArgs2)); 7321 static assert( is(typeof(defaultArgs2) == SymbolType!defaultArgs2)); 7322 7323 @property string defaultArgsProp1(int i = 0); 7324 @property void defaultArgsProp2(string, int i = 0); 7325 7326 static assert( is(SymbolType!defaultArgsProp1 == ToFunctionType!(string function(int) @property))); 7327 static assert( is(PropertyType!defaultArgsProp1 == string)); 7328 static assert( is(typeof(defaultArgsProp1) == PropertyType!defaultArgsProp1)); 7329 7330 static assert( is(SymbolType!defaultArgsProp2 == ToFunctionType!(void function(string, int) @property))); 7331 static assert(!__traits(compiles, PropertyType!defaultArgsProp2)); 7332 static assert(!__traits(compiles, typeof(defaultArgsProp2))); 7333 7334 int returningSetter(string); 7335 @property int returningSetterProp(string); 7336 7337 static assert( is(SymbolType!returningSetter == ToFunctionType!(int function(string)))); 7338 static assert(!__traits(compiles, PropertyType!returningSetter)); 7339 static assert( is(typeof(returningSetter) == SymbolType!returningSetter)); 7340 7341 static assert( is(SymbolType!returningSetterProp == ToFunctionType!(int function(string) @property))); 7342 static assert(!__traits(compiles, PropertyType!returningSetterProp)); 7343 static assert(!__traits(compiles, typeof(returningSetterProp))); 7344 } 7345 7346 // These are for the next unittest block to test overloaded free functions (in 7347 // addition to the overloaded member functions and static functions that it 7348 // tests). That way, if there are any differences in how free functions and 7349 // member functions are handled, we'll catch those bugs (be they compiler bugs 7350 // or bugs in phobos.sys.traits). 7351 version (PhobosUnittest) 7352 { 7353 private void modFunc1(); 7354 private void modFunc1(string); 7355 private int modFunc1(string, int); 7356 7357 private int modFunc2(); 7358 private int modFunc2(string); 7359 private string modFunc2(string, int); 7360 7361 private void modFunc3(int*); 7362 private void modFunc3(float); 7363 private string modFunc3(int a = 0); 7364 7365 private int modGetterFirst(); 7366 private void modGetterFirst(int); 7367 7368 private void modSetterFirst(int); 7369 private int modSetterFirst(); 7370 7371 private void modSetterOnly(string); 7372 private void modSetterOnly(int); 7373 7374 private @property int modPropGetterFirst(); 7375 private @property void modPropGetterFirst(int); 7376 7377 private @property void modPropSetterFirst(int); 7378 private @property int modPropSetterFirst(); 7379 7380 private @property void modPropSetterOnly(string); 7381 private @property void modPropSetterOnly(int); 7382 7383 private int function() @property modGetterFirstFuncPtr(); 7384 private void modGetterFirstFuncPtr(int function() @property); 7385 7386 private void modSetterFirstFuncPtr(int function() @property); 7387 private int function() @property modSetterFirstFuncPtr(); 7388 7389 private int function() @property modPropGetterFirstFuncPtr() @property; 7390 private void modPropGetterFirstFuncPtr(int function() @property) @property; 7391 7392 private void modPropSetterFirstFuncPtr(int function() @property) @property; 7393 private int function() @property modPropSetterFirstFuncPtr() @property; 7394 } 7395 7396 @safe unittest 7397 { 7398 // Note that with overloads without @property, typeof gives the first 7399 // overload, whereas with overloads with @property, typeof gives the return 7400 // type of the getter overload no matter where it is in the order. 7401 // PropertyType needs to always give the getter overload whether @property 7402 // is used or not, since that's the type of the symbol when used as a 7403 // getter property in an expression. 7404 { 7405 alias module_ = __traits(parent, __traits(parent, {})); 7406 7407 // void modFunc1(); 7408 // void modFunc1(string); 7409 // int modFunc1(string, int); 7410 { 7411 static assert( is(SymbolType!modFunc1 == ToFunctionType!(void function()))); 7412 static assert(!__traits(compiles, PropertyType!modFunc1)); 7413 static assert( is(typeof(modFunc1) == SymbolType!modFunc1)); 7414 7415 alias overloads = __traits(getOverloads, module_, "modFunc1"); 7416 static assert(overloads.length == 3); 7417 7418 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function()))); 7419 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7420 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7421 7422 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string)))); 7423 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7424 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7425 7426 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int function(string, int)))); 7427 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7428 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7429 } 7430 7431 // int modFunc2(); 7432 // int modFunc2(string); 7433 // string modFunc2(string, int); 7434 { 7435 static assert( is(SymbolType!modFunc2 == ToFunctionType!(int function()))); 7436 static assert( is(PropertyType!modFunc2 == int)); 7437 static assert( is(typeof(modFunc2) == SymbolType!modFunc2)); 7438 7439 alias overloads = __traits(getOverloads, module_, "modFunc2"); 7440 static assert(overloads.length == 3); 7441 7442 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 7443 static assert( is(PropertyType!(overloads[0]) == int)); 7444 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7445 7446 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 7447 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7448 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7449 7450 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(string, int)))); 7451 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7452 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7453 } 7454 7455 // void modFunc3(int*); 7456 // void modFunc3(float); 7457 // string modFunc3(int a = 0); 7458 { 7459 static assert( is(SymbolType!modFunc3 == ToFunctionType!(void function(int*)))); 7460 static assert( is(PropertyType!modFunc3 == string)); 7461 static assert( is(typeof(modFunc3) == SymbolType!modFunc3)); 7462 7463 alias overloads = __traits(getOverloads, module_, "modFunc3"); 7464 static assert(overloads.length == 3); 7465 7466 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int*)))); 7467 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7468 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7469 7470 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(float)))); 7471 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7472 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7473 7474 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(int)))); 7475 static assert( is(PropertyType!(overloads[2]) == string)); 7476 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7477 } 7478 7479 // int modGetterFirst(); 7480 // void modGetterFirst(int); 7481 { 7482 static assert( is(SymbolType!modGetterFirst == ToFunctionType!(int function()))); 7483 static assert( is(PropertyType!modGetterFirst == int)); 7484 static assert( is(typeof(modGetterFirst) == SymbolType!modGetterFirst)); 7485 7486 alias overloads = __traits(getOverloads, module_, "modGetterFirst"); 7487 static assert(overloads.length == 2); 7488 7489 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 7490 static assert( is(PropertyType!(overloads[0]) == int)); 7491 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7492 7493 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 7494 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7495 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7496 } 7497 7498 // void modSetterFirst(int); 7499 // int modSetterFirst(); 7500 { 7501 static assert( is(SymbolType!modSetterFirst == ToFunctionType!(void function(int)))); 7502 static assert( is(PropertyType!modSetterFirst == int)); 7503 static assert( is(typeof(modSetterFirst) == SymbolType!modSetterFirst)); 7504 7505 alias overloads = __traits(getOverloads, module_, "modSetterFirst"); 7506 static assert(overloads.length == 2); 7507 7508 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 7509 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7510 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7511 7512 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 7513 static assert( is(PropertyType!(overloads[1]) == int)); 7514 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7515 } 7516 7517 // void modSetterOnly(string); 7518 // void modSetterOnly(int); 7519 { 7520 static assert( is(SymbolType!modSetterOnly == ToFunctionType!(void function(string)))); 7521 static assert(!__traits(compiles, PropertyType!modSetterOnly)); 7522 static assert( is(typeof(modSetterOnly) == SymbolType!modSetterOnly)); 7523 7524 alias overloads = __traits(getOverloads, module_, "modSetterOnly"); 7525 static assert(overloads.length == 2); 7526 7527 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string)))); 7528 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7529 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7530 7531 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 7532 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7533 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7534 } 7535 7536 // @property int modPropGetterFirst(); 7537 // @property void modPropGetterFirst(int); 7538 { 7539 static assert( is(SymbolType!modPropGetterFirst == ToFunctionType!(int function() @property))); 7540 static assert( is(PropertyType!modPropGetterFirst == int)); 7541 static assert( is(typeof(modPropGetterFirst) == PropertyType!modPropGetterFirst)); 7542 7543 alias overloads = __traits(getOverloads, module_, "modPropGetterFirst"); 7544 static assert(overloads.length == 2); 7545 7546 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property))); 7547 static assert( is(PropertyType!(overloads[0]) == int)); 7548 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 7549 7550 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 7551 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7552 static assert(!__traits(compiles, typeof((overloads[1])))); 7553 } 7554 7555 // @property void modPropSetterFirst(int); 7556 // @property int modPropSetterFirst(); 7557 { 7558 static assert( is(SymbolType!modPropSetterFirst == ToFunctionType!(void function(int) @property))); 7559 static assert( is(PropertyType!modPropSetterFirst == int)); 7560 static assert( is(typeof(modPropSetterFirst) == PropertyType!modPropSetterFirst)); 7561 7562 alias overloads = __traits(getOverloads, module_, "modPropSetterFirst"); 7563 static assert(overloads.length == 2); 7564 7565 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 7566 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7567 static assert(!__traits(compiles, typeof(overloads[0]))); 7568 7569 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 7570 static assert( is(PropertyType!(overloads[1]) == int)); 7571 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 7572 } 7573 7574 // @property void modPropSetterOnly(string); 7575 // @property void modPropSetterOnly(int); 7576 { 7577 static assert( is(SymbolType!modPropSetterOnly == ToFunctionType!(void function(string) @property))); 7578 static assert(!__traits(compiles, PropertyType!modPropSetterOnly)); 7579 static assert(!__traits(compiles, typeof(modPropSetterOnly))); 7580 7581 alias overloads = __traits(getOverloads, module_, "modPropSetterOnly"); 7582 static assert(overloads.length == 2); 7583 7584 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property))); 7585 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7586 static assert(!__traits(compiles, typeof(overloads[0]))); 7587 7588 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 7589 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7590 static assert(!__traits(compiles, typeof(overloads[1]))); 7591 } 7592 7593 // int function() @property modGetterFirstFuncPtr(); 7594 // void modGetterFirstFuncPtr(int function() @property); 7595 { 7596 static assert( is(SymbolType!modGetterFirstFuncPtr == 7597 ToFunctionType!(int function() @property function()))); 7598 static assert( is(PropertyType!modGetterFirstFuncPtr == int function() @property)); 7599 static assert( is(typeof(modGetterFirstFuncPtr) == SymbolType!modGetterFirstFuncPtr)); 7600 7601 alias overloads = __traits(getOverloads, module_, "modGetterFirstFuncPtr"); 7602 static assert(overloads.length == 2); 7603 7604 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property function()))); 7605 static assert( is(PropertyType!(overloads[0]) == int function() @property)); 7606 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7607 7608 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int function() @property)))); 7609 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7610 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7611 } 7612 7613 // void modSetterFirstFuncPtr(int function() @property); 7614 // int function() @property modSetterFirstFuncPtr(); 7615 { 7616 static assert( is(SymbolType!modSetterFirstFuncPtr == 7617 ToFunctionType!(void function(int function() @property)))); 7618 static assert( is(PropertyType!modSetterFirstFuncPtr == int function() @property)); 7619 static assert( is(typeof(modSetterFirstFuncPtr) == SymbolType!modSetterFirstFuncPtr)); 7620 7621 alias overloads = __traits(getOverloads, module_, "modSetterFirstFuncPtr"); 7622 static assert(overloads.length == 2); 7623 7624 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int function() @property)))); 7625 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7626 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7627 7628 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property function()))); 7629 static assert( is(PropertyType!(overloads[1]) == int function() @property)); 7630 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7631 } 7632 7633 // int function() @property modPropGetterFirstFuncPtr() @property; 7634 // void modPropGetterFirstFuncPtr(int function() @property) @property; 7635 { 7636 static assert( is(SymbolType!modPropGetterFirstFuncPtr == 7637 ToFunctionType!(int function() @property function() @property))); 7638 static assert( is(PropertyType!modPropGetterFirstFuncPtr == int function() @property)); 7639 static assert( is(typeof(modPropGetterFirstFuncPtr) == PropertyType!modPropGetterFirstFuncPtr)); 7640 7641 alias overloads = __traits(getOverloads, module_, "modPropGetterFirstFuncPtr"); 7642 static assert(overloads.length == 2); 7643 7644 static assert( is(SymbolType!(overloads[0]) == 7645 ToFunctionType!(int function() @property function() @property))); 7646 static assert( is(PropertyType!(overloads[0]) == int function() @property)); 7647 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 7648 7649 static assert( is(SymbolType!(overloads[1]) == 7650 ToFunctionType!(void function(int function() @property) @property))); 7651 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7652 static assert(!__traits(compiles, typeof((overloads[1])))); 7653 } 7654 7655 // void modPropSetterFirstFuncPtr(int function() @property) @property; 7656 // int function() @property modPropSetterFirstFuncPtr() @property; 7657 { 7658 static assert( is(SymbolType!modPropSetterFirstFuncPtr == 7659 ToFunctionType!(void function(int function() @property) @property))); 7660 static assert( is(PropertyType!modPropSetterFirstFuncPtr == int function() @property)); 7661 static assert( is(typeof(modPropSetterFirstFuncPtr) == PropertyType!modPropSetterFirstFuncPtr)); 7662 7663 alias overloads = __traits(getOverloads, module_, "modPropSetterFirstFuncPtr"); 7664 static assert(overloads.length == 2); 7665 7666 static assert( is(SymbolType!(overloads[0]) == 7667 ToFunctionType!(void function(int function() @property) @property))); 7668 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7669 static assert(!__traits(compiles, typeof(overloads[0]))); 7670 7671 static assert( is(SymbolType!(overloads[1]) == 7672 ToFunctionType!(int function() @property function() @property))); 7673 static assert( is(PropertyType!(overloads[1]) == int function() @property)); 7674 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 7675 } 7676 } 7677 7678 { 7679 static struct S 7680 { 7681 int[] arr1; 7682 immutable bool[] arr2; 7683 7684 void foo(); 7685 static void bar(); 7686 7687 long bob(); 7688 void sally(long); 7689 7690 @property long propGetter(); 7691 @property void propSetter(int[]); 7692 7693 static @property long staticPropGetter(); 7694 static @property void staticPropSetter(int[]); 7695 7696 void func1(); 7697 void func1(int[]); 7698 long func1(int[], long); 7699 7700 long func2(); 7701 long func2(int[]); 7702 int[] func2(int[], long); 7703 7704 void func3(long*); 7705 void func3(real); 7706 int[] func3(long a = 0); 7707 7708 long getterFirst(); 7709 void getterFirst(long); 7710 7711 void setterFirst(long); 7712 long setterFirst(); 7713 7714 void setterOnly(int[]); 7715 void setterOnly(long); 7716 7717 static long staticGetterFirst(); 7718 static void staticGetterFirst(long); 7719 7720 static void staticSetterFirst(long); 7721 static long staticSetterFirst(); 7722 7723 static void staticSetterOnly(int[]); 7724 static void staticSetterOnly(long); 7725 7726 @property long propGetterFirst(); 7727 @property void propGetterFirst(long); 7728 7729 @property void propSetterFirst(long); 7730 @property long propSetterFirst(); 7731 7732 @property void propSetterOnly(int[]); 7733 @property void propSetterOnly(long); 7734 7735 static @property long staticPropGetterFirst(); 7736 static @property void staticPropGetterFirst(long); 7737 7738 static @property void staticPropSetterFirst(long); 7739 static @property long staticPropSetterFirst(); 7740 7741 static @property void staticPropSetterOnly(int[]); 7742 static @property void staticPropSetterOnly(long); 7743 7744 long function() @property getterFirstFuncPtr(); 7745 void getterFirstFuncPtr(long function() @property); 7746 7747 void setterFirstFuncPtr(long function() @property); 7748 long function() @property setterFirstFuncPtr(); 7749 7750 long function() @property propGetterFirstFuncPtr() @property; 7751 void propGetterFirstFuncPtr(long function() @property) @property; 7752 7753 void propSetterFirstFuncPtr(long function() @property) @property; 7754 long function() @property propSetterFirstFuncPtr() @property; 7755 7756 static long delegate() @property staticGetterFirstDel(); 7757 static void staticGetterFirstDel(long delegate() @property); 7758 7759 static void staticSetterFirstDel(long delegate() @property); 7760 static long delegate() @property staticSetterFirstDel(); 7761 7762 static long delegate() @property staticPropGetterFirstDel() @property; 7763 static void staticPropGetterFirstDel(long delegate() @property) @property; 7764 7765 static void staticPropSetterFirstDel(long delegate() @property) @property; 7766 static long delegate() @property staticPropSetterFirstDel() @property; 7767 } 7768 7769 // int[] arr1; 7770 // immutable bool[] arr2; 7771 static assert( is(SymbolType!(S.arr1) == int[])); 7772 static assert( is(PropertyType!(S.arr1) == int[])); 7773 static assert( is(typeof(S.arr1) == int[])); 7774 7775 static assert( is(SymbolType!(S.arr2) == immutable bool[])); 7776 static assert( is(PropertyType!(S.arr2) == immutable bool[])); 7777 static assert( is(typeof(S.arr2) == immutable bool[])); 7778 7779 // void foo(); 7780 static assert( is(SymbolType!(S.foo) == function)); 7781 static assert( is(SymbolType!(S.foo) == ToFunctionType!(void function()))); 7782 static assert(!__traits(compiles, PropertyType!(S.foo))); 7783 static assert( is(typeof(S.foo) == SymbolType!(S.foo))); 7784 7785 //static void bar(); 7786 static assert( is(SymbolType!(S.bar) == function)); 7787 static assert( is(SymbolType!(S.bar) == ToFunctionType!(void function()))); 7788 static assert(!__traits(compiles, PropertyType!(S.bar))); 7789 static assert( is(typeof(S.bar) == SymbolType!(S.bar))); 7790 7791 // long bob(); 7792 static assert( is(SymbolType!(S.bob) == function)); 7793 static assert( is(SymbolType!(S.bob) == ToFunctionType!(long function()))); 7794 static assert( is(PropertyType!(S.bob) == long)); 7795 static assert( is(typeof(S.bob) == SymbolType!(S.bob))); 7796 7797 // void sally(long); 7798 static assert( is(SymbolType!(S.sally) == function)); 7799 static assert( is(SymbolType!(S.sally) == ToFunctionType!(void function(long)))); 7800 static assert(!__traits(compiles, PropertyType!(S.sally))); 7801 static assert( is(typeof(S.sally) == SymbolType!(S.sally))); 7802 7803 // @property long propGetter(); 7804 static assert( is(SymbolType!(S.propGetter) == function)); 7805 static assert( is(SymbolType!(S.propGetter) == ToFunctionType!(long function() @property))); 7806 static assert( is(PropertyType!(S.propGetter) == long)); 7807 static assert( is(typeof(S.propGetter) == PropertyType!(S.propGetter))); 7808 7809 // @property void propSetter(int[]); 7810 static assert( is(SymbolType!(S.propSetter) == function)); 7811 static assert( is(SymbolType!(S.propSetter) == ToFunctionType!(void function(int[]) @property))); 7812 static assert(!__traits(compiles, PropertyType!(S.propSetter))); 7813 static assert(!__traits(compiles, typeof(S.propSetter))); 7814 7815 // static @property long staticPropGetter(); 7816 static assert( is(SymbolType!(S.staticPropGetter) == function)); 7817 static assert( is(SymbolType!(S.staticPropGetter) == ToFunctionType!(long function() @property))); 7818 static assert( is(PropertyType!(S.staticPropGetter) == long)); 7819 static assert( is(typeof(S.staticPropGetter) == PropertyType!(S.staticPropGetter))); 7820 7821 // static @property void staticPropSetter(int[]); 7822 static assert( is(SymbolType!(S.staticPropSetter) == function)); 7823 static assert( is(SymbolType!(S.staticPropSetter) == ToFunctionType!(void function(int[]) @property))); 7824 static assert(!__traits(compiles, PropertyType!(S.staticPropSetter))); 7825 static assert(!__traits(compiles, typeof(S.staticPropSetter))); 7826 7827 // void func1(); 7828 // void func1(int[]); 7829 // long func1(int[], long); 7830 { 7831 static assert( is(SymbolType!(S.func1) == ToFunctionType!(void function()))); 7832 static assert(!__traits(compiles, PropertyType!(S.func1))); 7833 static assert( is(typeof((S.func1)) == SymbolType!(S.func1))); 7834 7835 alias overloads = __traits(getOverloads, S, "func1"); 7836 static assert(overloads.length == 3); 7837 7838 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function()))); 7839 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7840 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7841 7842 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int[])))); 7843 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7844 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7845 7846 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(long function(int[], long)))); 7847 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7848 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7849 } 7850 7851 // long func2(); 7852 // long func2(int[]); 7853 // int[] func2(int[], long); 7854 { 7855 static assert( is(SymbolType!(S.func2) == ToFunctionType!(long function()))); 7856 static assert( is(PropertyType!(S.func2) == long)); 7857 static assert( is(typeof((S.func2)) == SymbolType!(S.func2))); 7858 7859 alias overloads = __traits(getOverloads, S, "func2"); 7860 static assert(overloads.length == 3); 7861 7862 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function()))); 7863 static assert( is(PropertyType!(overloads[0]) == long)); 7864 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7865 7866 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function(int[])))); 7867 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7868 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7869 7870 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(int[], long)))); 7871 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7872 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7873 } 7874 7875 // void func3(long*); 7876 // void func3(real); 7877 // int[] func3(long a = 0); 7878 { 7879 static assert( is(SymbolType!(S.func3) == ToFunctionType!(void function(long*)))); 7880 static assert( is(PropertyType!(S.func3) == int[])); 7881 static assert( is(typeof((S.func3)) == SymbolType!(S.func3))); 7882 7883 alias overloads = __traits(getOverloads, S, "func3"); 7884 static assert(overloads.length == 3); 7885 7886 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long*)))); 7887 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7888 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7889 7890 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real)))); 7891 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7892 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7893 7894 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(long)))); 7895 static assert( is(PropertyType!(overloads[2]) == int[])); 7896 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7897 } 7898 7899 // long getterFirst(); 7900 // void getterFirst(long); 7901 { 7902 static assert( is(SymbolType!(S.getterFirst) == ToFunctionType!(long function()))); 7903 static assert( is(PropertyType!(S.getterFirst) == long)); 7904 static assert( is(typeof((S.getterFirst)) == SymbolType!(S.getterFirst))); 7905 7906 alias overloads = __traits(getOverloads, S, "getterFirst"); 7907 static assert(overloads.length == 2); 7908 7909 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function()))); 7910 static assert( is(PropertyType!(overloads[0]) == long)); 7911 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7912 7913 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 7914 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7915 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7916 } 7917 7918 // void setterFirst(long); 7919 // long setterFirst(); 7920 { 7921 static assert( is(SymbolType!(S.setterFirst) == ToFunctionType!(void function(long)))); 7922 static assert( is(PropertyType!(S.setterFirst) == long)); 7923 static assert( is(typeof((S.setterFirst)) == SymbolType!(S.setterFirst))); 7924 7925 alias overloads = __traits(getOverloads, S, "setterFirst"); 7926 static assert(overloads.length == 2); 7927 7928 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long)))); 7929 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7930 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7931 7932 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function()))); 7933 static assert( is(PropertyType!(overloads[1]) == long)); 7934 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7935 } 7936 7937 // void setterOnly(int[]); 7938 // void setterOnly(long); 7939 { 7940 static assert( is(SymbolType!(S.setterOnly) == ToFunctionType!(void function(int[])))); 7941 static assert(!__traits(compiles, PropertyType!(S.setterOnly))); 7942 static assert( is(typeof((S.setterOnly)) == SymbolType!(S.setterOnly))); 7943 7944 alias overloads = __traits(getOverloads, S, "setterOnly"); 7945 static assert(overloads.length == 2); 7946 7947 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[])))); 7948 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7949 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7950 7951 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 7952 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7953 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7954 } 7955 7956 // long staticGetterFirst(); 7957 // void staticGetterFirst(long); 7958 { 7959 static assert( is(SymbolType!(S.staticGetterFirst) == ToFunctionType!(long function()))); 7960 static assert( is(PropertyType!(S.staticGetterFirst) == long)); 7961 static assert( is(typeof((S.staticGetterFirst)) == SymbolType!(S.staticGetterFirst))); 7962 7963 alias overloads = __traits(getOverloads, S, "staticGetterFirst"); 7964 static assert(overloads.length == 2); 7965 7966 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function()))); 7967 static assert( is(PropertyType!(overloads[0]) == long)); 7968 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7969 7970 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 7971 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7972 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7973 } 7974 7975 // void staticSetterFirst(long); 7976 // long staticSetterFirst(); 7977 { 7978 static assert( is(SymbolType!(S.staticSetterFirst) == ToFunctionType!(void function(long)))); 7979 static assert( is(PropertyType!(S.staticSetterFirst) == long)); 7980 static assert( is(typeof((S.staticSetterFirst)) == SymbolType!(S.staticSetterFirst))); 7981 7982 alias overloads = __traits(getOverloads, S, "staticSetterFirst"); 7983 static assert(overloads.length == 2); 7984 7985 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long)))); 7986 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7987 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7988 7989 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function()))); 7990 static assert( is(PropertyType!(overloads[1]) == long)); 7991 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7992 } 7993 7994 // void staticSetterOnly(int[]); 7995 // void staticSetterOnly(long); 7996 { 7997 static assert( is(SymbolType!(S.staticSetterOnly) == ToFunctionType!(void function(int[])))); 7998 static assert(!__traits(compiles, PropertyType!(S.staticSetterOnly))); 7999 static assert( is(typeof((S.staticSetterOnly)) == SymbolType!(S.staticSetterOnly))); 8000 8001 alias overloads = __traits(getOverloads, S, "staticSetterOnly"); 8002 static assert(overloads.length == 2); 8003 8004 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[])))); 8005 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8006 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8007 8008 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 8009 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8010 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8011 } 8012 8013 // @property long propGetterFirst(); 8014 // @property void propGetterFirst(long); 8015 { 8016 static assert( is(SymbolType!(S.propGetterFirst) == ToFunctionType!(long function() @property))); 8017 static assert( is(PropertyType!(S.propGetterFirst) == long)); 8018 static assert( is(typeof((S.propGetterFirst)) == PropertyType!(S.propGetterFirst))); 8019 8020 alias overloads = __traits(getOverloads, S, "propGetterFirst"); 8021 static assert(overloads.length == 2); 8022 8023 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 8024 static assert( is(PropertyType!(overloads[0]) == long)); 8025 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8026 8027 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 8028 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8029 static assert(!__traits(compiles, typeof((overloads[1])))); 8030 } 8031 8032 // @property void propSetterFirst(long); 8033 // @property long propSetterFirst(); 8034 { 8035 static assert( is(SymbolType!(S.propSetterFirst) == ToFunctionType!(void function(long) @property))); 8036 static assert( is(PropertyType!(S.propSetterFirst) == long)); 8037 static assert( is(typeof((S.propSetterFirst)) == PropertyType!(S.propSetterFirst))); 8038 8039 alias overloads = __traits(getOverloads, S, "propSetterFirst"); 8040 static assert(overloads.length == 2); 8041 8042 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property))); 8043 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8044 static assert(!__traits(compiles, typeof(overloads[0]))); 8045 8046 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property))); 8047 static assert( is(PropertyType!(overloads[1]) == long)); 8048 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8049 } 8050 8051 // @property void propSetterOnly(int[]); 8052 // @property void propSetterOnly(long); 8053 { 8054 static assert( is(SymbolType!(S.propSetterOnly) == ToFunctionType!(void function(int[]) @property))); 8055 static assert(!__traits(compiles, PropertyType!(S.propSetterOnly))); 8056 static assert(!__traits(compiles, typeof((S.propSetterOnly)))); 8057 8058 alias overloads = __traits(getOverloads, S, "propSetterOnly"); 8059 static assert(overloads.length == 2); 8060 8061 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property))); 8062 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8063 static assert(!__traits(compiles, typeof(overloads[0]))); 8064 8065 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 8066 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8067 static assert(!__traits(compiles, typeof(overloads[1]))); 8068 } 8069 8070 // @property long staticPropGetterFirst(); 8071 // @property void staticPropGetterFirst(long); 8072 { 8073 static assert( is(SymbolType!(S.staticPropGetterFirst) == ToFunctionType!(long function() @property))); 8074 static assert( is(PropertyType!(S.staticPropGetterFirst) == long)); 8075 static assert( is(typeof((S.staticPropGetterFirst)) == PropertyType!(S.staticPropGetterFirst))); 8076 8077 alias overloads = __traits(getOverloads, S, "staticPropGetterFirst"); 8078 static assert(overloads.length == 2); 8079 8080 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 8081 static assert( is(PropertyType!(overloads[0]) == long)); 8082 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8083 8084 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 8085 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8086 static assert(!__traits(compiles, typeof((overloads[1])))); 8087 } 8088 8089 // @property void staticPropSetterFirst(long); 8090 // @property long staticPropSetterFirst(); 8091 { 8092 static assert( is(SymbolType!(S.staticPropSetterFirst) == ToFunctionType!(void function(long) @property))); 8093 static assert( is(PropertyType!(S.staticPropSetterFirst) == long)); 8094 static assert( is(typeof((S.staticPropSetterFirst)) == PropertyType!(S.staticPropSetterFirst))); 8095 8096 alias overloads = __traits(getOverloads, S, "staticPropSetterFirst"); 8097 static assert(overloads.length == 2); 8098 8099 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property))); 8100 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8101 static assert(!__traits(compiles, typeof(overloads[0]))); 8102 8103 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property))); 8104 static assert( is(PropertyType!(overloads[1]) == long)); 8105 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8106 } 8107 8108 // @property void staticPropSetterOnly(int[]); 8109 // @property void staticPropSetterOnly(long); 8110 { 8111 static assert( is(SymbolType!(S.staticPropSetterOnly) == ToFunctionType!(void function(int[]) @property))); 8112 static assert(!__traits(compiles, PropertyType!(S.staticPropSetterOnly))); 8113 static assert(!__traits(compiles, typeof((S.staticPropSetterOnly)))); 8114 8115 alias overloads = __traits(getOverloads, S, "staticPropSetterOnly"); 8116 static assert(overloads.length == 2); 8117 8118 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property))); 8119 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8120 static assert(!__traits(compiles, typeof(overloads[0]))); 8121 8122 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 8123 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8124 static assert(!__traits(compiles, typeof(overloads[1]))); 8125 } 8126 8127 // long function() @property getterFirstFuncPtr(); 8128 // void getterFirstFuncPtr(long function() @property); 8129 { 8130 static assert( is(SymbolType!(S.getterFirstFuncPtr) == 8131 ToFunctionType!(long function() @property function()))); 8132 static assert( is(PropertyType!(S.getterFirstFuncPtr) == long function() @property)); 8133 static assert( is(typeof((S.getterFirstFuncPtr)) == SymbolType!(S.getterFirstFuncPtr))); 8134 8135 alias overloads = __traits(getOverloads, S, "getterFirstFuncPtr"); 8136 static assert(overloads.length == 2); 8137 8138 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property function()))); 8139 static assert( is(PropertyType!(overloads[0]) == long function() @property)); 8140 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8141 8142 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long function() @property)))); 8143 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8144 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8145 } 8146 8147 // void setterFirstFuncPtr(long function() @property); 8148 // long function() @property setterFirstFuncPtr(); 8149 { 8150 static assert( is(SymbolType!(S.setterFirstFuncPtr) == 8151 ToFunctionType!(void function(long function() @property)))); 8152 static assert( is(PropertyType!(S.setterFirstFuncPtr) == long function() @property)); 8153 static assert( is(typeof((S.setterFirstFuncPtr)) == SymbolType!(S.setterFirstFuncPtr))); 8154 8155 alias overloads = __traits(getOverloads, S, "setterFirstFuncPtr"); 8156 static assert(overloads.length == 2); 8157 8158 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long function() @property)))); 8159 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8160 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8161 8162 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property function()))); 8163 static assert( is(PropertyType!(overloads[1]) == long function() @property)); 8164 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8165 } 8166 8167 // long function() @property propGetterFirstFuncPtr() @property; 8168 // void propGetterFirstFuncPtr(long function() @property) @property; 8169 { 8170 static assert( is(SymbolType!(S.propGetterFirstFuncPtr) == 8171 ToFunctionType!(long function() @property function() @property))); 8172 static assert( is(PropertyType!(S.propGetterFirstFuncPtr) == long function() @property)); 8173 static assert( is(typeof((S.propGetterFirstFuncPtr)) == PropertyType!(S.propGetterFirstFuncPtr))); 8174 8175 alias overloads = __traits(getOverloads, S, "propGetterFirstFuncPtr"); 8176 static assert(overloads.length == 2); 8177 8178 static assert( is(SymbolType!(overloads[0]) == 8179 ToFunctionType!(long function() @property function() @property))); 8180 static assert( is(PropertyType!(overloads[0]) == long function() @property)); 8181 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8182 8183 static assert( is(SymbolType!(overloads[1]) == 8184 ToFunctionType!(void function(long function() @property) @property))); 8185 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8186 static assert(!__traits(compiles, typeof((overloads[1])))); 8187 } 8188 8189 // void propSetterFirstFuncPtr(long function() @property) @property; 8190 // long function() @property propSetterFirstFuncPtr() @property; 8191 { 8192 static assert( is(SymbolType!(S.propSetterFirstFuncPtr) == 8193 ToFunctionType!(void function(long function() @property) @property))); 8194 static assert( is(PropertyType!(S.propSetterFirstFuncPtr) == long function() @property)); 8195 static assert( is(typeof((S.propSetterFirstFuncPtr)) == PropertyType!(S.propSetterFirstFuncPtr))); 8196 8197 alias overloads = __traits(getOverloads, S, "propSetterFirstFuncPtr"); 8198 static assert(overloads.length == 2); 8199 8200 static assert( is(SymbolType!(overloads[0]) == 8201 ToFunctionType!(void function(long function() @property) @property))); 8202 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8203 static assert(!__traits(compiles, typeof(overloads[0]))); 8204 8205 static assert( is(SymbolType!(overloads[1]) == 8206 ToFunctionType!(long function() @property function() @property))); 8207 static assert( is(PropertyType!(overloads[1]) == long function() @property)); 8208 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8209 } 8210 8211 // long function() @property staticGetterFirstDel(); 8212 // void staticGetterFirstDel(long function() @property); 8213 { 8214 static assert( is(SymbolType!(S.staticGetterFirstDel) == 8215 ToFunctionType!(long delegate() @property function()))); 8216 static assert( is(PropertyType!(S.staticGetterFirstDel) == long delegate() @property)); 8217 static assert( is(typeof((S.staticGetterFirstDel)) == SymbolType!(S.staticGetterFirstDel))); 8218 8219 alias overloads = __traits(getOverloads, S, "staticGetterFirstDel"); 8220 static assert(overloads.length == 2); 8221 8222 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long delegate() @property function()))); 8223 static assert( is(PropertyType!(overloads[0]) == long delegate() @property)); 8224 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8225 8226 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long delegate() @property)))); 8227 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8228 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8229 } 8230 8231 // void setterFirstDel(long function() @property); 8232 // long function() @property setterFirstDel(); 8233 { 8234 static assert( is(SymbolType!(S.staticSetterFirstDel) == 8235 ToFunctionType!(void function(long delegate() @property)))); 8236 static assert( is(PropertyType!(S.staticSetterFirstDel) == long delegate() @property)); 8237 static assert( is(typeof((S.staticSetterFirstDel)) == SymbolType!(S.staticSetterFirstDel))); 8238 8239 alias overloads = __traits(getOverloads, S, "staticSetterFirstDel"); 8240 static assert(overloads.length == 2); 8241 8242 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long delegate() @property)))); 8243 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8244 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8245 8246 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long delegate() @property function()))); 8247 static assert( is(PropertyType!(overloads[1]) == long delegate() @property)); 8248 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8249 } 8250 8251 // long function() @property staticPropGetterFirstDel() @property; 8252 // void staticPropGetterFirstDel(long function() @property) @property; 8253 { 8254 static assert( is(SymbolType!(S.staticPropGetterFirstDel) == 8255 ToFunctionType!(long delegate() @property function() @property))); 8256 static assert( is(PropertyType!(S.staticPropGetterFirstDel) == long delegate() @property)); 8257 static assert( is(typeof((S.staticPropGetterFirstDel)) == PropertyType!(S.staticPropGetterFirstDel))); 8258 8259 alias overloads = __traits(getOverloads, S, "staticPropGetterFirstDel"); 8260 static assert(overloads.length == 2); 8261 8262 static assert( is(SymbolType!(overloads[0]) == 8263 ToFunctionType!(long delegate() @property function() @property))); 8264 static assert( is(PropertyType!(overloads[0]) == long delegate() @property)); 8265 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8266 8267 static assert( is(SymbolType!(overloads[1]) == 8268 ToFunctionType!(void function(long delegate() @property) @property))); 8269 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8270 static assert(!__traits(compiles, typeof((overloads[1])))); 8271 } 8272 8273 // void propSetterFirstDel(long function() @property) @property; 8274 // long function() @property propSetterFirstDel() @property; 8275 { 8276 static assert( is(SymbolType!(S.staticPropSetterFirstDel) == 8277 ToFunctionType!(void function(long delegate() @property) @property))); 8278 static assert( is(PropertyType!(S.staticPropSetterFirstDel) == long delegate() @property)); 8279 static assert( is(typeof((S.staticPropSetterFirstDel)) == PropertyType!(S.staticPropSetterFirstDel))); 8280 8281 alias overloads = __traits(getOverloads, S, "staticPropSetterFirstDel"); 8282 static assert(overloads.length == 2); 8283 8284 static assert( is(SymbolType!(overloads[0]) == 8285 ToFunctionType!(void function(long delegate() @property) @property))); 8286 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8287 static assert(!__traits(compiles, typeof(overloads[0]))); 8288 8289 static assert( is(SymbolType!(overloads[1]) == 8290 ToFunctionType!(long delegate() @property function() @property))); 8291 static assert( is(PropertyType!(overloads[1]) == long delegate() @property)); 8292 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8293 } 8294 } 8295 { 8296 static interface I 8297 { 8298 void foo(); 8299 static void bar(); 8300 8301 int func1(); 8302 void func1(int); 8303 8304 void func2(int); 8305 int func2(); 8306 8307 @property void prop1(int); 8308 @property int prop1(); 8309 8310 @property int prop2(); 8311 @property void prop2(int); 8312 8313 static @property string staticProp(); 8314 static @property void staticProp(real); 8315 8316 @property void extraProp(string); 8317 8318 int defaultArg1(string str = "foo"); 8319 void defaultArg1(int, string str = "foo"); 8320 8321 void defaultArg2(int, string str = "foo"); 8322 int defaultArg2(string str = "foo"); 8323 8324 @property int defaultArgProp1(string str = "foo"); 8325 @property void defaultArgProp1(int, string str = "foo"); 8326 8327 @property void defaultArgProp2(int, string str = "foo"); 8328 @property int defaultArgProp2(string str = "foo"); 8329 8330 string defaultArgInDerived1(int); 8331 void defaultArgInDerived1(string, int); 8332 8333 void defaultArgInDerived2(string, int); 8334 string defaultArgInDerived2(int); 8335 8336 @property string defaultArgInDerivedProp1(int); 8337 @property void defaultArgInDerivedProp1(string, int); 8338 8339 @property void defaultArgInDerivedProp2(string, int); 8340 @property string defaultArgInDerivedProp2(int); 8341 } 8342 8343 { 8344 // void foo() 8345 static assert( is(SymbolType!(I.foo) == ToFunctionType!(void function()))); 8346 static assert(!__traits(compiles, PropertyType!(I.foo))); 8347 static assert( is(typeof(I.foo) == SymbolType!(I.foo))); 8348 8349 // static void bar() 8350 static assert( is(SymbolType!(I.bar) == ToFunctionType!(void function()))); 8351 static assert(!__traits(compiles, PropertyType!(I.bar))); 8352 static assert( is(typeof(I.bar) == SymbolType!(I.bar))); 8353 8354 // int func1(); 8355 // void func1(int); 8356 { 8357 static assert( is(SymbolType!(I.func1) == ToFunctionType!(int function()))); 8358 static assert( is(PropertyType!(I.func1) == int)); 8359 static assert( is(typeof(I.func1) == SymbolType!(I.func1))); 8360 8361 alias overloads = __traits(getOverloads, I, "func1"); 8362 static assert(overloads.length == 2); 8363 8364 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 8365 static assert( is(PropertyType!(overloads[0]) == int)); 8366 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8367 8368 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 8369 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8370 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8371 } 8372 8373 // void func2(int); 8374 // int func2(); 8375 { 8376 static assert( is(SymbolType!(I.func2) == ToFunctionType!(void function(int)))); 8377 static assert( is(PropertyType!(I.func2) == int)); 8378 static assert( is(typeof(I.func2) == SymbolType!(I.func2))); 8379 8380 alias overloads = __traits(getOverloads, I, "func2"); 8381 static assert(overloads.length == 2); 8382 8383 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 8384 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8385 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8386 8387 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 8388 static assert( is(PropertyType!(overloads[1]) == int)); 8389 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8390 } 8391 8392 // @property void prop1(int); 8393 // @property int prop1(); 8394 { 8395 static assert( is(SymbolType!(I.prop1) == ToFunctionType!(void function(int) @property))); 8396 static assert( is(PropertyType!(I.prop1) == int)); 8397 static assert( is(typeof(I.prop1) == PropertyType!(I.prop1))); 8398 8399 alias overloads = __traits(getOverloads, I, "prop1"); 8400 static assert(overloads.length == 2); 8401 8402 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 8403 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8404 static assert(!__traits(compiles, typeof(overloads[0]))); 8405 8406 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 8407 static assert( is(PropertyType!(overloads[1]) == int)); 8408 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8409 } 8410 8411 // @property int prop2(); 8412 // @property void prop2(int); 8413 { 8414 static assert( is(SymbolType!(I.prop2) == ToFunctionType!(int function() @property))); 8415 static assert( is(PropertyType!(I.prop2) == int)); 8416 static assert( is(typeof(I.prop2) == PropertyType!(I.prop2))); 8417 8418 alias overloads = __traits(getOverloads, I, "prop2"); 8419 static assert(overloads.length == 2); 8420 8421 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property))); 8422 static assert( is(PropertyType!(overloads[0]) == int)); 8423 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8424 8425 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 8426 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8427 static assert(!__traits(compiles, typeof(overloads[1]))); 8428 } 8429 8430 // static @property string staticProp(); 8431 // static @property void staticProp(real); 8432 { 8433 static assert( is(SymbolType!(I.staticProp) == ToFunctionType!(string function() @property))); 8434 static assert( is(PropertyType!(I.staticProp) == string)); 8435 static assert( is(typeof(I.staticProp) == PropertyType!(I.staticProp))); 8436 8437 alias overloads = __traits(getOverloads, I, "staticProp"); 8438 static assert(overloads.length == 2); 8439 8440 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 8441 static assert( is(PropertyType!(overloads[0]) == string)); 8442 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8443 8444 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 8445 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8446 static assert(!__traits(compiles, typeof(overloads[1]))); 8447 } 8448 8449 // @property void extraProp(string); 8450 { 8451 static assert( is(SymbolType!(I.extraProp) == ToFunctionType!(void function(string) @property))); 8452 static assert(!__traits(compiles, PropertyType!(I.extraProp))); 8453 static assert(!__traits(compiles, typeof(I.extraProp))); 8454 8455 alias overloads = __traits(getOverloads, I, "extraProp"); 8456 static assert(overloads.length == 1); 8457 8458 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property))); 8459 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8460 static assert(!__traits(compiles, typeof(overloads[0]))); 8461 } 8462 8463 // int defaultArg1(string str = "foo"); 8464 // void defaultArg1(int, string str = "foo"); 8465 { 8466 static assert( is(SymbolType!(I.defaultArg1) == ToFunctionType!(int function(string)))); 8467 static assert( is(PropertyType!(I.defaultArg1) == int)); 8468 static assert( is(typeof(I.defaultArg1) == SymbolType!(I.defaultArg1))); 8469 8470 alias overloads = __traits(getOverloads, I, "defaultArg1"); 8471 static assert(overloads.length == 2); 8472 8473 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string)))); 8474 static assert( is(PropertyType!(overloads[0]) == int)); 8475 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8476 8477 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string)))); 8478 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8479 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8480 } 8481 8482 // void defaultArg2(int, string str = "foo"); 8483 // int defaultArg2(string str = "foo"); 8484 { 8485 static assert( is(SymbolType!(I.defaultArg2) == ToFunctionType!(void function(int, string)))); 8486 static assert( is(PropertyType!(I.defaultArg2) == int)); 8487 static assert( is(typeof(I.defaultArg2) == SymbolType!(I.defaultArg2))); 8488 8489 alias overloads = __traits(getOverloads, I, "defaultArg2"); 8490 static assert(overloads.length == 2); 8491 8492 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 8493 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8494 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8495 8496 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 8497 static assert( is(PropertyType!(overloads[1]) == int)); 8498 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8499 } 8500 8501 // @property int defaultArgProp1(string str = "foo"); 8502 // @property void defaultArgProp1(int, string str = "foo"); 8503 { 8504 static assert( is(SymbolType!(I.defaultArgProp1) == ToFunctionType!(int function(string) @property))); 8505 static assert( is(PropertyType!(I.defaultArgProp1) == int)); 8506 static assert( is(typeof(I.defaultArgProp1) == PropertyType!(I.defaultArgProp1))); 8507 8508 alias overloads = __traits(getOverloads, I, "defaultArgProp1"); 8509 static assert(overloads.length == 2); 8510 8511 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 8512 static assert( is(PropertyType!(overloads[0]) == int)); 8513 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8514 8515 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 8516 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8517 static assert(!__traits(compiles, typeof(overloads[1]))); 8518 } 8519 8520 // @property void defaultArgProp2(int, string str = "foo"); 8521 // @property int defaultArgProp2(string str = "foo"); 8522 { 8523 static assert( is(SymbolType!(I.defaultArgProp2) == 8524 ToFunctionType!(void function(int, string) @property))); 8525 static assert( is(PropertyType!(I.defaultArgProp2) == int)); 8526 static assert( is(typeof(I.defaultArgProp2) == PropertyType!(I.defaultArgProp2))); 8527 8528 alias overloads = __traits(getOverloads, I, "defaultArgProp2"); 8529 static assert(overloads.length == 2); 8530 8531 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 8532 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8533 static assert(!__traits(compiles, typeof(overloads[0]))); 8534 8535 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 8536 static assert( is(PropertyType!(overloads[1]) == int)); 8537 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8538 } 8539 8540 // string defaultArgInDerived1(int); 8541 // void defaultArgInDerived1(string, int); 8542 { 8543 static assert( is(SymbolType!(I.defaultArgInDerived1) == ToFunctionType!(string function(int)))); 8544 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived1))); 8545 static assert( is(typeof(I.defaultArgInDerived1) == SymbolType!(I.defaultArgInDerived1))); 8546 8547 alias overloads = __traits(getOverloads, I, "defaultArgInDerived1"); 8548 static assert(overloads.length == 2); 8549 8550 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 8551 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8552 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8553 8554 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 8555 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8556 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8557 } 8558 8559 // void defaultArgInDerived2(string, int); 8560 // string defaultArgInDerived2(int); 8561 { 8562 static assert( is(SymbolType!(I.defaultArgInDerived2) == ToFunctionType!(void function(string, int)))); 8563 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived2))); 8564 static assert( is(typeof(I.defaultArgInDerived2) == SymbolType!(I.defaultArgInDerived2))); 8565 8566 alias overloads = __traits(getOverloads, I, "defaultArgInDerived2"); 8567 static assert(overloads.length == 2); 8568 8569 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 8570 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8571 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8572 8573 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 8574 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8575 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8576 } 8577 8578 // @property string defaultArgInDerivedProp1(int); 8579 // @property void defaultArgInDerivedProp1(string, int); 8580 { 8581 static assert( is(SymbolType!(I.defaultArgInDerivedProp1) == 8582 ToFunctionType!(string function(int) @property))); 8583 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp1))); 8584 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp1))); 8585 8586 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp1"); 8587 static assert(overloads.length == 2); 8588 8589 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 8590 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8591 static assert(!__traits(compiles, typeof(overloads[0]))); 8592 8593 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 8594 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8595 static assert(!__traits(compiles, typeof(overloads[0]))); 8596 } 8597 8598 // @property void defaultArgInDerivedProp2(string, int); 8599 // @property string defaultArgInDerivedProp2(int); 8600 { 8601 static assert( is(SymbolType!(I.defaultArgInDerivedProp2) == 8602 ToFunctionType!(void function(string, int) @property))); 8603 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp2))); 8604 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp2))); 8605 8606 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp2"); 8607 static assert(overloads.length == 2); 8608 8609 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property))); 8610 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8611 static assert(!__traits(compiles, typeof(overloads[0]))); 8612 8613 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property))); 8614 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8615 static assert(!__traits(compiles, typeof(overloads[1]))); 8616 } 8617 } 8618 8619 // For whatever reason, the virtual functions have to have bodies, or 8620 // the linker complains, even though the functions aren't actually 8621 // called anywhere, but having them implement the functions which are in 8622 // the interface at least gets rid of the attribute inference. 8623 static class C1 : I 8624 { 8625 shared int i; 8626 string s; 8627 8628 override void foo() {} 8629 8630 // This shadows the one in the interface, and it has a different 8631 // signature, so it makes sure that we're getting the right one. 8632 static int bar(); 8633 8634 final void baz(); 8635 8636 override int func1() { return 0; } 8637 override void func1(int) {} 8638 8639 override void func2(int) {} 8640 override int func2() { return 0; } 8641 8642 override @property void prop1(int) {} 8643 override @property int prop1() { return 0; } 8644 8645 override @property int prop2() { return 0; } 8646 override @property void prop2(int) {} 8647 8648 override @property void extraProp(string) {} 8649 @property bool extraProp() { return true; } 8650 8651 override int defaultArg1(string str = "foo") { return 42; } 8652 override void defaultArg1(int, string str = "foo") {} 8653 8654 // This tests the case where the derived type doesn't provide 8655 // default arguments even though the interface does. 8656 override void defaultArg2(int, string str) {} 8657 override int defaultArg2(string str) { return 42; } 8658 8659 override @property int defaultArgProp1(string str = "foo") { return 42; } 8660 override @property void defaultArgProp1(int, string str = "foo") {} 8661 8662 // This tests the case where the derived type doesn't provide 8663 // default arguments even though the interface does. 8664 override @property void defaultArgProp2(int, string str) {} 8665 override @property int defaultArgProp2(string str) { return 42; } 8666 8667 override string defaultArgInDerived1(int i = 0) { return ""; } 8668 override void defaultArgInDerived1(string, int i = 0) {} 8669 8670 override void defaultArgInDerived2(string, int i = 0) {} 8671 override string defaultArgInDerived2(int i = 0) { return ""; } 8672 8673 @property string defaultArgInDerivedProp1(int i = 0) { return ""; } 8674 @property void defaultArgInDerivedProp1(string, int i = 0) {} 8675 8676 @property void defaultArgInDerivedProp2(string, int i = 0) {} 8677 @property string defaultArgInDerivedProp2(int i = 0) { return ""; } 8678 } 8679 8680 { 8681 // shared int i; 8682 // string s; 8683 static assert( is(SymbolType!(C1.i) == shared int)); 8684 static assert( is(PropertyType!(C1.i) == shared int)); 8685 static assert( is(typeof(C1.i) == shared int)); 8686 8687 static assert( is(SymbolType!(C1.s) == string)); 8688 static assert( is(PropertyType!(C1.s) == string)); 8689 static assert( is(typeof(C1.s) == string)); 8690 8691 // override void foo() 8692 static assert( is(SymbolType!(C1.foo) == ToFunctionType!(void function()))); 8693 static assert(!__traits(compiles, PropertyType!(C1.foo))); 8694 static assert( is(typeof(C1.foo) == SymbolType!(C1.foo))); 8695 8696 // static int bar() 8697 static assert( is(SymbolType!(C1.bar) == ToFunctionType!(int function()))); 8698 static assert( is(PropertyType!(C1.bar) == int)); 8699 static assert( is(typeof(C1.bar) == SymbolType!(C1.bar))); 8700 8701 // void baz() 8702 static assert( is(SymbolType!(C1.baz) == ToFunctionType!(void function()))); 8703 static assert(!__traits(compiles, PropertyType!(C1.baz))); 8704 static assert( is(typeof(C1.baz) == SymbolType!(C1.baz))); 8705 8706 // override int func1(); 8707 // override void func1(int); 8708 { 8709 static assert( is(SymbolType!(C1.func1) == ToFunctionType!(int function()))); 8710 static assert( is(PropertyType!(C1.func1) == int)); 8711 static assert( is(typeof(C1.func1) == SymbolType!(C1.func1))); 8712 8713 alias overloads = __traits(getOverloads, C1, "func1"); 8714 static assert(overloads.length == 2); 8715 8716 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 8717 static assert( is(PropertyType!(overloads[0]) == int)); 8718 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8719 8720 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 8721 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8722 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8723 } 8724 8725 // override void func2(int); 8726 // override int func2(); 8727 { 8728 static assert( is(SymbolType!(C1.func2) == ToFunctionType!(void function(int)))); 8729 static assert( is(PropertyType!(C1.func2) == int)); 8730 static assert( is(typeof(C1.func2) == SymbolType!(C1.func2))); 8731 8732 alias overloads = __traits(getOverloads, C1, "func2"); 8733 static assert(overloads.length == 2); 8734 8735 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 8736 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8737 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8738 8739 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 8740 static assert( is(PropertyType!(overloads[1]) == int)); 8741 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8742 } 8743 8744 // override @property void prop1(int); 8745 // override @property int prop1(); 8746 { 8747 static assert( is(SymbolType!(C1.prop1) == ToFunctionType!(void function(int) @property))); 8748 static assert( is(PropertyType!(C1.prop1) == int)); 8749 static assert( is(typeof(C1.prop1) == PropertyType!(C1.prop1))); 8750 8751 alias overloads = __traits(getOverloads, C1, "prop1"); 8752 static assert(overloads.length == 2); 8753 8754 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 8755 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8756 static assert(!__traits(compiles, typeof(overloads[0]))); 8757 8758 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 8759 static assert( is(PropertyType!(overloads[1]) == int)); 8760 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8761 } 8762 8763 // override @property int prop2(); 8764 // override @property void prop2(int); 8765 { 8766 static assert( is(SymbolType!(C1.prop2) == ToFunctionType!(int function() @property))); 8767 static assert( is(PropertyType!(C1.prop2) == int)); 8768 static assert( is(typeof(C1.prop2) == PropertyType!(C1.prop2))); 8769 8770 alias overloads = __traits(getOverloads, C1, "prop2"); 8771 static assert(overloads.length == 2); 8772 8773 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property))); 8774 static assert( is(PropertyType!(overloads[0]) == int)); 8775 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8776 8777 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 8778 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8779 static assert(!__traits(compiles, typeof(overloads[1]))); 8780 } 8781 8782 // Actually on I, not C1. 8783 // static @property string staticProp(); 8784 // static @property void staticProp(real); 8785 { 8786 static assert( is(SymbolType!(C1.staticProp) == ToFunctionType!(string function() @property))); 8787 static assert( is(PropertyType!(C1.staticProp) == string)); 8788 static assert( is(typeof(C1.staticProp) == PropertyType!(C1.staticProp))); 8789 8790 alias overloads = __traits(getOverloads, C1, "staticProp"); 8791 static assert(overloads.length == 2); 8792 8793 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 8794 static assert( is(PropertyType!(overloads[0]) == string)); 8795 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8796 8797 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 8798 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8799 static assert(!__traits(compiles, typeof(overloads[1]))); 8800 } 8801 8802 // override @property void extraProp(string); 8803 // @property bool extraProp() { return true; } 8804 { 8805 static assert( is(SymbolType!(C1.extraProp) == ToFunctionType!(void function(string) @property))); 8806 static assert( is(PropertyType!(C1.extraProp) == bool)); 8807 static assert( is(typeof(C1.extraProp) == bool)); 8808 8809 alias overloads = __traits(getOverloads, C1, "extraProp"); 8810 static assert(overloads.length == 2); 8811 8812 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property))); 8813 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8814 static assert(!__traits(compiles, typeof(overloads[0]))); 8815 8816 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(bool function() @property))); 8817 static assert( is(PropertyType!(overloads[1]) == bool)); 8818 static assert( is(typeof(overloads[1]) == bool)); 8819 } 8820 8821 // override int defaultArg1(string str = "foo"); 8822 // override void defaultArg1(int, string str = "foo"); 8823 { 8824 static assert( is(SymbolType!(C1.defaultArg1) == ToFunctionType!(int function(string)))); 8825 static assert( is(PropertyType!(C1.defaultArg1) == int)); 8826 static assert( is(typeof(C1.defaultArg1) == SymbolType!(C1.defaultArg1))); 8827 8828 alias overloads = __traits(getOverloads, C1, "defaultArg1"); 8829 static assert(overloads.length == 2); 8830 8831 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string)))); 8832 static assert( is(PropertyType!(overloads[0]) == int)); 8833 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8834 8835 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string)))); 8836 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8837 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8838 } 8839 8840 // I provides default arguments, but C1 does not. 8841 // override void defaultArg2(int, string); 8842 // override int defaultArg2(string); 8843 { 8844 static assert( is(SymbolType!(C1.defaultArg2) == ToFunctionType!(void function(int, string)))); 8845 static assert(!__traits(compiles, PropertyType!(C1.defaultArg2))); 8846 static assert( is(typeof(C1.defaultArg2) == SymbolType!(C1.defaultArg2))); 8847 8848 alias overloads = __traits(getOverloads, C1, "defaultArg2"); 8849 static assert(overloads.length == 2); 8850 8851 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 8852 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8853 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8854 8855 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 8856 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8857 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8858 } 8859 8860 // override @property int defaultArgProp1(string str = "foo"); 8861 // override @property void defaultArgProp1(int, string str = "foo"); 8862 { 8863 static assert( is(SymbolType!(C1.defaultArgProp1) == ToFunctionType!(int function(string) @property))); 8864 static assert( is(PropertyType!(C1.defaultArgProp1) == int)); 8865 static assert( is(typeof(C1.defaultArgProp1) == PropertyType!(C1.defaultArgProp1))); 8866 8867 alias overloads = __traits(getOverloads, C1, "defaultArgProp1"); 8868 static assert(overloads.length == 2); 8869 8870 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 8871 static assert( is(PropertyType!(overloads[0]) == int)); 8872 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8873 8874 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 8875 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8876 static assert(!__traits(compiles, typeof(overloads[1]))); 8877 } 8878 8879 // I provides default arguments, but C1 does not. 8880 // override @property void defaultArgProp2(int, string str); 8881 // override @property int defaultArgProp2(string str); 8882 { 8883 static assert( is(SymbolType!(C1.defaultArgProp2) == 8884 ToFunctionType!(void function(int, string) @property))); 8885 static assert(!__traits(compiles, PropertyType!(C1.defaultArgProp2))); 8886 static assert(!__traits(compiles, typeof(C1.defaultArgProp2))); 8887 8888 alias overloads = __traits(getOverloads, C1, "defaultArgProp2"); 8889 static assert(overloads.length == 2); 8890 8891 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 8892 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8893 static assert(!__traits(compiles, typeof(overloads[0]))); 8894 8895 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 8896 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8897 static assert(!__traits(compiles, typeof(overloads[1]))); 8898 } 8899 8900 // I does not provide default arguments, but C1 does. 8901 // override string defaultArgInDerived1(int i = 0); 8902 // override void defaultArgInDerived1(string, int i = 0); 8903 { 8904 static assert( is(SymbolType!(C1.defaultArgInDerived1) == ToFunctionType!(string function(int)))); 8905 static assert( is(PropertyType!(C1.defaultArgInDerived1) == string)); 8906 static assert( is(typeof(C1.defaultArgInDerived1) == SymbolType!(C1.defaultArgInDerived1))); 8907 8908 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived1"); 8909 static assert(overloads.length == 2); 8910 8911 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 8912 static assert( is(PropertyType!(overloads[0]) == string)); 8913 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8914 8915 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 8916 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8917 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8918 } 8919 8920 // I does not provide default arguments, but C1 does. 8921 // override void defaultArgInDerived2(string, int i = 0); 8922 // override string defaultArgInDerived2(int i = 0); 8923 { 8924 static assert( is(SymbolType!(C1.defaultArgInDerived2) == ToFunctionType!(void function(string, int)))); 8925 static assert( is(PropertyType!(C1.defaultArgInDerived2) == string)); 8926 static assert( is(typeof(C1.defaultArgInDerived2) == SymbolType!(C1.defaultArgInDerived2))); 8927 8928 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived2"); 8929 static assert(overloads.length == 2); 8930 8931 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 8932 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8933 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8934 8935 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 8936 static assert( is(PropertyType!(overloads[1]) == string)); 8937 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8938 } 8939 8940 // I does not provide default arguments, but C1 does. 8941 // override @property string defaultArgInDerivedProp1(int i = 0); 8942 // override @property void defaultArgInDerivedProp1(string, int i = 0); 8943 { 8944 static assert( is(SymbolType!(C1.defaultArgInDerivedProp1) == 8945 ToFunctionType!(string function(int) @property))); 8946 static assert( is(PropertyType!(C1.defaultArgInDerivedProp1) == string)); 8947 static assert( is(typeof(C1.defaultArgInDerivedProp1) == string)); 8948 8949 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp1"); 8950 static assert(overloads.length == 2); 8951 8952 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 8953 static assert( is(PropertyType!(overloads[0]) == string)); 8954 static assert( is(typeof(overloads[0]) == string)); 8955 8956 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 8957 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8958 static assert(!__traits(compiles, typeof(overloads[1]))); 8959 } 8960 8961 // I does not provide default arguments, but C1 does. 8962 // override @property void defaultArgInDerivedProp2(string, int i = 0); 8963 // override @property string defaultArgInDerivedProp2(int i = 0); 8964 { 8965 static assert( is(SymbolType!(C1.defaultArgInDerivedProp2) == 8966 ToFunctionType!(void function(string, int) @property))); 8967 static assert( is(PropertyType!(C1.defaultArgInDerivedProp2) == string)); 8968 static assert( is(typeof(C1.defaultArgInDerivedProp2) == string)); 8969 8970 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp2"); 8971 static assert(overloads.length == 2); 8972 8973 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property))); 8974 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8975 static assert(!__traits(compiles, typeof(overloads[0]))); 8976 8977 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property))); 8978 static assert( is(PropertyType!(overloads[1]) == string)); 8979 static assert( is(typeof(overloads[1]) == string)); 8980 } 8981 } 8982 8983 // Changes the function order (and has different extraProps). 8984 // It also provides default arguments when C1 does not. 8985 static class C2 : I 8986 { 8987 real r; 8988 bool b; 8989 int* ptr; 8990 8991 @property long extraProp() { return 42; } 8992 override @property void extraProp(string) {} 8993 @property void extraProp(int) {} 8994 8995 override void foo() {} 8996 8997 @property string defaultArgInDerivedProp2(int i = 0) { return "dlang"; } 8998 @property void defaultArgInDerivedProp2(string, int i = 0) {} 8999 9000 string defaultArgInDerived2(int i = 0) { return "dlang"; } 9001 void defaultArgInDerived2(string, int i = 0) {} 9002 9003 void defaultArgInDerived1(string, int i = 0) {} 9004 string defaultArgInDerived1(int i = 0) { return "dlang"; } 9005 9006 @property void defaultArgInDerivedProp1(string, int i = 0) {} 9007 @property string defaultArgInDerivedProp1(int i = 0) { return "dlang"; } 9008 9009 override void defaultArg2(int, string str = "bar") {} 9010 override int defaultArg2(string str = "bar") { return 0; } 9011 9012 override @property int defaultArgProp2(string str = "bar") { return 0; } 9013 override @property void defaultArgProp2(int, string str = "bar") {} 9014 9015 override @property void defaultArgProp1(int, string str = "bar") {} 9016 override @property int defaultArgProp1(string str = "bar") { return 0; } 9017 9018 override void defaultArg1(int, string str = "bar") {} 9019 override int defaultArg1(string str = "bar") { return 0; } 9020 9021 override @property void prop2(int) {} 9022 override @property int prop2() { return 0; } 9023 9024 override @property void prop1(int) {} 9025 override @property int prop1() { return 0; } 9026 9027 override void func2(int) {} 9028 override int func2() { return 0; } 9029 9030 override int func1() { return 0; } 9031 override void func1(int) {} 9032 } 9033 9034 { 9035 // real r; 9036 // bool b; 9037 // int* ptr; 9038 9039 static assert( is(SymbolType!(C2.r) == real)); 9040 static assert( is(PropertyType!(C2.r) == real)); 9041 static assert( is(typeof(C2.r) == real)); 9042 9043 static assert( is(SymbolType!(C2.b) == bool)); 9044 static assert( is(PropertyType!(C2.b) == bool)); 9045 static assert( is(typeof(C2.b) == bool)); 9046 9047 static assert( is(SymbolType!(C2.ptr) == int*)); 9048 static assert( is(PropertyType!(C2.ptr) == int*)); 9049 static assert( is(typeof(C2.ptr) == int*)); 9050 9051 // Actually on I, not C2. 9052 // static @property string staticProp(); 9053 // static @property void staticProp(real); 9054 { 9055 static assert( is(SymbolType!(C2.staticProp) == ToFunctionType!(string function() @property))); 9056 static assert( is(PropertyType!(C2.staticProp) == string)); 9057 static assert( is(typeof(C2.staticProp) == PropertyType!(C2.staticProp))); 9058 9059 alias overloads = __traits(getOverloads, C2, "staticProp"); 9060 static assert(overloads.length == 2); 9061 9062 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 9063 static assert( is(PropertyType!(overloads[0]) == string)); 9064 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 9065 9066 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 9067 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9068 static assert(!__traits(compiles, typeof(overloads[1]))); 9069 } 9070 9071 // @property long extraProp() { return 42; } 9072 // override @property void extraProp(string) {} 9073 // @property void extraProp(int) {} 9074 { 9075 static assert( is(SymbolType!(C2.extraProp) == ToFunctionType!(long function() @property))); 9076 static assert( is(PropertyType!(C2.extraProp) == long)); 9077 static assert( is(typeof(C2.extraProp) == long)); 9078 9079 alias overloads = __traits(getOverloads, C2, "extraProp"); 9080 static assert(overloads.length == 3); 9081 9082 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 9083 static assert( is(PropertyType!(overloads[0]) == long)); 9084 static assert( is(typeof(overloads[0]) == long)); 9085 9086 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property))); 9087 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9088 static assert(!__traits(compiles, typeof(overloads[1]))); 9089 9090 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property))); 9091 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 9092 static assert(!__traits(compiles, typeof(overloads[2]))); 9093 } 9094 9095 // override void foo() 9096 static assert( is(SymbolType!(C2.foo) == ToFunctionType!(void function()))); 9097 static assert(!__traits(compiles, PropertyType!(C2.foo))); 9098 static assert( is(typeof(C2.foo) == SymbolType!(C2.foo))); 9099 9100 // I does not provide default arguments, but C2 does. 9101 // @property string defaultArgInDerivedProp2(int i = 0); 9102 // @property void defaultArgInDerivedProp2(string, int i = 0); 9103 { 9104 static assert( is(SymbolType!(C2.defaultArgInDerivedProp2) == 9105 ToFunctionType!(string function(int) @property))); 9106 static assert( is(PropertyType!(C2.defaultArgInDerivedProp2) == string)); 9107 static assert( is(typeof(C2.defaultArgInDerivedProp2) == string)); 9108 9109 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp2"); 9110 static assert(overloads.length == 2); 9111 9112 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 9113 static assert( is(PropertyType!(overloads[0]) == string)); 9114 static assert( is(typeof(overloads[0]) == string)); 9115 9116 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 9117 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9118 static assert(!__traits(compiles, typeof(overloads[1]))); 9119 } 9120 9121 // I does not provide default arguments, but C2 does. 9122 // string defaultArgInDerived2(int i = 0); 9123 // void defaultArgInDerived2(string, int i = 0); 9124 { 9125 static assert( is(SymbolType!(C2.defaultArgInDerived2) == ToFunctionType!(string function(int)))); 9126 static assert( is(PropertyType!(C2.defaultArgInDerived2) == string)); 9127 static assert( is(typeof(C2.defaultArgInDerived2) == SymbolType!(C2.defaultArgInDerived2))); 9128 9129 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived2"); 9130 static assert(overloads.length == 2); 9131 9132 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 9133 static assert( is(PropertyType!(overloads[0]) == string)); 9134 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9135 9136 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 9137 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9138 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9139 } 9140 9141 // I does not provide default arguments, but C2 does. 9142 // void defaultArgInDerived1(string, int i = 0); 9143 // string defaultArgInDerived1(int i = 0); 9144 { 9145 static assert( is(SymbolType!(C2.defaultArgInDerived1) == ToFunctionType!(void function(string, int)))); 9146 static assert( is(PropertyType!(C2.defaultArgInDerived1) == string)); 9147 static assert( is(typeof(C2.defaultArgInDerived1) == SymbolType!(C2.defaultArgInDerived1))); 9148 9149 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived1"); 9150 static assert(overloads.length == 2); 9151 9152 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 9153 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9154 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9155 9156 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 9157 static assert( is(PropertyType!(overloads[1]) == string)); 9158 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9159 } 9160 9161 // I does not provide default arguments, but C2 does. 9162 // @property void defaultArgInDerivedProp1(string, int i = 0); 9163 // @property string defaultArgInDerivedProp1(int i = 0); 9164 { 9165 static assert( is(SymbolType!(C2.defaultArgInDerivedProp1) == 9166 ToFunctionType!(void function(string, int) @property))); 9167 static assert( is(PropertyType!(C2.defaultArgInDerivedProp1) == string)); 9168 static assert( is(typeof(C2.defaultArgInDerivedProp1) == string)); 9169 9170 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp1"); 9171 static assert(overloads.length == 2); 9172 9173 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property))); 9174 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9175 static assert(!__traits(compiles, typeof(overloads[0]))); 9176 9177 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property))); 9178 static assert( is(PropertyType!(overloads[1]) == string)); 9179 static assert( is(typeof(overloads[1]) == string)); 9180 } 9181 9182 // override void defaultArg2(int, string str = "bar"); 9183 // override int defaultArg2(string str = "bar"); 9184 { 9185 static assert( is(SymbolType!(C2.defaultArg2) == ToFunctionType!(void function(int, string)))); 9186 static assert( is(PropertyType!(C2.defaultArg2) == int)); 9187 static assert( is(typeof(C2.defaultArg2) == SymbolType!(C2.defaultArg2))); 9188 9189 alias overloads = __traits(getOverloads, C2, "defaultArg2"); 9190 static assert(overloads.length == 2); 9191 9192 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 9193 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9194 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9195 9196 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 9197 static assert( is(PropertyType!(overloads[1]) == int)); 9198 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9199 } 9200 9201 // override @property int defaultArgProp2(string str = "bar"); 9202 // override @property void defaultArgProp2(int, string str = "bar"); 9203 { 9204 static assert( is(SymbolType!(C2.defaultArgProp2) == 9205 ToFunctionType!(int function(string) @property))); 9206 static assert( is(PropertyType!(C2.defaultArgProp2) == int)); 9207 static assert( is(typeof(C2.defaultArgProp2) == PropertyType!(C2.defaultArgProp2))); 9208 9209 alias overloads = __traits(getOverloads, C2, "defaultArgProp2"); 9210 static assert(overloads.length == 2); 9211 9212 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 9213 static assert( is(PropertyType!(overloads[0]) == int)); 9214 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 9215 9216 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 9217 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9218 static assert(!__traits(compiles, typeof(overloads[1]))); 9219 } 9220 9221 // override @property void defaultArgProp1(int, string str = "bar"); 9222 // override @property int defaultArgProp1(string str = "bar"); 9223 { 9224 9225 static assert( is(SymbolType!(C2.defaultArgProp1) == 9226 ToFunctionType!(void function(int, string) @property))); 9227 static assert( is(PropertyType!(C2.defaultArgProp1) == int)); 9228 static assert( is(typeof(C2.defaultArgProp1) == PropertyType!(C2.defaultArgProp1))); 9229 9230 alias overloads = __traits(getOverloads, C2, "defaultArgProp1"); 9231 static assert(overloads.length == 2); 9232 9233 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 9234 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9235 static assert(!__traits(compiles, typeof(overloads[0]))); 9236 9237 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 9238 static assert( is(PropertyType!(overloads[1]) == int)); 9239 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9240 } 9241 9242 // override void defaultArg1(int, string str = "bar"); 9243 // override int defaultArg1(string str = "bar"); 9244 { 9245 static assert( is(SymbolType!(C2.defaultArg1) == ToFunctionType!(void function(int, string)))); 9246 static assert( is(PropertyType!(C2.defaultArg1) == int)); 9247 static assert( is(typeof(C2.defaultArg1) == SymbolType!(C2.defaultArg1))); 9248 9249 alias overloads = __traits(getOverloads, C2, "defaultArg1"); 9250 static assert(overloads.length == 2); 9251 9252 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 9253 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9254 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9255 9256 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 9257 static assert( is(PropertyType!(overloads[1]) == int)); 9258 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9259 } 9260 9261 // override @property void prop2(int); 9262 // override @property int prop2(); 9263 { 9264 static assert( is(SymbolType!(C2.prop2) == ToFunctionType!(void function(int) @property))); 9265 static assert( is(PropertyType!(C2.prop2) == int)); 9266 static assert( is(typeof(C2.prop2) == PropertyType!(C2.prop2))); 9267 9268 alias overloads = __traits(getOverloads, C2, "prop2"); 9269 static assert(overloads.length == 2); 9270 9271 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9272 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9273 static assert(!__traits(compiles, typeof(overloads[0]))); 9274 9275 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9276 static assert( is(PropertyType!(overloads[1]) == int)); 9277 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9278 } 9279 9280 // override @property void prop1(int); 9281 // override @property int prop1(); 9282 { 9283 static assert( is(SymbolType!(C2.prop1) == ToFunctionType!(void function(int) @property))); 9284 static assert( is(PropertyType!(C2.prop1) == int)); 9285 static assert( is(typeof(C2.prop1) == PropertyType!(C2.prop1))); 9286 9287 alias overloads = __traits(getOverloads, C2, "prop1"); 9288 static assert(overloads.length == 2); 9289 9290 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9291 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9292 static assert(!__traits(compiles, typeof(overloads[0]))); 9293 9294 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9295 static assert( is(PropertyType!(overloads[1]) == int)); 9296 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9297 } 9298 9299 // override void func2(int); 9300 // override int func2(); 9301 { 9302 static assert( is(SymbolType!(C2.func2) == ToFunctionType!(void function(int)))); 9303 static assert( is(PropertyType!(C2.func2) == int)); 9304 static assert( is(typeof(C2.func2) == SymbolType!(C2.func2))); 9305 9306 alias overloads = __traits(getOverloads, C2, "func2"); 9307 static assert(overloads.length == 2); 9308 9309 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 9310 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9311 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9312 9313 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 9314 static assert( is(PropertyType!(overloads[1]) == int)); 9315 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9316 } 9317 9318 // override int func1(); 9319 // override void func1(int); 9320 { 9321 static assert( is(SymbolType!(C2.func1) == ToFunctionType!(int function()))); 9322 static assert( is(PropertyType!(C2.func1) == int)); 9323 static assert( is(typeof(C2.func1) == SymbolType!(C2.func1))); 9324 9325 alias overloads = __traits(getOverloads, C2, "func1"); 9326 static assert(overloads.length == 2); 9327 9328 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 9329 static assert( is(PropertyType!(overloads[0]) == int)); 9330 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9331 9332 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 9333 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9334 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9335 } 9336 } 9337 9338 static class C3 : C2 9339 { 9340 const(short)* ptr; 9341 } 9342 9343 { 9344 // real r; (from C2) 9345 // bool b; (from C2) 9346 // const(short)* ptr; (shadows C2.ptr) 9347 static assert( is(SymbolType!(C3.r) == real)); 9348 static assert( is(PropertyType!(C3.r) == real)); 9349 static assert( is(typeof(C3.r) == real)); 9350 9351 static assert( is(SymbolType!(C3.b) == bool)); 9352 static assert( is(PropertyType!(C3.b) == bool)); 9353 static assert( is(typeof(C3.b) == bool)); 9354 9355 static assert( is(SymbolType!(C3.ptr) == const(short)*)); 9356 static assert( is(PropertyType!(C3.ptr) == const(short)*)); 9357 static assert( is(typeof(C3.ptr) == const(short)*)); 9358 9359 // Actually on I, not C3. 9360 // static @property string staticProp(); 9361 // static @property void staticProp(real); 9362 { 9363 static assert( is(SymbolType!(C3.staticProp) == ToFunctionType!(string function() @property))); 9364 static assert( is(PropertyType!(C3.staticProp) == string)); 9365 static assert( is(typeof(C3.staticProp) == PropertyType!(C3.staticProp))); 9366 9367 alias overloads = __traits(getOverloads, C3, "staticProp"); 9368 static assert(overloads.length == 2); 9369 9370 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 9371 static assert( is(PropertyType!(overloads[0]) == string)); 9372 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 9373 9374 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 9375 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9376 static assert(!__traits(compiles, typeof(overloads[1]))); 9377 } 9378 9379 // @property long extraProp() { return 42; } 9380 // override @property void extraProp(string) {} 9381 // @property void extraProp(int) {} 9382 { 9383 static assert( is(SymbolType!(C3.extraProp) == ToFunctionType!(long function() @property))); 9384 static assert( is(PropertyType!(C3.extraProp) == long)); 9385 static assert( is(typeof(C3.extraProp) == long)); 9386 9387 alias overloads = __traits(getOverloads, C3, "extraProp"); 9388 static assert(overloads.length == 3); 9389 9390 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 9391 static assert( is(PropertyType!(overloads[0]) == long)); 9392 static assert( is(typeof(overloads[0]) == long)); 9393 9394 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property))); 9395 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9396 static assert(!__traits(compiles, typeof(overloads[1]))); 9397 9398 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property))); 9399 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 9400 static assert(!__traits(compiles, typeof(overloads[2]))); 9401 } 9402 9403 // override void foo() 9404 static assert( is(SymbolType!(C3.foo) == ToFunctionType!(void function()))); 9405 static assert(!__traits(compiles, PropertyType!(C3.foo))); 9406 static assert( is(typeof(C3.foo) == SymbolType!(C3.foo))); 9407 9408 // I does not provide default arguments, but C2 does. 9409 // @property string defaultArgInDerivedProp2(int i = 0); 9410 // @property void defaultArgInDerivedProp2(string, int i = 0); 9411 { 9412 static assert( is(SymbolType!(C3.defaultArgInDerivedProp2) == 9413 ToFunctionType!(string function(int) @property))); 9414 static assert( is(PropertyType!(C3.defaultArgInDerivedProp2) == string)); 9415 static assert( is(typeof(C3.defaultArgInDerivedProp2) == string)); 9416 9417 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp2"); 9418 static assert(overloads.length == 2); 9419 9420 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 9421 static assert( is(PropertyType!(overloads[0]) == string)); 9422 static assert( is(typeof(overloads[0]) == string)); 9423 9424 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 9425 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9426 static assert(!__traits(compiles, typeof(overloads[1]))); 9427 } 9428 9429 // I does not provide default arguments, but C2 does. 9430 // string defaultArgInDerived2(int i = 0); 9431 // void defaultArgInDerived2(string, int i = 0); 9432 { 9433 static assert( is(SymbolType!(C3.defaultArgInDerived2) == ToFunctionType!(string function(int)))); 9434 static assert( is(PropertyType!(C3.defaultArgInDerived2) == string)); 9435 static assert( is(typeof(C3.defaultArgInDerived2) == SymbolType!(C3.defaultArgInDerived2))); 9436 9437 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived2"); 9438 static assert(overloads.length == 2); 9439 9440 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 9441 static assert( is(PropertyType!(overloads[0]) == string)); 9442 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9443 9444 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 9445 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9446 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9447 } 9448 9449 // I does not provide default arguments, but C2 does. 9450 // void defaultArgInDerived1(string, int i = 0); 9451 // string defaultArgInDerived1(int i = 0); 9452 { 9453 static assert( is(SymbolType!(C3.defaultArgInDerived1) == ToFunctionType!(void function(string, int)))); 9454 static assert( is(PropertyType!(C3.defaultArgInDerived1) == string)); 9455 static assert( is(typeof(C3.defaultArgInDerived1) == SymbolType!(C3.defaultArgInDerived1))); 9456 9457 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived1"); 9458 static assert(overloads.length == 2); 9459 9460 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 9461 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9462 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9463 9464 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 9465 static assert( is(PropertyType!(overloads[1]) == string)); 9466 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9467 } 9468 9469 // I does not provide default arguments, but C2 does. 9470 // @property void defaultArgInDerivedProp1(string, int i = 0); 9471 // @property string defaultArgInDerivedProp1(int i = 0); 9472 { 9473 static assert( is(SymbolType!(C3.defaultArgInDerivedProp1) == 9474 ToFunctionType!(void function(string, int) @property))); 9475 static assert( is(PropertyType!(C3.defaultArgInDerivedProp1) == string)); 9476 static assert( is(typeof(C3.defaultArgInDerivedProp1) == string)); 9477 9478 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp1"); 9479 static assert(overloads.length == 2); 9480 9481 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property))); 9482 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9483 static assert(!__traits(compiles, typeof(overloads[0]))); 9484 9485 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property))); 9486 static assert( is(PropertyType!(overloads[1]) == string)); 9487 static assert( is(typeof(overloads[1]) == string)); 9488 } 9489 9490 // override void defaultArg2(int, string str = "bar"); 9491 // override int defaultArg2(string str = "bar"); 9492 { 9493 static assert( is(SymbolType!(C3.defaultArg2) == ToFunctionType!(void function(int, string)))); 9494 static assert( is(PropertyType!(C3.defaultArg2) == int)); 9495 static assert( is(typeof(C3.defaultArg2) == SymbolType!(C3.defaultArg2))); 9496 9497 alias overloads = __traits(getOverloads, C3, "defaultArg2"); 9498 static assert(overloads.length == 2); 9499 9500 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 9501 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9502 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9503 9504 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 9505 static assert( is(PropertyType!(overloads[1]) == int)); 9506 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9507 } 9508 9509 // override @property int defaultArgProp2(string str = "bar"); 9510 // override @property void defaultArgProp2(int, string str = "bar"); 9511 { 9512 static assert( is(SymbolType!(C3.defaultArgProp2) == 9513 ToFunctionType!(int function(string) @property))); 9514 static assert( is(PropertyType!(C3.defaultArgProp2) == int)); 9515 static assert( is(typeof(C3.defaultArgProp2) == PropertyType!(C3.defaultArgProp2))); 9516 9517 alias overloads = __traits(getOverloads, C3, "defaultArgProp2"); 9518 static assert(overloads.length == 2); 9519 9520 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 9521 static assert( is(PropertyType!(overloads[0]) == int)); 9522 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 9523 9524 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 9525 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9526 static assert(!__traits(compiles, typeof(overloads[1]))); 9527 } 9528 9529 // override @property void defaultArgProp1(int, string str = "bar"); 9530 // override @property int defaultArgProp1(string str = "bar"); 9531 { 9532 9533 static assert( is(SymbolType!(C3.defaultArgProp1) == 9534 ToFunctionType!(void function(int, string) @property))); 9535 static assert( is(PropertyType!(C3.defaultArgProp1) == int)); 9536 static assert( is(typeof(C3.defaultArgProp1) == PropertyType!(C3.defaultArgProp1))); 9537 9538 alias overloads = __traits(getOverloads, C3, "defaultArgProp1"); 9539 static assert(overloads.length == 2); 9540 9541 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 9542 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9543 static assert(!__traits(compiles, typeof(overloads[0]))); 9544 9545 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 9546 static assert( is(PropertyType!(overloads[1]) == int)); 9547 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9548 } 9549 9550 // override void defaultArg1(int, string str = "bar"); 9551 // override int defaultArg1(string str = "bar"); 9552 { 9553 static assert( is(SymbolType!(C3.defaultArg1) == ToFunctionType!(void function(int, string)))); 9554 static assert( is(PropertyType!(C3.defaultArg1) == int)); 9555 static assert( is(typeof(C3.defaultArg1) == SymbolType!(C3.defaultArg1))); 9556 9557 alias overloads = __traits(getOverloads, C3, "defaultArg1"); 9558 static assert(overloads.length == 2); 9559 9560 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 9561 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9562 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9563 9564 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 9565 static assert( is(PropertyType!(overloads[1]) == int)); 9566 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9567 } 9568 9569 // override @property void prop2(int); 9570 // override @property int prop2(); 9571 { 9572 static assert( is(SymbolType!(C3.prop2) == ToFunctionType!(void function(int) @property))); 9573 static assert( is(PropertyType!(C3.prop2) == int)); 9574 static assert( is(typeof(C3.prop2) == PropertyType!(C3.prop2))); 9575 9576 alias overloads = __traits(getOverloads, C3, "prop2"); 9577 static assert(overloads.length == 2); 9578 9579 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9580 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9581 static assert(!__traits(compiles, typeof(overloads[0]))); 9582 9583 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9584 static assert( is(PropertyType!(overloads[1]) == int)); 9585 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9586 } 9587 9588 // override @property void prop1(int); 9589 // override @property int prop1(); 9590 { 9591 static assert( is(SymbolType!(C3.prop1) == ToFunctionType!(void function(int) @property))); 9592 static assert( is(PropertyType!(C3.prop1) == int)); 9593 static assert( is(typeof(C3.prop1) == PropertyType!(C3.prop1))); 9594 9595 alias overloads = __traits(getOverloads, C3, "prop1"); 9596 static assert(overloads.length == 2); 9597 9598 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9599 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9600 static assert(!__traits(compiles, typeof(overloads[0]))); 9601 9602 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9603 static assert( is(PropertyType!(overloads[1]) == int)); 9604 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9605 } 9606 9607 // override void func2(int); 9608 // override int func2(); 9609 { 9610 static assert( is(SymbolType!(C3.func2) == ToFunctionType!(void function(int)))); 9611 static assert( is(PropertyType!(C3.func2) == int)); 9612 static assert( is(typeof(C3.func2) == SymbolType!(C3.func2))); 9613 9614 alias overloads = __traits(getOverloads, C3, "func2"); 9615 static assert(overloads.length == 2); 9616 9617 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 9618 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9619 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9620 9621 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 9622 static assert( is(PropertyType!(overloads[1]) == int)); 9623 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9624 } 9625 9626 // override int func1(); 9627 // override void func1(int); 9628 { 9629 static assert( is(SymbolType!(C3.func1) == ToFunctionType!(int function()))); 9630 static assert( is(PropertyType!(C3.func1) == int)); 9631 static assert( is(typeof(C3.func1) == SymbolType!(C3.func1))); 9632 9633 alias overloads = __traits(getOverloads, C3, "func1"); 9634 static assert(overloads.length == 2); 9635 9636 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 9637 static assert( is(PropertyType!(overloads[0]) == int)); 9638 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9639 9640 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 9641 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9642 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9643 } 9644 } 9645 } 9646 } 9647 9648 // This is probably overkill, since it's arguably testing the compiler more 9649 // than it's testing SymbolType or ToFunctionType, but with various tests 9650 // either using inference for all attributes or not providing a body to avoid 9651 // it entirely, it seemed prudent to add some tests where the attributes being 9652 // inferred were better controlled, and it does help ensure that SymbolType 9653 // and ToFunctionType behave as expected in each case. 9654 @safe unittest 9655 { 9656 static int var; 9657 9658 // Since these are actually called below (even if those functions aren't 9659 // called) we can't play the trick of not providing a body to set all of 9660 // the attributes, because we get linker errors when the functions below 9661 // call these functions. 9662 static void useGC() @safe pure nothrow { new int; } 9663 static void throws() @safe pure @nogc { Exception e; throw e; } 9664 static void impure() @safe nothrow @nogc { ++var; } 9665 static void unsafe() @system pure nothrow @nogc { int i; int* ptr = &i; } 9666 9667 { 9668 static void func() { useGC(); } 9669 static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure nothrow))); 9670 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure nothrow))); 9671 } 9672 { 9673 static void func() { throws(); } 9674 static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure @nogc))); 9675 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure @nogc))); 9676 } 9677 { 9678 static void func() { impure(); } 9679 static assert( is(typeof(func) == ToFunctionType!(void function() @safe nothrow @nogc))); 9680 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe nothrow @nogc))); 9681 } 9682 { 9683 static void func() { unsafe(); } 9684 static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow @nogc))); 9685 9686 // Doubling the test shouldn't be necessary, but since the order of the 9687 // attributes isn't supposed to matter, it seemed prudent to have at 9688 // least one test that used a different order. 9689 static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow @nogc))); 9690 static assert( is(SymbolType!func == ToFunctionType!(void function() @nogc nothrow pure @system))); 9691 } 9692 { 9693 static void func() { useGC(); throws(); } 9694 static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure))); 9695 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure))); 9696 } 9697 { 9698 static void func() { throws(); impure(); } 9699 static assert( is(typeof(func) == ToFunctionType!(void function() @safe @nogc))); 9700 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe @nogc))); 9701 } 9702 { 9703 static void func() { impure(); unsafe(); } 9704 static assert( is(typeof(func) == ToFunctionType!(void function() @system nothrow @nogc))); 9705 static assert( is(SymbolType!func == ToFunctionType!(void function() @system nothrow @nogc))); 9706 } 9707 { 9708 static void func() { useGC(); unsafe(); } 9709 static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow))); 9710 static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow))); 9711 } 9712 { 9713 static void func() { useGC(); throws(); impure(); unsafe(); } 9714 static assert( is(typeof(func) == ToFunctionType!(void function() @system))); 9715 static assert( is(SymbolType!func == ToFunctionType!(void function() @system))); 9716 } 9717 { 9718 static void func() @trusted { useGC(); throws(); impure(); unsafe(); } 9719 static assert( is(typeof(func) == ToFunctionType!(void function() @trusted))); 9720 static assert( is(SymbolType!func == ToFunctionType!(void function() @trusted))); 9721 } 9722 } 9723 9724 /++ 9725 Removes the outer layer of $(D const), $(D inout), or $(D immutable) 9726 from type $(D T). 9727 9728 If none of those qualifiers have been applied to the outer layer of 9729 type $(D T), then the result is $(D T). 9730 9731 For the built-in scalar types (that is $(D bool), the character types, and 9732 the numeric types), they only have one layer, so $(D const U) simply becomes 9733 $(D U). 9734 9735 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 9736 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 9737 goes from being fully $(D const) to being a mutable pointer to $(D const), 9738 and a dynamic array goes from being fully $(D const) to being a mutable 9739 dynamic array of $(D const) elements. And if there are multiple layers of 9740 pointers or arrays, it's just that outer layer which is affected - e.g. 9741 $(D const(U**)) would become $(D const(U*)*). 9742 9743 For user-defined types, the effect is that $(D const U) becomes $(D U), and 9744 how that affects member variables depends on the type of the member 9745 variable. If a member variable is explicitly marked with any mutability 9746 qualifiers, then it will continue to have those qualifiers even after 9747 Unconst has stripped all mutability qualifiers from the containing type. 9748 However, if a mutability qualifier was on the member variable only because 9749 the containing type had that qualifier, then when Unconst removes the 9750 qualifier from the containing type, it is removed from the member variable 9751 as well. 9752 9753 Also, Unconst has no effect on what a templated type is instantiated 9754 with, so if a templated type is instantiated with a template argument which 9755 has a mutability qualifier, the template instantiation will not change. 9756 +/ 9757 version (StdDdoc) template Unconst(T) 9758 { 9759 import core.internal.traits : CoreUnconst = Unconst; 9760 alias Unconst = CoreUnconst!T; 9761 } 9762 else 9763 { 9764 import core.internal.traits : CoreUnconst = Unconst; 9765 alias Unconst = CoreUnconst; 9766 } 9767 9768 /// 9769 @safe unittest 9770 { 9771 static assert(is(Unconst!( int) == int)); 9772 static assert(is(Unconst!( const int) == int)); 9773 static assert(is(Unconst!( inout int) == int)); 9774 static assert(is(Unconst!( inout const int) == int)); 9775 static assert(is(Unconst!(shared int) == shared int)); 9776 static assert(is(Unconst!(shared const int) == shared int)); 9777 static assert(is(Unconst!(shared inout int) == shared int)); 9778 static assert(is(Unconst!(shared inout const int) == shared int)); 9779 static assert(is(Unconst!( immutable int) == int)); 9780 9781 // Only the outer layer of immutable is removed. 9782 // immutable(int[]) -> immutable(int)[] 9783 alias ImmIntArr = immutable(int[]); 9784 static assert(is(Unconst!ImmIntArr == immutable(int)[])); 9785 9786 // Only the outer layer of const is removed. 9787 // immutable(int*) -> immutable(int)* 9788 alias ConstIntPtr = const(int*); 9789 static assert(is(Unconst!ConstIntPtr == const(int)*)); 9790 9791 // const(int)* -> const(int)* 9792 alias PtrToConstInt = const(int)*; 9793 static assert(is(Unconst!PtrToConstInt == const(int)*)); 9794 9795 static struct S 9796 { 9797 int* ptr; 9798 const int* cPtr; 9799 shared int* sPtr; 9800 } 9801 9802 const S s; 9803 static assert(is(typeof(s) == const S)); 9804 static assert(is(typeof(typeof(s).ptr) == const int*)); 9805 static assert(is(typeof(typeof(s).cPtr) == const int*)); 9806 static assert(is(typeof(typeof(s).sPtr) == const shared int*)); 9807 9808 // For user-defined types, all mutability qualifiers that are applied to 9809 // member variables only because the containing type has them are removed, 9810 // but the ones that are directly on those member variables remain. 9811 9812 // const S -> S 9813 static assert(is(Unconst!(typeof(s)) == S)); 9814 static assert(is(typeof(Unconst!(typeof(s)).ptr) == int*)); 9815 static assert(is(typeof(Unconst!(typeof(s)).cPtr) == const int*)); 9816 static assert(is(typeof(Unconst!(typeof(s)).sPtr) == shared int*)); 9817 9818 static struct Foo(T) 9819 { 9820 T* ptr; 9821 } 9822 9823 // The qualifier on the type is removed, but the qualifier on the template 9824 // argument is not. 9825 static assert(is(Unconst!(const(Foo!(const int))) == Foo!(const int))); 9826 static assert(is(Unconst!(Foo!(const int)) == Foo!(const int))); 9827 static assert(is(Unconst!(const(Foo!int)) == Foo!int)); 9828 } 9829 9830 /++ 9831 Removes the outer layer of $(D shared) from type $(D T). 9832 9833 If $(D shared) has not been applied to the outer layer of type $(D T), then 9834 the result is $(D T). 9835 9836 Note that while $(D immutable) is implicitly $(D shared), it is unaffected 9837 by Unshared. Only explicit $(D shared) is removed. 9838 9839 For the built-in scalar types (that is $(D bool), the character types, and 9840 the numeric types), they only have one layer, so $(D shared U) simply 9841 becomes $(D U). 9842 9843 Where the layers come in is pointers and arrays. $(D shared(U*)) becomes 9844 $(D shared(U)*), and $(D shared(U[])), becomes $(D shared(U)[]). So, a 9845 pointer goes from being fully $(D shared) to being a mutable pointer to 9846 $(D shared), and a dynamic array goes from being fully $(D shared) to being 9847 a mutable dynamic array of $(D shared) elements. And if there are multiple 9848 layers of pointers or arrays, it's just that outer layer which is affected 9849 - e.g. $(D shared(U**)) would become $(D shared(U*)*). 9850 9851 For user-defined types, the effect is that $(D shared U) becomes $(D U), 9852 and how that affects member variables depends on the type of the member 9853 variable. If a member variable is explicitly marked with $(D shared), then 9854 it will continue to be $(D shared) even after Unshared has stripped 9855 $(D shared) from the containing type. However, if $(D shared) was on the 9856 member variable only because the containing type was $(D shared), then when 9857 Unshared removes the qualifier from the containing type, it is removed from 9858 the member variable as well. 9859 9860 Also, Unshared has no effect on what a templated type is instantiated 9861 with, so if a templated type is instantiated with a template argument which 9862 has a type qualifier, the template instantiation will not change. 9863 +/ 9864 template Unshared(T) 9865 { 9866 static if (is(T == shared U, U)) 9867 alias Unshared = U; 9868 else 9869 alias Unshared = T; 9870 } 9871 9872 /// 9873 @safe unittest 9874 { 9875 static assert(is(Unshared!( int) == int)); 9876 static assert(is(Unshared!( const int) == const int)); 9877 static assert(is(Unshared!( inout int) == inout int)); 9878 static assert(is(Unshared!( inout const int) == inout const int)); 9879 static assert(is(Unshared!(shared int) == int)); 9880 static assert(is(Unshared!(shared const int) == const int)); 9881 static assert(is(Unshared!(shared inout int) == inout int)); 9882 static assert(is(Unshared!(shared inout const int) == inout const int)); 9883 static assert(is(Unshared!( immutable int) == immutable int)); 9884 9885 // Only the outer layer of shared is removed. 9886 // shared(int[]) -> shared(int)[] 9887 alias SharedIntArr = shared(int[]); 9888 static assert(is(Unshared!SharedIntArr == shared(int)[])); 9889 9890 // Only the outer layer of shared is removed. 9891 // shared(int*) -> shared(int)* 9892 alias SharedIntPtr = shared(int*); 9893 static assert(is(Unshared!SharedIntPtr == shared(int)*)); 9894 9895 // shared(int)* -> shared(int)* 9896 alias PtrToSharedInt = shared(int)*; 9897 static assert(is(Unshared!PtrToSharedInt == shared(int)*)); 9898 9899 // immutable is unaffected 9900 alias ImmutableArr = immutable(int[]); 9901 static assert(is(Unshared!ImmutableArr == immutable(int[]))); 9902 9903 static struct S 9904 { 9905 int* ptr; 9906 const int* cPtr; 9907 shared int* sPtr; 9908 } 9909 9910 shared S s; 9911 static assert(is(typeof(s) == shared S)); 9912 static assert(is(typeof(typeof(s).ptr) == shared int*)); 9913 static assert(is(typeof(typeof(s).cPtr) == const shared int*)); 9914 static assert(is(typeof(typeof(s).sPtr) == shared int*)); 9915 9916 // For user-defined types, if shared is applied to a member variable only 9917 // because the containing type is shared, then shared is removed from that 9918 // member variable, but if the member variable is directly marked as shared, 9919 // then it continues to be shared. 9920 9921 // shared S -> S 9922 static assert(is(Unshared!(typeof(s)) == S)); 9923 static assert(is(typeof(Unshared!(typeof(s)).ptr) == int*)); 9924 static assert(is(typeof(Unshared!(typeof(s)).cPtr) == const int*)); 9925 static assert(is(typeof(Unshared!(typeof(s)).sPtr) == shared int*)); 9926 9927 static struct Foo(T) 9928 { 9929 T* ptr; 9930 } 9931 9932 // The qualifier on the type is removed, but the qualifier on the template 9933 // argument is not. 9934 static assert(is(Unshared!(shared(Foo!(shared int))) == Foo!(shared int))); 9935 static assert(is(Unshared!(Foo!(shared int)) == Foo!(shared int))); 9936 static assert(is(Unshared!(shared(Foo!int)) == Foo!int)); 9937 } 9938 9939 /++ 9940 Removes the outer layer of all type qualifiers from type $(D T) - this 9941 includes $(D shared). 9942 9943 If no type qualifiers have been applied to the outer layer of type $(D T), 9944 then the result is $(D T). 9945 9946 For the built-in scalar types (that is $(D bool), the character types, and 9947 the numeric types), they only have one layer, so $(D const U) simply becomes 9948 $(D U). 9949 9950 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 9951 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 9952 goes from being fully $(D const) to being a mutable pointer to $(D const), 9953 and a dynamic array goes from being fully $(D const) to being a mutable 9954 dynamic array of $(D const) elements. And if there are multiple layers of 9955 pointers or arrays, it's just that outer layer which is affected - e.g. 9956 $(D shared(U**)) would become $(D shared(U*)*). 9957 9958 For user-defined types, the effect is that $(D const U) becomes $(D U), and 9959 how that affects member variables depends on the type of the member 9960 variable. If a member variable is explicitly marked with any qualifiers, 9961 then it will continue to have those qualifiers even after Unqualified has 9962 stripped all qualifiers from the containing type. However, if a qualifier 9963 was on the member variable only because the containing type had that 9964 qualifier, then when Unqualified removes the qualifier from the containing 9965 type, it is removed from the member variable as well. 9966 9967 Also, Unqualified has no effect on what a templated type is instantiated 9968 with, so if a templated type is instantiated with a template argument which 9969 has a type qualifier, the template instantiation will not change. 9970 9971 Note that in most cases, $(LREF Unconst) or $(LREF Unshared) should be used 9972 rather than Unqualified, because in most cases, code is not designed to 9973 work with $(D shared) and thus doing type checks which remove $(D shared) 9974 will allow $(D shared) types to pass template constraints when they won't 9975 actually work with the code. And when code is designed to work with 9976 $(D shared), it's often the case that the type checks need to take 9977 $(D const) into account in order to avoid accidentally mutating $(D const) 9978 data and violating the type system. 9979 9980 In particular, historically, a lot of D code has used 9981 $(REF Unqual, std, traits) (which is equivalent to phobos.sys.traits' 9982 Unqualified) when the programmer's intent was to remove $(D const), and 9983 $(D shared) wasn't actually considered at all. And in such cases, the code 9984 really should use $(LREF Unconst) instead. 9985 9986 But of course, if a template constraint or $(D static if) really needs to 9987 strip off both the mutability qualifiers and $(D shared) for what it's 9988 testing for, then that's what Unqualified is for. It's just that it's best 9989 practice to use $(LREF Unconst) when it's not clear that $(D shared) should 9990 be removed as well. 9991 9992 Also, note that $(D is(immutable T == immutable U))) is equivalent to 9993 $(D is(Unqualified!T == Unqualified!U)) (using $(D immutable) converts 9994 $(D const), $(D inout), and $(D shared) to $(D immutable), whereas using 9995 Unqualified strips off all type qualifiers, but the resulting comparison is 9996 the same as long as $(D immutable) is used on both sides or Unqualified is 9997 used on both sides)). So, in cases where code needs to compare two types to 9998 see whether they're the same while ignoring all qualifiers, it's generally 9999 better to use $(D immutable) on both types rather than using Unqualfied on 10000 both types, since that avoids needing to instantiate a template, and those 10001 instantiations can really add up when a project has a lot of templates 10002 with template constraints, $(D static if)s, and other forms of conditional 10003 compilation that need to compare types. 10004 +/ 10005 template Unqualified(T) 10006 { 10007 import core.internal.traits : CoreUnqualified = Unqual; 10008 alias Unqualified = CoreUnqualified!(T); 10009 } 10010 10011 /// 10012 @safe unittest 10013 { 10014 static assert(is(Unqualified!( int) == int)); 10015 static assert(is(Unqualified!( const int) == int)); 10016 static assert(is(Unqualified!( inout int) == int)); 10017 static assert(is(Unqualified!( inout const int) == int)); 10018 static assert(is(Unqualified!(shared int) == int)); 10019 static assert(is(Unqualified!(shared const int) == int)); 10020 static assert(is(Unqualified!(shared inout int) == int)); 10021 static assert(is(Unqualified!(shared inout const int) == int)); 10022 static assert(is(Unqualified!( immutable int) == int)); 10023 10024 // Only the outer layer of immutable is removed. 10025 // immutable(int[]) -> immutable(int)[] 10026 alias ImmIntArr = immutable(int[]); 10027 static assert(is(Unqualified!ImmIntArr == immutable(int)[])); 10028 10029 // Only the outer layer of const is removed. 10030 // const(int*) -> const(int)* 10031 alias ConstIntPtr = const(int*); 10032 static assert(is(Unqualified!ConstIntPtr == const(int)*)); 10033 10034 // const(int)* -> const(int)* 10035 alias PtrToConstInt = const(int)*; 10036 static assert(is(Unqualified!PtrToConstInt == const(int)*)); 10037 10038 // Only the outer layer of shared is removed. 10039 // shared(int*) -> shared(int)* 10040 alias SharedIntPtr = shared(int*); 10041 static assert(is(Unqualified!SharedIntPtr == shared(int)*)); 10042 10043 // shared(int)* -> shared(int)* 10044 alias PtrToSharedInt = shared(int)*; 10045 static assert(is(Unqualified!PtrToSharedInt == shared(int)*)); 10046 10047 // Both const and shared are removed from the outer layer. 10048 // shared const int[] -> shared(const(int))[] 10049 alias SharedConstIntArr = shared const(int[]); 10050 static assert(is(Unqualified!SharedConstIntArr == shared(const(int))[])); 10051 10052 static struct S 10053 { 10054 int* ptr; 10055 const int* cPtr; 10056 shared int* sPtr; 10057 } 10058 10059 shared const S s; 10060 static assert(is(typeof(s) == shared const S)); 10061 static assert(is(typeof(typeof(s).ptr) == shared const int*)); 10062 static assert(is(typeof(typeof(s).cPtr) == shared const int*)); 10063 static assert(is(typeof(typeof(s).sPtr) == shared const int*)); 10064 10065 // For user-defined types, all qualifiers that are applied to member 10066 // variables only because the containing type has them are removed, but the 10067 // ones that are directly on those member variables remain. 10068 10069 // shared const S -> S 10070 static assert(is(Unqualified!(typeof(s)) == S)); 10071 static assert(is(typeof(Unqualified!(typeof(s)).ptr) == int*)); 10072 static assert(is(typeof(Unqualified!(typeof(s)).cPtr) == const int*)); 10073 static assert(is(typeof(Unqualified!(typeof(s)).sPtr) == shared int*)); 10074 10075 static struct Foo(T) 10076 { 10077 T* ptr; 10078 } 10079 10080 // The qualifiers on the type are removed, but the qualifiers on the 10081 // template argument are not. 10082 static assert(is(Unqualified!(const(Foo!(const int))) == Foo!(const int))); 10083 static assert(is(Unqualified!(Foo!(const int)) == Foo!(const int))); 10084 static assert(is(Unqualified!(const(Foo!int)) == Foo!int)); 10085 } 10086 10087 /++ 10088 Applies $(D const) to the given type. 10089 10090 This is primarily useful in conjunction with templates that take a template 10091 predicate (such as many of the templates in phobos.sys.meta), since while in 10092 most cases, you can simply do $(D const T) or $(D const(T)) to make $(D T) 10093 $(D const), with something like $(REF Map, phobos, sys, meta), you need to 10094 pass a template to be applied. 10095 10096 See_Also: 10097 $(LREF ImmutableOf) 10098 $(LREF InoutOf) 10099 $(LREF SharedOf) 10100 +/ 10101 alias ConstOf(T) = const T; 10102 10103 /// 10104 @safe unittest 10105 { 10106 static assert(is(ConstOf!int == const int)); 10107 static assert(is(ConstOf!(const int) == const int)); 10108 static assert(is(ConstOf!(inout int) == inout const int)); 10109 static assert(is(ConstOf!(shared int) == const shared int)); 10110 10111 // Note that const has no effect on immutable. 10112 static assert(is(ConstOf!(immutable int) == immutable int)); 10113 10114 import phobos.sys.meta : AliasSeq, Map; 10115 10116 alias Types = AliasSeq!(int, long, 10117 bool*, ubyte[], 10118 string, immutable(string)); 10119 alias WithConst = Map!(ConstOf, Types); 10120 static assert(is(WithConst == 10121 AliasSeq!(const int, const long, 10122 const(bool*), const(ubyte[]), 10123 const(string), immutable(string)))); 10124 } 10125 10126 /++ 10127 Applies $(D immutable) to the given type. 10128 10129 This is primarily useful in conjunction with templates that take a template 10130 predicate (such as many of the templates in phobos.sys.meta), since while in 10131 most cases, you can simply do $(D immutable T) or $(D immutable(T)) to make 10132 $(D T) $(D immutable), with something like $(REF Map, phobos, sys, meta), 10133 you need to pass a template to be applied. 10134 10135 See_Also: 10136 $(LREF ConstOf) 10137 $(LREF InoutOf) 10138 $(LREF SharedOf) 10139 +/ 10140 alias ImmutableOf(T) = immutable T; 10141 10142 /// 10143 @safe unittest 10144 { 10145 static assert(is(ImmutableOf!int == immutable int)); 10146 10147 // Note that immutable overrides const and inout. 10148 static assert(is(ImmutableOf!(const int) == immutable int)); 10149 static assert(is(ImmutableOf!(inout int) == immutable int)); 10150 10151 // Note that immutable overrides shared, since immutable is implicitly 10152 // shared. 10153 static assert(is(ImmutableOf!(shared int) == immutable int)); 10154 10155 static assert(is(ImmutableOf!(immutable int) == immutable int)); 10156 10157 import phobos.sys.meta : AliasSeq, Map; 10158 10159 alias Types = AliasSeq!(int, long, 10160 bool*, ubyte[], 10161 string, immutable(string)); 10162 alias WithImmutable = Map!(ImmutableOf, Types); 10163 static assert(is(WithImmutable == 10164 AliasSeq!(immutable int, immutable long, 10165 immutable(bool*), immutable(ubyte[]), 10166 immutable(string), immutable(string)))); 10167 } 10168 10169 /++ 10170 Applies $(D inout) to the given type. 10171 10172 This is primarily useful in conjunction with templates that take a template 10173 predicate (such as many of the templates in phobos.sys.meta), since while in 10174 most cases, you can simply do $(D inout T) or $(D inout(T)) to make $(D T) 10175 $(D inout), with something like $(REF Map, phobos, sys, meta), you need to 10176 pass a template to be applied. 10177 10178 See_Also: 10179 $(LREF ConstOf) 10180 $(LREF ImmutableOf) 10181 $(LREF SharedOf) 10182 +/ 10183 alias InoutOf(T) = inout T; 10184 10185 /// 10186 @safe unittest 10187 { 10188 static assert(is(InoutOf!int == inout int)); 10189 static assert(is(InoutOf!(const int) == inout const int)); 10190 static assert(is(InoutOf!(inout int) == inout int)); 10191 static assert(is(InoutOf!(shared int) == inout shared int)); 10192 10193 // Note that inout has no effect on immutable. 10194 static assert(is(InoutOf!(immutable int) == immutable int)); 10195 10196 import phobos.sys.meta : AliasSeq, Map; 10197 10198 alias Types = AliasSeq!(int, long, 10199 bool*, ubyte[], 10200 string, immutable(string)); 10201 alias WithInout = Map!(InoutOf, Types); 10202 static assert(is(WithInout == 10203 AliasSeq!(inout int, inout long, 10204 inout(bool*), inout(ubyte[]), 10205 inout(string), immutable(string)))); 10206 } 10207 10208 /++ 10209 Applies $(D shared) to the given type. 10210 10211 This is primarily useful in conjunction with templates that take a template 10212 predicate (such as many of the templates in phobos.sys.meta), since while in 10213 most cases, you can simply do $(D shared T) or $(D shared(T)) to make $(D T) 10214 $(D shared), with something like $(REF Map, phobos, sys, meta), you need to 10215 pass a template to be applied. 10216 10217 See_Also: 10218 $(LREF ConstOf) 10219 $(LREF ImmutableOf) 10220 $(LREF InoutOf) 10221 +/ 10222 alias SharedOf(T) = shared T; 10223 10224 /// 10225 @safe unittest 10226 { 10227 static assert(is(SharedOf!int == shared int)); 10228 static assert(is(SharedOf!(const int) == const shared int)); 10229 static assert(is(SharedOf!(inout int) == inout shared int)); 10230 static assert(is(SharedOf!(shared int) == shared int)); 10231 10232 // Note that shared has no effect on immutable, since immutable is 10233 // implicitly shared. 10234 static assert(is(SharedOf!(immutable int) == immutable int)); 10235 10236 import phobos.sys.meta : AliasSeq, Map; 10237 10238 alias Types = AliasSeq!(int, long, 10239 bool*, ubyte[], 10240 string, immutable(string)); 10241 alias WithShared = Map!(SharedOf, Types); 10242 static assert(is(WithShared == 10243 AliasSeq!(shared int, shared long, 10244 shared(bool*), shared(ubyte[]), 10245 shared(string), immutable(string)))); 10246 } 10247 10248 // Needed for rvalueOf/lvalueOf because 10249 // "inout on return means inout must be on a parameter as well" 10250 private struct __InoutWorkaroundStruct {} 10251 10252 /++ 10253 Creates an lvalue or rvalue of type T to be used in conjunction with 10254 $(D is(typeof(...))) or 10255 $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))). 10256 10257 The idea is that some traits or other forms of conditional compilation need 10258 to verify that a particular piece of code compiles with an rvalue or an 10259 lvalue of a specific type, and these $(D @property) functions allow you to 10260 get an rvalue or lvalue of a specific type to use within an expression that 10261 is then tested to see whether it compiles. 10262 10263 They're $(D @property) functions so that using $(D typeof) on them gives 10264 the return type rather than the type of the function. 10265 10266 Note that these functions are $(I not) defined, so if they're actually used 10267 outside of type introspection, they'll result in linker errors. They're 10268 entirely for testing that a particular piece of code compiles with an rvalue 10269 or lvalue of the given type. 10270 10271 The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that 10272 these work when the given type has the $(D inout) qualifier, since the 10273 language requires that a function that returns an $(D inout) type also have 10274 an $(D inout) type as a parameter. It should just be ignored. 10275 +/ 10276 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 10277 10278 /++ Ditto +/ 10279 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 10280 10281 /// 10282 @safe unittest 10283 { 10284 static int foo(int); 10285 static assert(is(typeof(foo(lvalueOf!int)) == int)); 10286 static assert(is(typeof(foo(rvalueOf!int)) == int)); 10287 10288 static bool bar(ref int); 10289 static assert(is(typeof(bar(lvalueOf!int)) == bool)); 10290 static assert(!is(typeof(bar(rvalueOf!int)))); 10291 10292 static assert( is(typeof({ lvalueOf!int = 42; }))); 10293 static assert(!is(typeof({ rvalueOf!int = 42; }))); 10294 10295 static struct S {} 10296 static assert( is(typeof({ lvalueOf!S = S.init; }))); 10297 static assert(!is(typeof({ rvalueOf!S = S.init; }))); 10298 10299 static struct NoAssign 10300 { 10301 @disable void opAssign(ref NoAssign); 10302 } 10303 static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; }))); 10304 static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; }))); 10305 } 10306 10307 @system unittest 10308 { 10309 import phobos.sys.meta : AliasSeq; 10310 10311 void needLvalue(T)(ref T); 10312 static struct S {} 10313 int i; 10314 struct Nested { void f() { ++i; } } 10315 10316 static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object)) 10317 { 10318 static assert(!__traits(compiles, needLvalue(rvalueOf!T))); 10319 static assert( __traits(compiles, needLvalue(lvalueOf!T))); 10320 static assert(is(typeof(rvalueOf!T) == T)); 10321 static assert(is(typeof(lvalueOf!T) == T)); 10322 } 10323 10324 static assert(!__traits(compiles, rvalueOf!int = 1)); 10325 static assert( __traits(compiles, lvalueOf!byte = 127)); 10326 static assert(!__traits(compiles, lvalueOf!byte = 128)); 10327 } 10328 10329 // We may want to add this as some sort of public test helper in the future in 10330 // whatever module would be appropriate for that. 10331 private template assertWithQualifiers(alias Pred, T, bool expected) 10332 { 10333 static assert(Pred!T == expected); 10334 static assert(Pred!(const T) == expected); 10335 static assert(Pred!(inout T) == expected); 10336 static assert(Pred!(immutable T) == expected); 10337 static assert(Pred!(shared T) == expected); 10338 10339 static if (is(T == U*, U)) 10340 { 10341 static assert(Pred!(const(U)*) == expected); 10342 static assert(Pred!(inout(U)*) == expected); 10343 static assert(Pred!(immutable(U)*) == expected); 10344 static assert(Pred!(shared(U)*) == expected); 10345 } 10346 else static if (is(T == U[], U)) 10347 { 10348 static assert(Pred!(const(U)[]) == expected); 10349 static assert(Pred!(inout(U)[]) == expected); 10350 static assert(Pred!(immutable(U)[]) == expected); 10351 static assert(Pred!(shared(U)[]) == expected); 10352 } 10353 else static if (is(T == U[n], U, size_t n)) 10354 { 10355 static assert(Pred!(const(U)[n]) == expected); 10356 static assert(Pred!(inout(U)[n]) == expected); 10357 static assert(Pred!(immutable(U)[n]) == expected); 10358 static assert(Pred!(shared(U)[n]) == expected); 10359 } 10360 } 10361 10362 private template assertWithQualifiers(alias Pred) 10363 { 10364 alias assertWithQualifiers(T, bool expected) = .assertWithQualifiers!(Pred, T, expected); 10365 } 10366 10367 @safe unittest 10368 { 10369 mixin assertWithQualifiers!(isPointer, int*, true); 10370 mixin assertWithQualifiers!(isPointer, int, false); 10371 10372 alias test = assertWithQualifiers!isPointer; 10373 mixin test!(int*, true); 10374 mixin test!(int, false); 10375 }