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 ToFunctionType) 81 )) 82 $(TR $(TD Aggregate Type Traits) $(TD 83 $(LREF FieldNames) 84 $(LREF FieldSymbols) 85 $(LREF FieldTypes) 86 $(LREF hasComplexAssignment) 87 $(LREF hasComplexCopying) 88 $(LREF hasComplexDestruction) 89 $(LREF hasIndirections) 90 )) 91 $(TR $(TD General Types) $(TD 92 $(LREF KeyType) 93 $(LREF OriginalType) 94 $(LREF PropertyType) 95 $(LREF SymbolType) 96 $(LREF ValueType) 97 )) 98 $(TR $(TD Traits for removing type qualfiers) $(TD 99 $(LREF Unconst) 100 $(LREF Unshared) 101 $(LREF Unqualified) 102 )) 103 $(TR $(TD Type Constructors) $(TD 104 $(LREF ConstOf) 105 $(LREF ImmutableOf) 106 $(LREF InoutOf) 107 $(LREF SharedOf) 108 )) 109 $(TR $(TD Misc) $(TD 110 $(LREF defaultInit) 111 $(LREF EnumMembers) 112 $(LREF lvalueOf) 113 $(LREF rvalueOf) 114 )) 115 ) 116 117 Copyright: Copyright The D Language Foundation 2005 - 2024. 118 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 119 Authors: $(HTTP jmdavisprog.com, Jonathan M Davis) 120 $(HTTP digitalmars.com, Walter Bright), 121 Tomasz Stachowiak (`isExpressions`), 122 $(HTTP erdani.org, Andrei Alexandrescu), 123 Shin Fujishiro, 124 $(HTTP octarineparrot.com, Robert Clipsham), 125 $(HTTP klickverbot.at, David Nadlinger), 126 Kenji Hara, 127 Shoichi Kato 128 Source: $(PHOBOSSRC phobos/sys/traits) 129 +/ 130 module phobos.sys.traits; 131 132 /++ 133 Whether the given type is an "aggregate type" - i.e. a struct, class, 134 interface, or union. Enum types whose base type is an aggregate type are 135 also considered aggregate types. 136 +/ 137 template isAggregateType(T) 138 { 139 static if (is(T == enum)) 140 enum isAggregateType = isAggregateType!(OriginalType!T); 141 else 142 enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union); 143 } 144 145 /// 146 @safe unittest 147 { 148 struct S {} 149 class C {} 150 interface I {} 151 union U {} 152 153 static assert( isAggregateType!S); 154 static assert( isAggregateType!C); 155 static assert( isAggregateType!I); 156 static assert( isAggregateType!U); 157 static assert( isAggregateType!(const S)); 158 static assert( isAggregateType!(shared C)); 159 160 static assert(!isAggregateType!int); 161 static assert(!isAggregateType!string); 162 static assert(!isAggregateType!(S*)); 163 static assert(!isAggregateType!(C[])); 164 static assert(!isAggregateType!(I[string])); 165 166 enum ES : S { a = S.init } 167 enum EC : C { a = C.init } 168 enum EI : I { a = I.init } 169 enum EU : U { a = U.init } 170 171 static assert( isAggregateType!ES); 172 static assert( isAggregateType!EC); 173 static assert( isAggregateType!EI); 174 static assert( isAggregateType!EU); 175 static assert( isAggregateType!(const ES)); 176 static assert( isAggregateType!(const EC)); 177 } 178 179 /++ 180 Whether the given type is a dynamic array (or what is sometimes referred to 181 as a slice, since a dynamic array in D is a slice of memory). 182 183 Note that this does not include implicit conversions or enum types. The 184 type itself must be a dynamic array. 185 186 Remember that D's dynamic arrays are essentially: 187 --- 188 struct DynamicArray(T) 189 { 190 size_t length; 191 T* ptr; 192 } 193 --- 194 where $(D ptr) points to the first element in the array, and $(D length) is 195 the number of elements in the array. 196 197 A dynamic array is not a pointer (unlike arrays in C/C++), and its elements 198 do not live inside the dynamic array itself. The dynamic array is simply a 199 slice of memory and does not own or manage its own memory. It can be a 200 slice of any piece of memory, including GC-allocated memory, the stack, 201 malloc-ed memory, etc. (with what kind of memory it is of course being 202 determined by how the dynamic array was created in the first place) 203 - though if you do any operations on it which end up requiring allocation 204 (e.g. appending to it if it doesn't have the capacity to expand in-place, 205 which it won't if it isn't a slice of GC-allocated memory), then that 206 reallocation will result in the dynamic array being a slice of newly 207 allocated, GC-backed memory (regardless of what it was a slice of before), 208 since it's the GC that deals with those allocations. 209 210 As long as code just accesses the elements or members of the dynamic array 211 - or reduces its length so that it's a smaller slice - it will continue to 212 point to whatever block of memory it pointed to originally. And because the 213 GC makes sure that appending to a dynamic array does not stomp on the 214 memory of any other dynamic arrays, appending to a dynamic array will not 215 affect any other dynamic array which is a slice of that same block of 216 memory whether a reallocation occurs or not. 217 218 Regardless, since what allocated the memory that the dynamic array is a 219 slice of is irrevelant to the type of the dynamic array, whether a given 220 type is a dynamic array has nothing to do with the kind of memory that's 221 backing it. A dynamic array which is a slice of a static array of $(D int) 222 is the the same type as a dynamic array of $(D int) allocated with $(D new) 223 - i.e. both are $(D int[]). So, this trait will not tell you anything about 224 what kind of memory a dynamic array is a slice of. It just tells you 225 whether the type is a dynamic array or not. 226 227 If for some reason, it matters for a function what kind of memory backs one 228 of its parameters which is a dynamic array, or it needs to be made clear 229 whether the function will possibly cause that dynamic array to be 230 reallocated, then that needs to be indicated by the documentation and 231 cannot be enforced with a template constraint. A template constraint can 232 enforce that a type used with a template meets certain criteria (e.g. that 233 it's a dynamic array), but it cannot enforce anything about how the 234 template actually uses the type. 235 236 However, it $(D is) possible to enforce that a function doesn't use any 237 operations on a dynamic array which might cause it to be reallocated by 238 marking that function as $(D @nogc). 239 240 In most cases though, code can be written to not care what kind of memory 241 backs a dynamic array, because none of the operations on a dynamic array 242 actually care what kind of memory it's a slice of. It mostly just matters 243 when you need to track the lifetime of the memory, because it wasn't 244 allocated by the GC, or when it matters whether a dynamic array could be 245 reallocated or not (e.g. because the code needs to have that dynamic array 246 continue to point to the same block of memory). 247 248 See_Also: 249 $(LREF isPointer) 250 $(LREF isStaticArray) 251 $(DDSUBLINK spec/arrays, , The language spec for arrays) 252 +/ 253 enum isDynamicArray(T) = is(T == U[], U); 254 255 /// 256 @safe unittest 257 { 258 // Some types which are dynamic arrays. 259 static assert( isDynamicArray!(int[])); 260 static assert( isDynamicArray!(const int[])); 261 static assert( isDynamicArray!(inout int[])); 262 static assert( isDynamicArray!(shared(int)[])); 263 static assert( isDynamicArray!string); 264 265 static assert( isDynamicArray!(typeof([1, 2, 3]))); 266 static assert( isDynamicArray!(typeof("dlang"))); 267 268 int[] arr; 269 static assert( isDynamicArray!(typeof(arr))); 270 271 // Some types which aren't dynamic arrays. 272 static assert(!isDynamicArray!int); 273 static assert(!isDynamicArray!(int*)); 274 static assert(!isDynamicArray!real); 275 276 static struct S 277 { 278 int[] arr; 279 } 280 static assert(!isDynamicArray!S); 281 282 // The struct itself isn't considered a dynamic array, 283 // but its member variable is when checked directly. 284 static assert( isDynamicArray!(typeof(S.arr))); 285 286 // Static arrays. 287 static assert(!isDynamicArray!(int[5])); 288 static assert(!isDynamicArray!(const(int)[5])); 289 290 int[2] sArr = [42, 97]; 291 static assert(!isDynamicArray!(typeof(sArr))); 292 293 // While a static array is not a dynamic array, 294 // a slice of a static array is a dynamic array. 295 static assert( isDynamicArray!(typeof(sArr[]))); 296 297 // Dynamic array of static arrays. 298 static assert( isDynamicArray!(long[3][])); 299 300 // Static array of dynamic arrays. 301 static assert(!isDynamicArray!(long[][3])); 302 303 // Associative array. 304 static assert(!isDynamicArray!(int[string])); 305 306 // While typeof(null) gets treated as void[] in some contexts, it is 307 // distinct from void[] and is not considered to be a dynamic array. 308 static assert(!isDynamicArray!(typeof(null))); 309 310 // However, naturally, if null is cast to a dynamic array, it's a 311 // dynamic array, since the cast forces the type. 312 static assert( isDynamicArray!(typeof(cast(int[]) null))); 313 314 enum E : int[] 315 { 316 a = [1, 2, 3], 317 } 318 319 // Enums do not count. 320 static assert(!isDynamicArray!E); 321 322 static struct AliasThis 323 { 324 int[] arr; 325 alias this = arr; 326 } 327 328 // Other implicit conversions do not count. 329 static assert(!isDynamicArray!AliasThis); 330 } 331 332 @safe unittest 333 { 334 import phobos.sys.meta : Alias, AliasSeq; 335 336 static struct AliasThis(T) 337 { 338 T member; 339 alias this = member; 340 } 341 342 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 343 { 344 foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][])) 345 { 346 enum E : Q!T { a = Q!T.init } 347 348 static assert( isDynamicArray!(Q!T)); 349 static assert(!isDynamicArray!E); 350 static assert(!isDynamicArray!(AliasThis!(Q!T))); 351 } 352 353 foreach (T; AliasSeq!(int, int[51], int[][2], 354 char[][int][11], immutable char[13u], 355 const(real)[1], const(real)[1][1], void[0])) 356 { 357 enum E : Q!T { a = Q!T.init } 358 359 static assert(!isDynamicArray!(Q!T)); 360 static assert(!isDynamicArray!E); 361 static assert(!isDynamicArray!(AliasThis!(Q!T))); 362 } 363 } 364 } 365 366 /++ 367 Whether type $(D T) is a static array. 368 369 Note that this does not include implicit conversions or enum types. The 370 type itself must be a static array. This is in contrast to 371 $(D __traits(isStaticArray, T)) which is true for enums (but not for other 372 implict conversions to static arrays). 373 374 As explained in the module documentation, traits like this one are not true 375 for enums (unlike most of the $(D __traits) traits) in order to avoid 376 testing for implicit conversions by default with template constraints, 377 since that tends to lead to subtle bugs when the code isn't carefully 378 written to take implicit conversions into account. 379 380 See also: 381 $(DDSUBLINK spec/traits, isStaticArray, $(D __traits(isStaticArray, T))) 382 $(DDSUBLINK spec/arrays, , The language spec for arrays) 383 +/ 384 enum isStaticArray(T) = is(T == U[n], U, size_t n); 385 386 /// 387 @safe unittest 388 { 389 // Some types which are static arrays. 390 static assert( isStaticArray!(int[12])); 391 static assert( isStaticArray!(const int[42])); 392 static assert( isStaticArray!(inout int[0])); 393 static assert( isStaticArray!(shared(int)[907])); 394 static assert( isStaticArray!(immutable(char)[5])); 395 396 // D doesn't have static array literals, but you get the same effect 397 // by casting a dynamic array literal to a static array, and of course, 398 // the result is typed as a static array. 399 static assert( isStaticArray!(typeof(cast(int[3]) [1, 2, 3]))); 400 401 int[2] sArr = [1, 2]; 402 static assert( isStaticArray!(typeof(sArr))); 403 404 // Some types which are not static arrays. 405 static assert(!isStaticArray!int); 406 static assert(!isStaticArray!(int*)); 407 static assert(!isStaticArray!real); 408 409 static struct S 410 { 411 int[4] arr; 412 } 413 static assert(!isStaticArray!S); 414 415 // The struct itself isn't considered a static array, 416 // but its member variable is when checked directly. 417 static assert( isStaticArray!(typeof(S.arr))); 418 419 // Dynamic arrays. 420 static assert(!isStaticArray!(int[])); 421 static assert(!isStaticArray!(const(int)[])); 422 static assert(!isStaticArray!string); 423 424 int[] arr; 425 static assert(!isStaticArray!(typeof(arr))); 426 427 // A slice of a static array is of course not a static array, 428 // because it's a dynamic array. 429 static assert(!isStaticArray!(typeof(sArr[]))); 430 431 // Static array of dynamic arrays. 432 static assert( isStaticArray!(long[][3])); 433 434 // Dynamic array of static arrays. 435 static assert(!isStaticArray!(long[3][])); 436 437 // Associative array. 438 static assert(!isStaticArray!(int[string])); 439 440 // Of course, null is not considered to be a static array. 441 static assert(!isStaticArray!(typeof(null))); 442 443 enum E : int[3] 444 { 445 a = [1, 2, 3], 446 } 447 448 // Enums do not count. 449 static assert(!isStaticArray!E); 450 451 // This is where isStaticArray differs from __traits(isStaticArray, ...) 452 static assert( __traits(isStaticArray, E)); 453 454 static struct AliasThis 455 { 456 int[] arr; 457 alias this = arr; 458 } 459 460 // Other implicit conversions do not count. 461 static assert(!isStaticArray!AliasThis); 462 463 static assert(!__traits(isStaticArray, AliasThis)); 464 } 465 466 @safe unittest 467 { 468 import phobos.sys.meta : Alias, AliasSeq; 469 470 static struct AliasThis(T) 471 { 472 T member; 473 alias this = member; 474 } 475 476 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 477 { 478 foreach (T; AliasSeq!(int[51], int[][2], 479 char[][int][11], immutable char[13u], 480 const(real)[1], const(real)[1][1], void[0])) 481 { 482 enum E : Q!T { a = Q!T.init, } 483 484 static assert( isStaticArray!(Q!T)); 485 static assert(!isStaticArray!E); 486 static assert(!isStaticArray!(AliasThis!(Q!T))); 487 } 488 489 foreach (T; AliasSeq!(int, int[], char[], string, long[3][], double[string][])) 490 { 491 enum E : Q!T { a = Q!T.init, } 492 493 static assert(!isStaticArray!(Q!T)); 494 static assert(!isStaticArray!E); 495 static assert(!isStaticArray!(AliasThis!(Q!T))); 496 } 497 } 498 } 499 500 /++ 501 Whether the given type is one of the built-in integer types, ignoring all 502 qualifiers. 503 504 $(TABLE 505 $(TR $(TH Integer Types)) 506 $(TR $(TD byte)) 507 $(TR $(TD ubyte)) 508 $(TR $(TD short)) 509 $(TR $(TD ushort)) 510 $(TR $(TD int)) 511 $(TR $(TD uint)) 512 $(TR $(TD long)) 513 $(TR $(TD ulong)) 514 ) 515 516 Note that this does not include implicit conversions or enum types. The 517 type itself must be one of the built-in integer types. 518 519 This trait does have some similarities with $(D __traits(isIntegral, T)), 520 but $(D isIntegral) accepts a $(I lot) more types than isInteger does. 521 isInteger is specifically for testing for the built-in integer types, 522 whereas $(D isIntegral) tests for a whole set of types that are vaguely 523 integer-like (including $(D bool), the three built-in character types, and 524 some of the vector types from core.simd). So, for most code, isInteger is 525 going to be more appropriate, but obviously, it depends on what the code is 526 trying to do. 527 528 See also: 529 $(DDSUBLINK spec/traits, isIntegral, $(D __traits(isIntegral, T))) 530 $(LREF isFloatingPoint) 531 $(LREF isSignedInteger) 532 $(LREF isNumeric) 533 $(LREF isUnsignedInteger) 534 +/ 535 enum isInteger(T) = is(immutable T == immutable byte) || 536 is(immutable T == immutable ubyte) || 537 is(immutable T == immutable short) || 538 is(immutable T == immutable ushort) || 539 is(immutable T == immutable int) || 540 is(immutable T == immutable uint) || 541 is(immutable T == immutable long) || 542 is(immutable T == immutable ulong); 543 544 /// 545 @safe unittest 546 { 547 // Some types which are integer types. 548 static assert( isInteger!byte); 549 static assert( isInteger!ubyte); 550 static assert( isInteger!short); 551 static assert( isInteger!ushort); 552 static assert( isInteger!int); 553 static assert( isInteger!uint); 554 static assert( isInteger!long); 555 static assert( isInteger!ulong); 556 557 static assert( isInteger!(const ubyte)); 558 static assert( isInteger!(immutable short)); 559 static assert( isInteger!(inout int)); 560 static assert( isInteger!(shared uint)); 561 static assert( isInteger!(const shared ulong)); 562 563 static assert( isInteger!(typeof(42))); 564 static assert( isInteger!(typeof(1234567890L))); 565 566 int i; 567 static assert( isInteger!(typeof(i))); 568 569 // Some types which aren't integer types. 570 static assert(!isInteger!bool); 571 static assert(!isInteger!char); 572 static assert(!isInteger!wchar); 573 static assert(!isInteger!dchar); 574 static assert(!isInteger!(int[])); 575 static assert(!isInteger!(ubyte[4])); 576 static assert(!isInteger!(int*)); 577 static assert(!isInteger!double); 578 static assert(!isInteger!string); 579 580 static struct S 581 { 582 int i; 583 } 584 static assert(!isInteger!S); 585 586 // The struct itself isn't considered an integer, 587 // but its member variable is when checked directly. 588 static assert( isInteger!(typeof(S.i))); 589 590 enum E : int 591 { 592 a = 42 593 } 594 595 // Enums do not count. 596 static assert(!isInteger!E); 597 598 static struct AliasThis 599 { 600 int i; 601 alias this = i; 602 } 603 604 // Other implicit conversions do not count. 605 static assert(!isInteger!AliasThis); 606 } 607 608 @safe unittest 609 { 610 import phobos.sys.meta : Alias, AliasSeq; 611 612 static struct AliasThis(T) 613 { 614 T member; 615 alias this = member; 616 } 617 618 // The actual core.simd types available vary from system to system, so we 619 // have to be a bit creative here. The reason that we're testing these types 620 // is because __traits(isIntegral, T) accepts them, but isInteger is not 621 // supposed to. 622 template SIMDTypes() 623 { 624 import core.simd; 625 626 alias SIMDTypes = AliasSeq!(); 627 static if (is(ubyte16)) 628 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 629 static if (is(int4)) 630 SIMDTypes = AliasSeq!(SIMDTypes, int4); 631 static if (is(double2)) 632 SIMDTypes = AliasSeq!(SIMDTypes, double2); 633 static if (is(void16)) 634 SIMDTypes = AliasSeq!(SIMDTypes, void16); 635 } 636 637 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 638 { 639 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong)) 640 { 641 enum E : Q!T { a = Q!T.init } 642 643 static assert( isInteger!(Q!T)); 644 static assert(!isInteger!E); 645 static assert(!isInteger!(AliasThis!(Q!T))); 646 } 647 648 foreach (T; AliasSeq!(bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 649 int[], ubyte[8], dchar[], void[], long*)) 650 { 651 enum E : Q!T { a = Q!T.init } 652 653 static assert(!isInteger!(Q!T)); 654 static assert(!isInteger!E); 655 static assert(!isInteger!(AliasThis!(Q!T))); 656 } 657 } 658 } 659 660 /++ 661 Whether the given type is one of the built-in signed integer types, ignoring 662 all qualifiers. 663 664 $(TABLE 665 $(TR $(TH Signed Integer Types)) 666 $(TR $(TD byte)) 667 $(TR $(TD short)) 668 $(TR $(TD int)) 669 $(TR $(TD long)) 670 ) 671 672 Note that this does not include implicit conversions or enum types. The 673 type itself must be one of the built-in signed integer types. 674 675 See also: 676 $(LREF isFloatingPoint) 677 $(LREF isInteger) 678 $(LREF isNumeric) 679 $(LREF isUnsignedInteger) 680 +/ 681 enum isSignedInteger(T) = is(immutable T == immutable byte) || 682 is(immutable T == immutable short) || 683 is(immutable T == immutable int) || 684 is(immutable T == immutable long); 685 686 /// 687 @safe unittest 688 { 689 // Some types which are signed integer types. 690 static assert( isSignedInteger!byte); 691 static assert( isSignedInteger!short); 692 static assert( isSignedInteger!int); 693 static assert( isSignedInteger!long); 694 695 static assert( isSignedInteger!(const byte)); 696 static assert( isSignedInteger!(immutable short)); 697 static assert( isSignedInteger!(inout int)); 698 static assert( isSignedInteger!(shared int)); 699 static assert( isSignedInteger!(const shared long)); 700 701 static assert( isSignedInteger!(typeof(42))); 702 static assert( isSignedInteger!(typeof(1234567890L))); 703 704 int i; 705 static assert( isSignedInteger!(typeof(i))); 706 707 // Some types which aren't signed integer types. 708 static assert(!isSignedInteger!ubyte); 709 static assert(!isSignedInteger!ushort); 710 static assert(!isSignedInteger!uint); 711 static assert(!isSignedInteger!ulong); 712 713 static assert(!isSignedInteger!bool); 714 static assert(!isSignedInteger!char); 715 static assert(!isSignedInteger!wchar); 716 static assert(!isSignedInteger!dchar); 717 static assert(!isSignedInteger!(int[])); 718 static assert(!isSignedInteger!(ubyte[4])); 719 static assert(!isSignedInteger!(int*)); 720 static assert(!isSignedInteger!double); 721 static assert(!isSignedInteger!string); 722 723 static struct S 724 { 725 int i; 726 } 727 static assert(!isSignedInteger!S); 728 729 // The struct itself isn't considered a signed integer, 730 // but its member variable is when checked directly. 731 static assert( isSignedInteger!(typeof(S.i))); 732 733 enum E : int 734 { 735 a = 42 736 } 737 738 // Enums do not count. 739 static assert(!isSignedInteger!E); 740 741 static struct AliasThis 742 { 743 int i; 744 alias this = i; 745 } 746 747 // Other implicit conversions do not count. 748 static assert(!isSignedInteger!AliasThis); 749 } 750 751 @safe unittest 752 { 753 import phobos.sys.meta : Alias, AliasSeq; 754 755 static struct AliasThis(T) 756 { 757 T member; 758 alias this = member; 759 } 760 761 // The actual core.simd types available vary from system to system, so we 762 // have to be a bit creative here. The reason that we're testing these types 763 // is because __traits(isIntegral, T) accepts them, but isSignedInteger is 764 // not supposed to. 765 template SIMDTypes() 766 { 767 import core.simd; 768 769 alias SIMDTypes = AliasSeq!(); 770 static if (is(ubyte16)) 771 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 772 static if (is(int4)) 773 SIMDTypes = AliasSeq!(SIMDTypes, int4); 774 static if (is(double2)) 775 SIMDTypes = AliasSeq!(SIMDTypes, double2); 776 static if (is(void16)) 777 SIMDTypes = AliasSeq!(SIMDTypes, void16); 778 } 779 780 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 781 { 782 foreach (T; AliasSeq!(byte, short, int, long)) 783 { 784 enum E : Q!T { a = Q!T.init } 785 786 static assert( isSignedInteger!(Q!T)); 787 static assert(!isSignedInteger!E); 788 static assert(!isSignedInteger!(AliasThis!(Q!T))); 789 } 790 791 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, 792 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 793 int[], ubyte[8], dchar[], void[], long*)) 794 { 795 enum E : Q!T { a = Q!T.init } 796 797 static assert(!isSignedInteger!(Q!T)); 798 static assert(!isSignedInteger!E); 799 static assert(!isSignedInteger!(AliasThis!(Q!T))); 800 } 801 } 802 } 803 804 /++ 805 Whether the given type is one of the built-in unsigned integer types, 806 ignoring all qualifiers. 807 808 $(TABLE 809 $(TR $(TH Integer Types)) 810 $(TR $(TD ubyte)) 811 $(TR $(TD ushort)) 812 $(TR $(TD uint)) 813 $(TR $(TD ulong)) 814 ) 815 816 Note that this does not include implicit conversions or enum types. The 817 type itself must be one of the built-in unsigned integer types. 818 819 This trait does have some similarities with $(D __traits(isUnsigned, T)), 820 but $(D isUnsigned) accepts a $(I lot) more types than isUnsignedInteger 821 does. isUnsignedInteger is specifically for testing for the built-in 822 unsigned integer types, whereas $(D isUnsigned) tests for a whole set of 823 types that are unsigned and vaguely integer-like (including $(D bool), the 824 three built-in character types, and some of the vector types from 825 core.simd). So, for most code, isUnsignedInteger is going to be more 826 appropriate, but obviously, it depends on what the code is trying to do. 827 828 See also: 829 $(DDSUBLINK spec/traits, isUnsigned, $(D __traits(isUnsigned, T))) 830 $(LREF isFloatingPoint) 831 $(LREF isInteger) 832 $(LREF isSignedInteger) 833 $(LREF isNumeric) 834 +/ 835 enum isUnsignedInteger(T) = is(immutable T == immutable ubyte) || 836 is(immutable T == immutable ushort) || 837 is(immutable T == immutable uint) || 838 is(immutable T == immutable ulong); 839 840 /// 841 @safe unittest 842 { 843 // Some types which are unsigned integer types. 844 static assert( isUnsignedInteger!ubyte); 845 static assert( isUnsignedInteger!ushort); 846 static assert( isUnsignedInteger!uint); 847 static assert( isUnsignedInteger!ulong); 848 849 static assert( isUnsignedInteger!(const ubyte)); 850 static assert( isUnsignedInteger!(immutable ushort)); 851 static assert( isUnsignedInteger!(inout uint)); 852 static assert( isUnsignedInteger!(shared uint)); 853 static assert( isUnsignedInteger!(const shared ulong)); 854 855 static assert( isUnsignedInteger!(typeof(42u))); 856 static assert( isUnsignedInteger!(typeof(1234567890UL))); 857 858 uint u; 859 static assert( isUnsignedInteger!(typeof(u))); 860 861 // Some types which aren't unsigned integer types. 862 static assert(!isUnsignedInteger!byte); 863 static assert(!isUnsignedInteger!short); 864 static assert(!isUnsignedInteger!int); 865 static assert(!isUnsignedInteger!long); 866 867 static assert(!isUnsignedInteger!bool); 868 static assert(!isUnsignedInteger!char); 869 static assert(!isUnsignedInteger!wchar); 870 static assert(!isUnsignedInteger!dchar); 871 static assert(!isUnsignedInteger!(int[])); 872 static assert(!isUnsignedInteger!(ubyte[4])); 873 static assert(!isUnsignedInteger!(int*)); 874 static assert(!isUnsignedInteger!double); 875 static assert(!isUnsignedInteger!string); 876 877 static struct S 878 { 879 uint u; 880 } 881 static assert(!isUnsignedInteger!S); 882 883 // The struct itself isn't considered an unsigned integer, 884 // but its member variable is when checked directly. 885 static assert( isUnsignedInteger!(typeof(S.u))); 886 887 enum E : uint 888 { 889 a = 42 890 } 891 892 // Enums do not count. 893 static assert(!isUnsignedInteger!E); 894 895 static struct AliasThis 896 { 897 uint u; 898 alias this = u; 899 } 900 901 // Other implicit conversions do not count. 902 static assert(!isUnsignedInteger!AliasThis); 903 } 904 905 @safe unittest 906 { 907 import phobos.sys.meta : Alias, AliasSeq; 908 909 static struct AliasThis(T) 910 { 911 T member; 912 alias this = member; 913 } 914 915 // The actual core.simd types available vary from system to system, so we 916 // have to be a bit creative here. The reason that we're testing these types 917 // is because __traits(isIntegral, T) and __traits(isUnsigned, T) accept 918 // them, but isUnsignedInteger is not supposed to. 919 template SIMDTypes() 920 { 921 import core.simd; 922 923 alias SIMDTypes = AliasSeq!(); 924 static if (is(ubyte16)) 925 SIMDTypes = AliasSeq!(SIMDTypes, ubyte16); 926 static if (is(int4)) 927 SIMDTypes = AliasSeq!(SIMDTypes, int4); 928 static if (is(double2)) 929 SIMDTypes = AliasSeq!(SIMDTypes, double2); 930 static if (is(void16)) 931 SIMDTypes = AliasSeq!(SIMDTypes, void16); 932 } 933 934 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 935 { 936 foreach (T; AliasSeq!(ubyte, ushort, uint, ulong)) 937 { 938 enum E : Q!T { a = Q!T.init } 939 940 static assert( isUnsignedInteger!(Q!T)); 941 static assert(!isUnsignedInteger!E); 942 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 943 } 944 945 foreach (T; AliasSeq!(byte, short, int, long, 946 bool, char, wchar, dchar, float, double, real, SIMDTypes!(), 947 int[], ubyte[8], dchar[], void[], long*)) 948 { 949 enum E : Q!T { a = Q!T.init } 950 951 static assert(!isUnsignedInteger!(Q!T)); 952 static assert(!isUnsignedInteger!E); 953 static assert(!isUnsignedInteger!(AliasThis!(Q!T))); 954 } 955 } 956 } 957 958 /++ 959 Whether the given type is one of the built-in floating-point types, ignoring 960 all qualifiers. 961 962 $(TABLE 963 $(TR $(TH Floating-Point Types)) 964 $(TR $(TD float)) 965 $(TR $(TD double)) 966 $(TR $(TD real)) 967 ) 968 969 Note that this does not include implicit conversions or enum types. The 970 type itself must be one of the built-in floating-point types. 971 972 This trait does have some similarities with $(D __traits(isFloating, T)), 973 but $(D isFloating) accepts more types than isFloatingPoint does. 974 isFloatingPoint is specifically for testing for the built-in floating-point 975 types, whereas $(D isFloating) tests for a whole set of types that are 976 vaguely float-like (including enums with a base type which is a 977 floating-point type and some of the vector types from core.simd). So, for 978 most code, isFloatingPoint is going to be more appropriate, but obviously, 979 it depends on what the code is trying to do. 980 981 See also: 982 $(DDSUBLINK spec/traits, isFloating, $(D __traits(isFloating, T))) 983 $(LREF isInteger) 984 $(LREF isSignedInteger) 985 $(LREF isNumeric) 986 $(LREF isUnsignedInteger) 987 +/ 988 enum isFloatingPoint(T) = is(immutable T == immutable float) || 989 is(immutable T == immutable double) || 990 is(immutable T == immutable real); 991 992 /// 993 @safe unittest 994 { 995 // Some types which are floating-point types. 996 static assert( isFloatingPoint!float); 997 static assert( isFloatingPoint!double); 998 static assert( isFloatingPoint!real); 999 1000 static assert( isFloatingPoint!(const float)); 1001 static assert( isFloatingPoint!(immutable float)); 1002 static assert( isFloatingPoint!(inout double)); 1003 static assert( isFloatingPoint!(shared double)); 1004 static assert( isFloatingPoint!(const shared real)); 1005 1006 static assert( isFloatingPoint!(typeof(42.0))); 1007 static assert( isFloatingPoint!(typeof(42f))); 1008 static assert( isFloatingPoint!(typeof(1e5))); 1009 static assert( isFloatingPoint!(typeof(97.4L))); 1010 1011 double d; 1012 static assert( isFloatingPoint!(typeof(d))); 1013 1014 // Some types which aren't floating-point types. 1015 static assert(!isFloatingPoint!bool); 1016 static assert(!isFloatingPoint!char); 1017 static assert(!isFloatingPoint!dchar); 1018 static assert(!isFloatingPoint!int); 1019 static assert(!isFloatingPoint!long); 1020 static assert(!isFloatingPoint!(float[])); 1021 static assert(!isFloatingPoint!(double[4])); 1022 static assert(!isFloatingPoint!(real*)); 1023 static assert(!isFloatingPoint!string); 1024 1025 static struct S 1026 { 1027 double d; 1028 } 1029 static assert(!isFloatingPoint!S); 1030 1031 // The struct itself isn't considered a floating-point type, 1032 // but its member variable is when checked directly. 1033 static assert( isFloatingPoint!(typeof(S.d))); 1034 1035 enum E : double 1036 { 1037 a = 12.34 1038 } 1039 1040 // Enums do not count. 1041 static assert(!isFloatingPoint!E); 1042 1043 static struct AliasThis 1044 { 1045 double d; 1046 alias this = d; 1047 } 1048 1049 // Other implicit conversions do not count. 1050 static assert(!isFloatingPoint!AliasThis); 1051 } 1052 1053 @safe unittest 1054 { 1055 import phobos.sys.meta : Alias, AliasSeq; 1056 1057 static struct AliasThis(T) 1058 { 1059 T member; 1060 alias this = member; 1061 } 1062 1063 // The actual core.simd types available vary from system to system, so we 1064 // have to be a bit creative here. The reason that we're testing these types 1065 // is because __traits(isFloating, T) accepts them, but isFloatingPoint is 1066 // not supposed to. 1067 template SIMDTypes() 1068 { 1069 import core.simd; 1070 1071 alias SIMDTypes = AliasSeq!(); 1072 static if (is(int4)) 1073 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1074 static if (is(double2)) 1075 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1076 static if (is(void16)) 1077 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1078 } 1079 1080 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1081 { 1082 foreach (T; AliasSeq!(float, double, real)) 1083 { 1084 enum E : Q!T { a = Q!T.init } 1085 1086 static assert( isFloatingPoint!(Q!T)); 1087 static assert(!isFloatingPoint!E); 1088 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1089 } 1090 1091 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, ubyte, short, ushort, 1092 int, uint, long, ulong, SIMDTypes!(), 1093 int[], float[8], real[], void[], double*)) 1094 { 1095 enum E : Q!T { a = Q!T.init } 1096 1097 static assert(!isFloatingPoint!(Q!T)); 1098 static assert(!isFloatingPoint!E); 1099 static assert(!isFloatingPoint!(AliasThis!(Q!T))); 1100 } 1101 } 1102 } 1103 1104 /++ 1105 Whether the given type is one of the built-in numeric types, ignoring all 1106 qualifiers. It's equivalent to $(D isInteger!T || isFloatingPoint!T), but 1107 it only involves a single template instantation instead of two. 1108 1109 $(TABLE 1110 $(TR $(TH Numeric Types)) 1111 $(TR $(TD byte)) 1112 $(TR $(TD ubyte)) 1113 $(TR $(TD short)) 1114 $(TR $(TD ushort)) 1115 $(TR $(TD int)) 1116 $(TR $(TD uint)) 1117 $(TR $(TD long)) 1118 $(TR $(TD ulong)) 1119 $(TR $(TD float)) 1120 $(TR $(TD double)) 1121 $(TR $(TD real)) 1122 ) 1123 1124 Note that this does not include implicit conversions or enum types. The 1125 type itself must be one of the built-in numeric types. 1126 1127 See_Also: 1128 $(LREF isFloatingPoint) 1129 $(LREF isInteger) 1130 $(LREF isSignedInteger) 1131 $(LREF isUnsignedInteger) 1132 +/ 1133 enum isNumeric(T) = is(immutable T == immutable byte) || 1134 is(immutable T == immutable ubyte) || 1135 is(immutable T == immutable short) || 1136 is(immutable T == immutable ushort) || 1137 is(immutable T == immutable int) || 1138 is(immutable T == immutable uint) || 1139 is(immutable T == immutable long) || 1140 is(immutable T == immutable ulong) || 1141 is(immutable T == immutable float) || 1142 is(immutable T == immutable double) || 1143 is(immutable T == immutable real); 1144 1145 /// 1146 @safe unittest 1147 { 1148 // Some types which are numeric types. 1149 static assert( isNumeric!byte); 1150 static assert( isNumeric!ubyte); 1151 static assert( isNumeric!short); 1152 static assert( isNumeric!ushort); 1153 static assert( isNumeric!int); 1154 static assert( isNumeric!uint); 1155 static assert( isNumeric!long); 1156 static assert( isNumeric!ulong); 1157 static assert( isNumeric!float); 1158 static assert( isNumeric!double); 1159 static assert( isNumeric!real); 1160 1161 static assert( isNumeric!(const short)); 1162 static assert( isNumeric!(immutable int)); 1163 static assert( isNumeric!(inout uint)); 1164 static assert( isNumeric!(shared long)); 1165 static assert( isNumeric!(const shared real)); 1166 1167 static assert( isNumeric!(typeof(42))); 1168 static assert( isNumeric!(typeof(1234657890L))); 1169 static assert( isNumeric!(typeof(42.0))); 1170 static assert( isNumeric!(typeof(42f))); 1171 static assert( isNumeric!(typeof(1e5))); 1172 static assert( isNumeric!(typeof(97.4L))); 1173 1174 int i; 1175 static assert( isNumeric!(typeof(i))); 1176 1177 // Some types which aren't numeric types. 1178 static assert(!isNumeric!bool); 1179 static assert(!isNumeric!char); 1180 static assert(!isNumeric!dchar); 1181 static assert(!isNumeric!(int[])); 1182 static assert(!isNumeric!(double[4])); 1183 static assert(!isNumeric!(real*)); 1184 static assert(!isNumeric!string); 1185 1186 static struct S 1187 { 1188 int i; 1189 } 1190 static assert(!isNumeric!S); 1191 1192 // The struct itself isn't considered a numeric type, 1193 // but its member variable is when checked directly. 1194 static assert( isNumeric!(typeof(S.i))); 1195 1196 enum E : int 1197 { 1198 a = 42 1199 } 1200 1201 // Enums do not count. 1202 static assert(!isNumeric!E); 1203 1204 static struct AliasThis 1205 { 1206 int i; 1207 alias this = i; 1208 } 1209 1210 // Other implicit conversions do not count. 1211 static assert(!isNumeric!AliasThis); 1212 } 1213 1214 @safe unittest 1215 { 1216 import phobos.sys.meta : Alias, AliasSeq; 1217 1218 static struct AliasThis(T) 1219 { 1220 T member; 1221 alias this = member; 1222 } 1223 1224 // The actual core.simd types available vary from system to system, so we 1225 // have to be a bit creative here. The reason that we're testing these types 1226 // is because __traits(isInteger, T) and __traits(isFloating, T) accept 1227 // them, but isNumeric is not supposed to. 1228 template SIMDTypes() 1229 { 1230 import core.simd; 1231 1232 alias SIMDTypes = AliasSeq!(); 1233 static if (is(int4)) 1234 SIMDTypes = AliasSeq!(SIMDTypes, int4); 1235 static if (is(double2)) 1236 SIMDTypes = AliasSeq!(SIMDTypes, double2); 1237 static if (is(void16)) 1238 SIMDTypes = AliasSeq!(SIMDTypes, void16); 1239 } 1240 1241 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1242 { 1243 foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real)) 1244 { 1245 enum E : Q!T { a = Q!T.init } 1246 1247 static assert( isNumeric!(Q!T)); 1248 static assert(!isNumeric!E); 1249 static assert(!isNumeric!(AliasThis!(Q!T))); 1250 } 1251 1252 foreach (T; AliasSeq!(bool, char, wchar, dchar, SIMDTypes!(), 1253 int[], float[8], real[], void[], double*)) 1254 { 1255 enum E : Q!T { a = Q!T.init } 1256 1257 static assert(!isNumeric!(Q!T)); 1258 static assert(!isNumeric!E); 1259 static assert(!isNumeric!(AliasThis!(Q!T))); 1260 } 1261 } 1262 } 1263 1264 /++ 1265 Whether the given type is a pointer. 1266 1267 Note that this does not include implicit conversions or enum types. The 1268 type itself must be a pointer. 1269 1270 Also, remember that unlike C/C++, D's arrays are not pointers. Rather, a 1271 dynamic array in D is a slice of memory which has a member which is a 1272 pointer to its first element and another member which is the length of the 1273 array as $(D size_t). So, a dynamic array / slice has a $(D ptr) member 1274 which is a pointer, but the dynamic array itself is not a pointer. 1275 1276 See_Also: 1277 $(LREF isDynamicArray) 1278 +/ 1279 enum isPointer(T) = is(T == U*, U); 1280 1281 /// 1282 @system unittest 1283 { 1284 // Some types which are pointers. 1285 static assert( isPointer!(bool*)); 1286 static assert( isPointer!(int*)); 1287 static assert( isPointer!(int**)); 1288 static assert( isPointer!(real*)); 1289 static assert( isPointer!(string*)); 1290 1291 static assert( isPointer!(const int*)); 1292 static assert( isPointer!(immutable int*)); 1293 static assert( isPointer!(inout int*)); 1294 static assert( isPointer!(shared int*)); 1295 static assert( isPointer!(const shared int*)); 1296 1297 static assert( isPointer!(typeof("foobar".ptr))); 1298 1299 int* ptr; 1300 static assert( isPointer!(typeof(ptr))); 1301 1302 int i; 1303 static assert( isPointer!(typeof(&i))); 1304 1305 // Some types which aren't pointers. 1306 static assert(!isPointer!bool); 1307 static assert(!isPointer!int); 1308 static assert(!isPointer!dchar); 1309 static assert(!isPointer!(int[])); 1310 static assert(!isPointer!(double[4])); 1311 static assert(!isPointer!string); 1312 1313 static struct S 1314 { 1315 int* ptr; 1316 } 1317 static assert(!isPointer!S); 1318 1319 // The struct itself isn't considered a numeric type, 1320 // but its member variable is when checked directly. 1321 static assert( isPointer!(typeof(S.ptr))); 1322 1323 enum E : immutable(char*) 1324 { 1325 a = "foobar".ptr 1326 } 1327 1328 // Enums do not count. 1329 static assert(!isPointer!E); 1330 1331 static struct AliasThis 1332 { 1333 int* ptr; 1334 alias this = ptr; 1335 } 1336 1337 // Other implicit conversions do not count. 1338 static assert(!isPointer!AliasThis); 1339 } 1340 1341 @safe unittest 1342 { 1343 import phobos.sys.meta : Alias, AliasSeq; 1344 1345 static struct AliasThis(T) 1346 { 1347 T member; 1348 alias this = member; 1349 } 1350 1351 static struct S 1352 { 1353 int i; 1354 } 1355 1356 foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf)) 1357 { 1358 foreach (T; AliasSeq!(long*, S*, S**, S***, double[]*)) 1359 { 1360 enum E : Q!T { a = Q!T.init } 1361 1362 static assert( isPointer!(Q!T)); 1363 static assert(!isPointer!E); 1364 static assert(!isPointer!(AliasThis!(Q!T))); 1365 } 1366 1367 foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, int, uint, long, 1368 int[], float[8], real[], void[])) 1369 { 1370 enum E : Q!T { a = Q!T.init } 1371 1372 static assert(!isPointer!(Q!T)); 1373 static assert(!isPointer!E); 1374 static assert(!isPointer!(AliasThis!(Q!T))); 1375 } 1376 } 1377 } 1378 1379 /++ 1380 Evaluates to $(D true) if given a type and $(D false) for all other symbols. 1381 1382 This is equivalent to $(D is(T)), but some people may find using a named 1383 trait to be clearer, and it can be used in conjunction with templates that 1384 take a template predicate (such as those in phobos.sys.meta), which can't 1385 be done with naked is expressions. 1386 1387 See_Also: 1388 $(DDSUBLINK dlang.org/spec/expression.html, is-type, Spec on the related is expression) 1389 +/ 1390 enum isType(T) = true; 1391 1392 /// Ditto 1393 enum isType(alias sym) = false; 1394 1395 /// 1396 @safe unittest 1397 { 1398 static assert( isType!int); 1399 static assert( isType!(int[])); 1400 static assert( isType!string); 1401 static assert( isType!(int[int])); 1402 static assert( isType!(ubyte*)); 1403 static assert( isType!void); 1404 1405 int i; 1406 static assert(!isType!i); 1407 static assert( isType!(typeof(i))); 1408 1409 struct S {} 1410 static assert( isType!S); 1411 static assert(!isType!(S.init)); 1412 1413 class C {} 1414 static assert( isType!C); 1415 static assert(!isType!(C.init)); 1416 1417 interface I {} 1418 static assert( isType!I); 1419 static assert(!isType!(I.init)); 1420 1421 union U {} 1422 static assert( isType!U); 1423 static assert(!isType!(U.init)); 1424 1425 static void func() {} 1426 static assert(!isType!func); 1427 static assert( isType!(typeof(func))); 1428 1429 void funcWithContext() { ++i; } 1430 static assert(!isType!funcWithContext); 1431 static assert( isType!(typeof(funcWithContext))); 1432 1433 int function() funcPtr; 1434 static assert(!isType!funcPtr); 1435 static assert( isType!(typeof(funcPtr))); 1436 1437 int delegate() del; 1438 static assert(!isType!del); 1439 static assert( isType!(typeof(del))); 1440 1441 template Templ() {} 1442 static assert(!isType!Templ); 1443 static assert(!isType!(Templ!())); 1444 1445 template TemplWithType() 1446 { 1447 struct S {} 1448 } 1449 static assert(!isType!TemplWithType); 1450 static assert(!isType!(TemplWithType!())); 1451 static assert( isType!(TemplWithType!().S)); 1452 1453 struct TemplType() {} 1454 static assert(!isType!TemplType); 1455 static assert( isType!(TemplType!())); 1456 } 1457 1458 /++ 1459 Evaluates to $(D true) if the given type or symbol is an instantiation of 1460 the given template. 1461 1462 The overload which takes $(D T) operates on types and indicates whether an 1463 aggregate type (i.e. struct, class, interface, or union) is an 1464 instantiation of the given template. 1465 1466 The overload which takes $(D Symbol) operates on function templates, 1467 because unlike with aggregate types, the type of a function does not retain 1468 the fact that it was instantiated from a template. So, for functions, it's 1469 necessary to pass the function itself as a symbol rather than pass the type 1470 of the function. 1471 1472 The overload which takes $(D Symbol) also works with templates which are 1473 not types or functions. 1474 1475 The single-argument overload makes it so that it can be partially 1476 instantiated with the first argument, which will often be necessary with 1477 template predicates. 1478 +/ 1479 template isInstantiationOf(alias Template, T) 1480 if (__traits(isTemplate, Template)) 1481 { 1482 enum isInstantiationOf = is(T == Template!Args, Args...); 1483 } 1484 1485 /++ Ditto +/ 1486 template isInstantiationOf(alias Template, alias Symbol) 1487 if (__traits(isTemplate, Template)) 1488 { 1489 enum impl(alias T : Template!Args, Args...) = true; 1490 enum impl(alias T) = false; 1491 enum isInstantiationOf = impl!Symbol; 1492 } 1493 1494 /++ Ditto +/ 1495 template isInstantiationOf(alias Template) 1496 if (__traits(isTemplate, Template)) 1497 { 1498 enum isInstantiationOf(T) = is(T == Template!Args, Args...); 1499 1500 template isInstantiationOf(alias Symbol) 1501 { 1502 enum impl(alias T : Template!Args, Args...) = true; 1503 enum impl(alias T) = false; 1504 enum isInstantiationOf = impl!Symbol; 1505 } 1506 } 1507 1508 /// Examples of templated types. 1509 @safe unittest 1510 { 1511 static struct S(T) {} 1512 static class C(T) {} 1513 1514 static assert( isInstantiationOf!(S, S!int)); 1515 static assert( isInstantiationOf!(S, S!int)); 1516 static assert( isInstantiationOf!(S, S!string)); 1517 static assert( isInstantiationOf!(S, const S!string)); 1518 static assert( isInstantiationOf!(S, shared S!string)); 1519 static assert(!isInstantiationOf!(S, int)); 1520 static assert(!isInstantiationOf!(S, C!int)); 1521 static assert(!isInstantiationOf!(S, C!string)); 1522 static assert(!isInstantiationOf!(S, C!(S!int))); 1523 1524 static assert( isInstantiationOf!(C, C!int)); 1525 static assert( isInstantiationOf!(C, C!string)); 1526 static assert( isInstantiationOf!(C, const C!string)); 1527 static assert( isInstantiationOf!(C, shared C!string)); 1528 static assert(!isInstantiationOf!(C, int)); 1529 static assert(!isInstantiationOf!(C, S!int)); 1530 static assert(!isInstantiationOf!(C, S!string)); 1531 static assert(!isInstantiationOf!(C, S!(C!int))); 1532 1533 static struct Variadic(T...) {} 1534 1535 static assert( isInstantiationOf!(Variadic, Variadic!())); 1536 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1537 static assert( isInstantiationOf!(Variadic, Variadic!(int, string))); 1538 static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int))); 1539 static assert( isInstantiationOf!(Variadic, const Variadic!(int, short))); 1540 static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short))); 1541 static assert(!isInstantiationOf!(Variadic, int)); 1542 static assert(!isInstantiationOf!(Variadic, S!int)); 1543 static assert(!isInstantiationOf!(Variadic, C!int)); 1544 1545 static struct ValueArg(int i) {} 1546 static assert( isInstantiationOf!(ValueArg, ValueArg!42)); 1547 static assert( isInstantiationOf!(ValueArg, ValueArg!256)); 1548 static assert( isInstantiationOf!(ValueArg, const ValueArg!1024)); 1549 static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024)); 1550 static assert(!isInstantiationOf!(ValueArg, int)); 1551 static assert(!isInstantiationOf!(ValueArg, S!int)); 1552 1553 int i; 1554 1555 static struct AliasArg(alias Symbol) {} 1556 static assert( isInstantiationOf!(AliasArg, AliasArg!42)); 1557 static assert( isInstantiationOf!(AliasArg, AliasArg!int)); 1558 static assert( isInstantiationOf!(AliasArg, AliasArg!i)); 1559 static assert( isInstantiationOf!(AliasArg, const AliasArg!i)); 1560 static assert( isInstantiationOf!(AliasArg, shared AliasArg!i)); 1561 static assert(!isInstantiationOf!(AliasArg, int)); 1562 static assert(!isInstantiationOf!(AliasArg, S!int)); 1563 1564 // An uninstantiated template is not an instance of any template, 1565 // not even itself. 1566 static assert(!isInstantiationOf!(S, S)); 1567 static assert(!isInstantiationOf!(S, C)); 1568 static assert(!isInstantiationOf!(C, C)); 1569 static assert(!isInstantiationOf!(C, S)); 1570 1571 // Variables of a templated type are not considered instantiations of that 1572 // type. For templated types, the overload which takes a type must be used. 1573 S!int s; 1574 C!string c; 1575 static assert(!isInstantiationOf!(S, s)); 1576 static assert(!isInstantiationOf!(C, c)); 1577 } 1578 1579 // Examples of templated functions. 1580 @safe unittest 1581 { 1582 static int foo(T...)() { return 42; } 1583 static void bar(T...)(T var) {} 1584 static void baz(T)(T var) {} 1585 static bool frobozz(alias pred)(int) { return true; } 1586 1587 static assert( isInstantiationOf!(foo, foo!int)); 1588 static assert( isInstantiationOf!(foo, foo!string)); 1589 static assert( isInstantiationOf!(foo, foo!(int, string))); 1590 static assert(!isInstantiationOf!(foo, bar!int)); 1591 static assert(!isInstantiationOf!(foo, bar!string)); 1592 static assert(!isInstantiationOf!(foo, bar!(int, string))); 1593 1594 static assert( isInstantiationOf!(bar, bar!int)); 1595 static assert( isInstantiationOf!(bar, bar!string)); 1596 static assert( isInstantiationOf!(bar, bar!(int, string))); 1597 static assert(!isInstantiationOf!(bar, foo!int)); 1598 static assert(!isInstantiationOf!(bar, foo!string)); 1599 static assert(!isInstantiationOf!(bar, foo!(int, string))); 1600 1601 static assert( isInstantiationOf!(baz, baz!int)); 1602 static assert( isInstantiationOf!(baz, baz!string)); 1603 static assert(!isInstantiationOf!(baz, foo!(int, string))); 1604 1605 static assert( isInstantiationOf!(frobozz, frobozz!(a => a))); 1606 static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2))); 1607 static assert(!isInstantiationOf!(frobozz, baz!int)); 1608 1609 // Unfortunately, the function type is not considered an instantiation of 1610 // the template, because that information is not part of the type, unlike 1611 // with templated structs or classes. 1612 static assert(!isInstantiationOf!(foo, typeof(foo!int))); 1613 static assert(!isInstantiationOf!(bar, typeof(bar!int))); 1614 } 1615 1616 // Examples of templates which aren't types or functions. 1617 @safe unittest 1618 { 1619 template SingleArg(T) {} 1620 template Variadic(T...) {} 1621 template ValueArg(string s) {} 1622 template Alias(alias symbol) {} 1623 1624 static assert( isInstantiationOf!(SingleArg, SingleArg!int)); 1625 static assert( isInstantiationOf!(SingleArg, SingleArg!string)); 1626 static assert(!isInstantiationOf!(SingleArg, int)); 1627 static assert(!isInstantiationOf!(SingleArg, Variadic!int)); 1628 1629 static assert( isInstantiationOf!(Variadic, Variadic!())); 1630 static assert( isInstantiationOf!(Variadic, Variadic!int)); 1631 static assert( isInstantiationOf!(Variadic, Variadic!string)); 1632 static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long))); 1633 static assert(!isInstantiationOf!(Variadic, int)); 1634 static assert(!isInstantiationOf!(Variadic, SingleArg!int)); 1635 1636 static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang")); 1637 static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar")); 1638 static assert(!isInstantiationOf!(ValueArg, string)); 1639 static assert(!isInstantiationOf!(ValueArg, Variadic!string)); 1640 1641 int i; 1642 1643 static assert( isInstantiationOf!(Alias, Alias!int)); 1644 static assert( isInstantiationOf!(Alias, Alias!42)); 1645 static assert( isInstantiationOf!(Alias, Alias!i)); 1646 static assert(!isInstantiationOf!(Alias, int)); 1647 static assert(!isInstantiationOf!(Alias, SingleArg!int)); 1648 } 1649 1650 /// Examples of partial instantation. 1651 @safe unittest 1652 { 1653 static struct SingleArg(T) {} 1654 static struct Variadic(T...) {} 1655 1656 alias isSingleArg = isInstantiationOf!SingleArg; 1657 alias isVariadic = isInstantiationOf!Variadic; 1658 1659 static assert( isSingleArg!(SingleArg!int)); 1660 static assert( isSingleArg!(const SingleArg!int)); 1661 static assert(!isSingleArg!int); 1662 static assert(!isSingleArg!(Variadic!int)); 1663 1664 static assert( isVariadic!(Variadic!())); 1665 static assert( isVariadic!(Variadic!int)); 1666 static assert( isVariadic!(shared Variadic!int)); 1667 static assert( isVariadic!(Variadic!(int, string))); 1668 static assert(!isVariadic!int); 1669 static assert(!isVariadic!(SingleArg!int)); 1670 1671 T foo(T)(T t) { return t; } 1672 T likeFoo(T)(T t) { return t; } 1673 bool bar(alias pred)(int i) { return pred(i); } 1674 1675 alias isFoo = isInstantiationOf!foo; 1676 alias isBar = isInstantiationOf!bar; 1677 1678 static assert( isFoo!(foo!int)); 1679 static assert( isFoo!(foo!string)); 1680 static assert(!isFoo!int); 1681 static assert(!isFoo!(likeFoo!int)); 1682 static assert(!isFoo!(bar!(a => true))); 1683 1684 static assert( isBar!(bar!(a => true))); 1685 static assert( isBar!(bar!(a => a > 2))); 1686 static assert(!isBar!int); 1687 static assert(!isBar!(foo!int)); 1688 static assert(!isBar!(likeFoo!int)); 1689 } 1690 1691 /++ 1692 Evaluates to the default-initialized value of the given type. 1693 1694 defaultInit should be used in generic code in contexts where the 1695 default-initialized value of a type is needed rather than that type's 1696 $(D init) value. 1697 1698 For most types, the default-initialized value of a type $(I is) its 1699 $(D init) value - i.e. for some type, $(D T), it would normally be 1700 $(D T.init). However, there are some corner cases in the language where a 1701 type's $(D init) value is not its default-initialized value. In particular, 1702 1703 1. If a type is a non-$(K_STATIC) nested struct, it has a context pointer 1704 which refers to the scope in which it's declared. So, its 1705 default-initialized value is its $(D init) value $(I plus) the value for 1706 its context pointer. However, if such a nested struct is explicitly 1707 initialized with just its $(D init) value instead of being 1708 default-initialized or being constructed via a constructor, then its 1709 context pointer is $(K_NULL), potentially leading to segfaults when the 1710 object is used. 1711 2. If a type is a struct for which default initialization has been disabled 1712 using $(D @disable this();), then while its $(D init) value is still used 1713 as the value of the object at the start of a constructor call (as is the 1714 case with any struct), the struct cannot be default-initialized and must 1715 instead be explicitly constructed. So, instead of $(D T.init) being the 1716 default-initialized value, it's just the struct's initial state before 1717 the constructor constructs the object, and the struct does not actually 1718 have a default-initialized value. 1719 1720 In the case of #2, there is no default initialization for the struct, 1721 whereas in the case of #1, there $(I is) default initialization for the 1722 struct but only within the scope where the struct is declared. Outside of 1723 that scope, the compiler does not have access to that scope and therefore 1724 cannot iniitialize the context pointer with a value, so a compilation error 1725 results. And so, either case can make it so that a struct cannot be 1726 default-initialized. 1727 1728 In both cases, an instance of the struct can still be explicitly 1729 initialized with its $(D init) value, but that will usually lead to 1730 incorrect code, because either the object's context pointer will be 1731 $(K_NULL), or it's a type which was designed with the idea that it would 1732 only ever be explicitly constructed. So, while sometimes it's still 1733 appropriate to explicitly use the $(D init) value (e.g. by default, 1734 $(REF1 destroy, object) will set the object to its $(D init) value after 1735 destroying it so that it's in a valid state to have its destructor called 1736 afterwards in cases where the object is still going to be destroyed when it 1737 leaves scope), in general, generic code which needs to explicitly 1738 default-initialize a variable shouldn't use the type's $(D init) value. 1739 1740 For a type, $(D T), which is a struct which does not declare a $(K_STATIC) 1741 $(D opCall), $(D T()) can be used instead of $(D T.init) to get the type's 1742 default-initialized value, and unlike $(D T.init), it will fail to compile 1743 if the object cannot actually be default-initialized (be it because it has 1744 disabled default initialization, or because it's a nested struct outside of 1745 the scope where that struct was declared). So, unlike $(D T.init), it 1746 won't compile in cases where default initialization does not work, and thus 1747 it can't accidentally be used to initialize a struct which cannot be 1748 default-intiialized. Also, for nested structs, $(D T()) will initialize the 1749 context pointer, unlike $(D T.init). So, using $(D T()) normally gives the 1750 actual default-initialized value for the type or fails to compile if the 1751 type cannot be default-initialized. 1752 1753 However, unfortunately, using $(D T()) does not work in generic code, 1754 because it is legal for a struct to declare a $(K_STATIC) $(D opCall) which 1755 takes no arguments, overriding the normal behavior of $(D T()) and making 1756 it so that it's no longer the default-initialized value. Instead, it's 1757 whatever $(K_STATIC) $(D opCall) returns, and $(K_STATIC) $(D opCall) can 1758 return any type, not just $(D T), because even though it looks like a 1759 constructor call, it's not actually a constructor call, and it can return 1760 whatever the programmer felt like - including $(K_VOID). This means that 1761 the only way to consistently get a default-initialized value for a type in 1762 generic code is to actually declare a variable and not give it a value. 1763 1764 So, in order to work around that, defaultInit does that for you. 1765 $(D defaultInit!Foo) evaluates to the default-initialized value of $(D Foo), 1766 but unlike $(D Foo.init), it won't compile when $(D Foo) cannot be 1767 default-initialized. And it won't get hijacked by $(K_STATIC) $(D opCall). 1768 1769 The downside to using such a helper template is that it will not work with 1770 a nested struct even within the scope where that nested struct is declared 1771 (since defaultInit is declared outside of that scope). So, code which needs 1772 to get a default-initialized instance of a nested struct within the scope 1773 where it's declared will either have to simply declare a variable and not 1774 initialize it or use $(D T()) to explicitly get the default-initialized 1775 value. And since this is within the code where the type is declared, it's 1776 fully within the programmer's control to not declare a $(K_STATIC) 1777 $(D opCall) for it. So, it shouldn't be a problem in practice. 1778 +/ 1779 template defaultInit(T) 1780 if (is(typeof({T t;}))) 1781 { 1782 // At present, simply using T.init should work, since all of the cases where 1783 // it wouldn't won't get past the template constraint. However, it's 1784 // possible that that will change at some point in the future, and this 1785 // approach is guaranteed to give whatever the default-initialized value is 1786 // regardless of whether it's T.init. 1787 enum defaultInit = (){ T retval; return retval; }(); 1788 } 1789 1790 /// 1791 @safe unittest 1792 { 1793 static assert(defaultInit!int == 0); 1794 static assert(defaultInit!bool == false); 1795 static assert(defaultInit!(int*) is null); 1796 static assert(defaultInit!(int[]) is null); 1797 static assert(defaultInit!string is null); 1798 static assert(defaultInit!(int[2]) == [0, 0]); 1799 1800 static struct S 1801 { 1802 int i = 42; 1803 } 1804 static assert(defaultInit!S == S(42)); 1805 1806 static assert(defaultInit!Object is null); 1807 1808 interface I 1809 { 1810 bool foo(); 1811 } 1812 static assert(defaultInit!I is null); 1813 1814 static struct NoDefaultInit 1815 { 1816 int i; 1817 @disable this(); 1818 } 1819 1820 // It's not legal to default-initialize NoDefaultInit, because it has 1821 // disabled default initialization. 1822 static assert(!__traits(compiles, defaultInit!NoDefaultInit)); 1823 1824 int var = 2; 1825 struct Nested 1826 { 1827 int i = 40; 1828 1829 int foo() 1830 { 1831 return i + var; 1832 } 1833 } 1834 1835 // defaultInit doesn't have access to this scope and thus cannot 1836 // initialize the nested struct. 1837 static assert(!__traits(compiles, defaultInit!Nested)); 1838 1839 // However, because Nested has no static opCall (and we know it doesn't 1840 // because we're doing this in the same scope where Nested was declared), 1841 // Nested() can be used to get the default-initialized value. 1842 static assert(Nested() == Nested(40)); 1843 1844 Nested nested; 1845 assert(Nested() == nested); 1846 1847 // Both have properly initialized context pointers, 1848 // whereas Nested.init does not. 1849 assert(Nested().foo() == nested.foo()); 1850 1851 // defaultInit does not get hijacked by static opCall. 1852 static struct HasOpCall 1853 { 1854 int i; 1855 1856 static opCall() 1857 { 1858 return HasOpCall(42); 1859 } 1860 1861 static opCall(int i) 1862 { 1863 HasOpCall retval; 1864 retval.i = i; 1865 return retval; 1866 } 1867 } 1868 1869 static assert(defaultInit!HasOpCall == HasOpCall(0)); 1870 static assert(HasOpCall() == HasOpCall(42)); 1871 } 1872 1873 @safe unittest 1874 { 1875 static struct NoCopy 1876 { 1877 int i = 17; 1878 @disable this(this); 1879 } 1880 static assert(defaultInit!NoCopy == NoCopy(17)); 1881 1882 string function() funcPtr; 1883 static assert(defaultInit!(SymbolType!funcPtr) is null); 1884 1885 string delegate() del; 1886 static assert(defaultInit!(SymbolType!del) is null); 1887 1888 int function() @property propFuncPtr; 1889 static assert(defaultInit!(SymbolType!propFuncPtr) is null); 1890 1891 int delegate() @property propDel; 1892 static assert(defaultInit!(SymbolType!propDel) is null); 1893 } 1894 1895 /++ 1896 Evaluates to an $(D AliasSeq) containing the members of an enum type. 1897 1898 The elements of the $(D AliasSeq) are in the same order as they are in the 1899 enum declaration. 1900 1901 An enum can have multiple members with the same value, so if code needs the 1902 enum values to be unique (e.g. if it's generating a switch statement from 1903 them), then $(REF Unique, phobos, sys, meta) can be used to filter out the 1904 duplicate values - e.g. $(D Unique!(isEqual, EnumMembers!E)). 1905 +/ 1906 template EnumMembers(E) 1907 if (is(E == enum)) 1908 { 1909 import phobos.sys.meta : AliasSeq; 1910 1911 alias EnumMembers = AliasSeq!(); 1912 static foreach (member; __traits(allMembers, E)) 1913 EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, member)); 1914 } 1915 1916 /// Create an array of enum values. 1917 @safe unittest 1918 { 1919 enum Sqrts : real 1920 { 1921 one = 1, 1922 two = 1.41421, 1923 three = 1.73205 1924 } 1925 auto sqrts = [EnumMembers!Sqrts]; 1926 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]); 1927 } 1928 1929 /++ 1930 A generic function $(D rank(v)) in the following example uses this template 1931 for finding a member $(D e) in an enum type $(D E). 1932 +/ 1933 @safe unittest 1934 { 1935 // Returns i if e is the i-th member of E. 1936 static size_t rank(E)(E e) 1937 if (is(E == enum)) 1938 { 1939 static foreach (i, member; EnumMembers!E) 1940 { 1941 if (e == member) 1942 return i; 1943 } 1944 assert(0, "Not an enum member"); 1945 } 1946 1947 enum Mode 1948 { 1949 read = 1, 1950 write = 2, 1951 map = 4 1952 } 1953 assert(rank(Mode.read) == 0); 1954 assert(rank(Mode.write) == 1); 1955 assert(rank(Mode.map) == 2); 1956 } 1957 1958 /// Use EnumMembers to generate a switch statement using static foreach. 1959 @safe unittest 1960 { 1961 static class Foo 1962 { 1963 string calledMethod; 1964 void foo() @safe { calledMethod = "foo"; } 1965 void bar() @safe { calledMethod = "bar"; } 1966 void baz() @safe { calledMethod = "baz"; } 1967 } 1968 1969 enum FuncName : string { foo = "foo", bar = "bar", baz = "baz" } 1970 1971 auto foo = new Foo; 1972 1973 s: final switch (FuncName.bar) 1974 { 1975 static foreach (member; EnumMembers!FuncName) 1976 { 1977 // Generate a case for each enum value. 1978 case member: 1979 { 1980 // Call foo.{enum value}(). 1981 __traits(getMember, foo, member)(); 1982 break s; 1983 } 1984 } 1985 } 1986 1987 // Since we passed FuncName.bar to the switch statement, the bar member 1988 // function was called. 1989 assert(foo.calledMethod == "bar"); 1990 } 1991 1992 @safe unittest 1993 { 1994 { 1995 enum A { a } 1996 static assert([EnumMembers!A] == [A.a]); 1997 enum B { a, b, c, d, e } 1998 static assert([EnumMembers!B] == [B.a, B.b, B.c, B.d, B.e]); 1999 } 2000 { 2001 enum A : string { a = "alpha", b = "beta" } 2002 static assert([EnumMembers!A] == [A.a, A.b]); 2003 2004 static struct S 2005 { 2006 int value; 2007 int opCmp(S rhs) const nothrow { return value - rhs.value; } 2008 } 2009 enum B : S { a = S(1), b = S(2), c = S(3) } 2010 static assert([EnumMembers!B] == [B.a, B.b, B.c]); 2011 } 2012 { 2013 enum A { a = 0, b = 0, c = 1, d = 1, e } 2014 static assert([EnumMembers!A] == [A.a, A.b, A.c, A.d, A.e]); 2015 } 2016 { 2017 enum E { member, a = 0, b = 0 } 2018 2019 static assert(__traits(isSame, EnumMembers!E[0], E.member)); 2020 static assert(__traits(isSame, EnumMembers!E[1], E.a)); 2021 static assert(__traits(isSame, EnumMembers!E[2], E.b)); 2022 2023 static assert(__traits(identifier, EnumMembers!E[0]) == "member"); 2024 static assert(__traits(identifier, EnumMembers!E[1]) == "a"); 2025 static assert(__traits(identifier, EnumMembers!E[2]) == "b"); 2026 } 2027 } 2028 2029 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums 2030 @safe unittest 2031 { 2032 static string genEnum() 2033 { 2034 string result = "enum TLAs {"; 2035 foreach (c0; '0' .. '2' + 1) 2036 { 2037 foreach (c1; '0' .. '9' + 1) 2038 { 2039 foreach (c2; '0' .. '9' + 1) 2040 { 2041 foreach (c3; '0' .. '9' + 1) 2042 { 2043 result ~= '_'; 2044 result ~= c0; 2045 result ~= c1; 2046 result ~= c2; 2047 result ~= c3; 2048 result ~= ','; 2049 } 2050 } 2051 } 2052 } 2053 result ~= '}'; 2054 return result; 2055 } 2056 mixin(genEnum); 2057 static assert(EnumMembers!TLAs[0] == TLAs._0000); 2058 static assert(EnumMembers!TLAs[$ - 1] == TLAs._2999); 2059 } 2060 2061 /++ 2062 Whether the type $(D From) is implicitly convertible to the type $(D To). 2063 2064 Note that template constraints should be very careful about when they test 2065 for implicit conversions and in general should prefer to either test for an 2066 exact set of types or for types which compile with a particular piece of 2067 code rather than being designed to accept any type which implicitly converts 2068 to a particular type. 2069 2070 This is because having a type pass a template constraint based on an 2071 implicit conversion but then not have the implicit conversion actually take 2072 place (which it won't unless the template does something to force it 2073 internally) can lead to either compilation errors or subtle behavioral 2074 differences - and even when the conversion is done explicitly within a 2075 templated function, since it's not done at the call site, it can still lead 2076 to subtle bugs in some cases (e.g. if slicing a static array is involved). 2077 2078 For situations where code needs to verify that a type is implicitly 2079 convertible based solely on its qualifiers, $(LREF isQualifierConvertible) 2080 would be a more appropriate choice than isImplicitlyConvertible. 2081 2082 Given how trivial the $(D is) expression for isImplicitlyConvertible is - 2083 $(D is(To : From)) - this trait is provided primarily so that it can be 2084 used in conjunction with templates that use a template predicate (such as 2085 many of the templates in phobos.sys.meta). 2086 2087 The single-argument overload makes it so that it can be partially 2088 instantiated with the first argument, which will often be necessary with 2089 template predicates. 2090 2091 See_Also: 2092 $(DDSUBLINK dlang.org/spec/type, implicit-conversions, Spec on implicit conversions) 2093 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 2094 $(LREF isQualifierConvertible) 2095 +/ 2096 enum isImplicitlyConvertible(From, To) = is(From : To); 2097 2098 /++ Ditto +/ 2099 template isImplicitlyConvertible(From) 2100 { 2101 enum isImplicitlyConvertible(To) = is(From : To); 2102 } 2103 2104 /// 2105 @safe unittest 2106 { 2107 static assert( isImplicitlyConvertible!(byte, long)); 2108 static assert( isImplicitlyConvertible!(ushort, long)); 2109 static assert( isImplicitlyConvertible!(int, long)); 2110 static assert( isImplicitlyConvertible!(long, long)); 2111 static assert( isImplicitlyConvertible!(ulong, long)); 2112 2113 static assert( isImplicitlyConvertible!(ubyte, int)); 2114 static assert( isImplicitlyConvertible!(short, int)); 2115 static assert( isImplicitlyConvertible!(int, int)); 2116 static assert( isImplicitlyConvertible!(uint, int)); 2117 static assert(!isImplicitlyConvertible!(long, int)); 2118 static assert(!isImplicitlyConvertible!(ulong, int)); 2119 2120 static assert(!isImplicitlyConvertible!(int, string)); 2121 static assert(!isImplicitlyConvertible!(int, int[])); 2122 static assert(!isImplicitlyConvertible!(int, int*)); 2123 2124 static assert(!isImplicitlyConvertible!(string, int)); 2125 static assert(!isImplicitlyConvertible!(int[], int)); 2126 static assert(!isImplicitlyConvertible!(int*, int)); 2127 2128 // For better or worse, bool and the built-in character types will 2129 // implicitly convert to integer or floating-point types if the target type 2130 // is large enough. Sometimes, this is desirable, whereas at other times, 2131 // it can have very surprising results, so it's one reason why code should 2132 // be very careful when testing for implicit conversions. 2133 static assert( isImplicitlyConvertible!(bool, int)); 2134 static assert( isImplicitlyConvertible!(char, int)); 2135 static assert( isImplicitlyConvertible!(wchar, int)); 2136 static assert( isImplicitlyConvertible!(dchar, int)); 2137 2138 static assert( isImplicitlyConvertible!(bool, ubyte)); 2139 static assert( isImplicitlyConvertible!(char, ubyte)); 2140 static assert(!isImplicitlyConvertible!(wchar, ubyte)); 2141 static assert(!isImplicitlyConvertible!(dchar, ubyte)); 2142 2143 static assert( isImplicitlyConvertible!(bool, double)); 2144 static assert( isImplicitlyConvertible!(char, double)); 2145 static assert( isImplicitlyConvertible!(wchar, double)); 2146 static assert( isImplicitlyConvertible!(dchar, double)); 2147 2148 // Value types can be implicitly converted regardless of their qualifiers 2149 // thanks to the fact that they're copied. 2150 static assert( isImplicitlyConvertible!(int, int)); 2151 static assert( isImplicitlyConvertible!(const int, int)); 2152 static assert( isImplicitlyConvertible!(immutable int, int)); 2153 static assert( isImplicitlyConvertible!(inout int, int)); 2154 2155 static assert( isImplicitlyConvertible!(int, const int)); 2156 static assert( isImplicitlyConvertible!(int, immutable int)); 2157 static assert( isImplicitlyConvertible!(int, inout int)); 2158 2159 // Reference types are far more restrictive about which implicit conversions 2160 // they allow, because qualifiers in D are transitive. 2161 static assert( isImplicitlyConvertible!(int*, int*)); 2162 static assert(!isImplicitlyConvertible!(const int*, int*)); 2163 static assert(!isImplicitlyConvertible!(immutable int*, int*)); 2164 2165 static assert( isImplicitlyConvertible!(int*, const int*)); 2166 static assert( isImplicitlyConvertible!(const int*, const int*)); 2167 static assert( isImplicitlyConvertible!(immutable int*, const int*)); 2168 2169 static assert(!isImplicitlyConvertible!(int*, immutable int*)); 2170 static assert(!isImplicitlyConvertible!(const int*, immutable int*)); 2171 static assert( isImplicitlyConvertible!(immutable int*, immutable int*)); 2172 2173 // Note that inout gets a bit weird, since it's only used with function 2174 // parameters, and it's a stand-in for whatever mutability qualifiers the 2175 // type actually has. So, a function parameter that's inout accepts any 2176 // mutability, but you can't actually implicitly convert to inout, because 2177 // it's unknown within the function what the actual mutability of the type 2178 // is. It will differ depending on the function arguments of a specific 2179 // call to that function, so the same code has to work with all combinations 2180 // of mutability qualifiers. 2181 static assert(!isImplicitlyConvertible!(int*, inout int*)); 2182 static assert(!isImplicitlyConvertible!(const int*, inout int*)); 2183 static assert(!isImplicitlyConvertible!(immutable int*, inout int*)); 2184 static assert( isImplicitlyConvertible!(inout int*, inout int*)); 2185 2186 static assert(!isImplicitlyConvertible!(inout int*, int*)); 2187 static assert( isImplicitlyConvertible!(inout int*, const int*)); 2188 static assert(!isImplicitlyConvertible!(inout int*, immutable int*)); 2189 2190 // Enums implicitly convert to their base type. 2191 enum E : int 2192 { 2193 a = 42 2194 } 2195 static assert( isImplicitlyConvertible!(E, int)); 2196 static assert( isImplicitlyConvertible!(E, long)); 2197 static assert(!isImplicitlyConvertible!(E, int[])); 2198 2199 // Structs only implicit convert to another type via declaring an 2200 // alias this. 2201 static struct S 2202 { 2203 int i; 2204 } 2205 static assert(!isImplicitlyConvertible!(S, int)); 2206 static assert(!isImplicitlyConvertible!(S, long)); 2207 static assert(!isImplicitlyConvertible!(S, string)); 2208 2209 static struct AliasThis 2210 { 2211 int i; 2212 alias this = i; 2213 } 2214 static assert( isImplicitlyConvertible!(AliasThis, int)); 2215 static assert( isImplicitlyConvertible!(AliasThis, long)); 2216 static assert(!isImplicitlyConvertible!(AliasThis, string)); 2217 2218 static struct AliasThis2 2219 { 2220 AliasThis at; 2221 alias this = at; 2222 } 2223 static assert( isImplicitlyConvertible!(AliasThis2, AliasThis)); 2224 static assert( isImplicitlyConvertible!(AliasThis2, int)); 2225 static assert( isImplicitlyConvertible!(AliasThis2, long)); 2226 static assert(!isImplicitlyConvertible!(AliasThis2, string)); 2227 2228 static struct AliasThis3 2229 { 2230 AliasThis2 at; 2231 alias this = at; 2232 } 2233 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2)); 2234 static assert( isImplicitlyConvertible!(AliasThis3, AliasThis)); 2235 static assert( isImplicitlyConvertible!(AliasThis3, int)); 2236 static assert( isImplicitlyConvertible!(AliasThis3, long)); 2237 static assert(!isImplicitlyConvertible!(AliasThis3, string)); 2238 2239 // D does not support implicit conversions via construction. 2240 static struct Cons 2241 { 2242 this(int i) 2243 { 2244 this.i = i; 2245 } 2246 2247 int i; 2248 } 2249 static assert(!isImplicitlyConvertible!(int, Cons)); 2250 2251 // Classes support implicit conversion based on their class and 2252 // interface hierarchies. 2253 static interface I1 {} 2254 static class Base : I1 {} 2255 2256 static interface I2 {} 2257 static class Foo : Base, I2 {} 2258 2259 static class Bar : Base {} 2260 2261 static assert( isImplicitlyConvertible!(Base, Base)); 2262 static assert(!isImplicitlyConvertible!(Base, Foo)); 2263 static assert(!isImplicitlyConvertible!(Base, Bar)); 2264 static assert( isImplicitlyConvertible!(Base, I1)); 2265 static assert(!isImplicitlyConvertible!(Base, I2)); 2266 2267 static assert( isImplicitlyConvertible!(Foo, Base)); 2268 static assert( isImplicitlyConvertible!(Foo, Foo)); 2269 static assert(!isImplicitlyConvertible!(Foo, Bar)); 2270 static assert( isImplicitlyConvertible!(Foo, I1)); 2271 static assert( isImplicitlyConvertible!(Foo, I2)); 2272 2273 static assert( isImplicitlyConvertible!(Bar, Base)); 2274 static assert(!isImplicitlyConvertible!(Bar, Foo)); 2275 static assert( isImplicitlyConvertible!(Bar, Bar)); 2276 static assert( isImplicitlyConvertible!(Bar, I1)); 2277 static assert(!isImplicitlyConvertible!(Bar, I2)); 2278 2279 static assert(!isImplicitlyConvertible!(I1, Base)); 2280 static assert(!isImplicitlyConvertible!(I1, Foo)); 2281 static assert(!isImplicitlyConvertible!(I1, Bar)); 2282 static assert( isImplicitlyConvertible!(I1, I1)); 2283 static assert(!isImplicitlyConvertible!(I1, I2)); 2284 2285 static assert(!isImplicitlyConvertible!(I2, Base)); 2286 static assert(!isImplicitlyConvertible!(I2, Foo)); 2287 static assert(!isImplicitlyConvertible!(I2, Bar)); 2288 static assert(!isImplicitlyConvertible!(I2, I1)); 2289 static assert( isImplicitlyConvertible!(I2, I2)); 2290 2291 // Note that arrays are not implicitly convertible even when their elements 2292 // are implicitly convertible. 2293 static assert(!isImplicitlyConvertible!(ubyte[], uint[])); 2294 static assert(!isImplicitlyConvertible!(Foo[], Base[])); 2295 static assert(!isImplicitlyConvertible!(Bar[], Base[])); 2296 2297 // However, like with pointers, dynamic arrays are convertible based on 2298 // constness. 2299 static assert( isImplicitlyConvertible!(Base[], const Base[])); 2300 static assert( isImplicitlyConvertible!(Base[], const(Base)[])); 2301 static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[])); 2302 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 2303 static assert( isImplicitlyConvertible!(const Base[], const Base[])); 2304 static assert(!isImplicitlyConvertible!(const Base[], immutable Base[])); 2305 } 2306 2307 /++ 2308 isImplicitlyConvertible can be used with partial instantiation so that it 2309 can be passed to a template which takes a unary predicate. 2310 +/ 2311 @safe unittest 2312 { 2313 import phobos.sys.meta : AliasSeq, all, indexOf; 2314 2315 // byte is implicitly convertible to byte, short, int, and long. 2316 static assert(all!(isImplicitlyConvertible!byte, short, int, long)); 2317 2318 // const(char)[] at index 2 is the first type in the AliasSeq which string 2319 // can be implicitly converted to. 2320 alias Types = AliasSeq!(int, char[], const(char)[], string, int*); 2321 static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2); 2322 } 2323 2324 /++ 2325 Whether $(D From) is 2326 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) 2327 to $(D To). 2328 2329 This is testing whether $(D From) and $(D To) are the same type - minus the 2330 qualifiers - and whether the qualifiers on $(D From) can be implicitly 2331 converted to the qualifiers on $(D To). No other implicit conversions are 2332 taken into account. 2333 2334 For instance, $(D const int*) is not implicitly convertible to $(D int*), 2335 because that would violate $(D const). That means that $(D const) is not 2336 qualifier convertible to mutable. And as such, $(I any) $(D const) type 2337 is not qualifier convertible to a mutable type even if it's implicitly 2338 convertible. E.G. $(D const int) is implicitly convertible to $(D int), 2339 because it can be copied to avoid violating $(D const), but it's still not 2340 qualifier convertible, because $(D const) types in general cannot be 2341 implicitly converted to mutable. 2342 2343 The exact types being tested matter, because they need to be the same 2344 (minus the qualifiers) in order to be considered convertible, but beyond 2345 that, all that matters for the conversion is whether those qualifers would 2346 be convertible regardless of which types they were on. So, if you're having 2347 trouble picturing whether $(D From) would be qualifier convertible to 2348 $(D To), then consider which conversions would be allowed from $(D From[]) 2349 to $(D To[]) (and remember that dynamic arrays are only implicitly 2350 convertible based on their qualifers). 2351 2352 The $(DDSUBLINK spec/const3, implicit_qualifier_conversions, spec) provides 2353 a table of which qualifiers can be implcitly converted to which other 2354 qualifers (and of course, there a bunch of examples below). 2355 2356 So, isQualifierConvertible can be used in a case like 2357 $(D isQualifierConvertible!(ReturnType!(typeof(foo(bar))), const char), 2358 which would be testing that the return type of $(D foo(bar)) was $(D char), 2359 $(D const char), or $(D immutable char) (since those are the only types 2360 which are qualifier convertible to $(D const char)). 2361 2362 This is in contrast to 2363 $(D isImplicitlyConvertible!(ReturnType!(typeof(foo(bar))), const char), 2364 which would be $(D true) for $(I any) type which was implicitly convertible 2365 to $(D const char) rather than just $(D char), $(D const char), and 2366 $(D immutable char). 2367 2368 The single-argument overload makes it so that it can be partially 2369 instantiated with the first argument, which will often be necessary with 2370 template predicates. 2371 2372 See_Also: 2373 $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions) 2374 $(LREF isImplicitlyConvertible) 2375 +/ 2376 enum isQualifierConvertible(From, To) = is(immutable From == immutable To) && is(From* : To*); 2377 2378 /++ Ditto +/ 2379 template isQualifierConvertible(From) 2380 { 2381 enum isQualifierConvertible(To) = is(immutable From == immutable To) && is(From* : To*); 2382 } 2383 2384 /// 2385 @safe unittest 2386 { 2387 // i.e. char* -> const char* 2388 static assert( isQualifierConvertible!(char, const char)); 2389 2390 // i.e. const char* -> char* 2391 static assert(!isQualifierConvertible!(const char, char)); 2392 2393 static assert( isQualifierConvertible!(int, int)); 2394 static assert( isQualifierConvertible!(int, const int)); 2395 static assert(!isQualifierConvertible!(int, immutable int)); 2396 2397 static assert(!isQualifierConvertible!(const int, int)); 2398 static assert( isQualifierConvertible!(const int, const int)); 2399 static assert(!isQualifierConvertible!(const int, immutable int)); 2400 2401 static assert(!isQualifierConvertible!(immutable int, int)); 2402 static assert( isQualifierConvertible!(immutable int, const int)); 2403 static assert( isQualifierConvertible!(immutable int, immutable int)); 2404 2405 // Note that inout gets a bit weird, since it's only used with function 2406 // parameters, and it's a stand-in for whatever mutability qualifiers the 2407 // type actually has. So, a function parameter that's inout accepts any 2408 // mutability, but you can't actually implicitly convert to inout, because 2409 // it's unknown within the function what the actual mutability of the type 2410 // is. It will differ depending on the function arguments of a specific 2411 // call to that function, so the same code has to work with all combinations 2412 // of mutability qualifiers. 2413 static assert(!isQualifierConvertible!(int, inout int)); 2414 static assert(!isQualifierConvertible!(const int, inout int)); 2415 static assert(!isQualifierConvertible!(immutable int, inout int)); 2416 static assert( isQualifierConvertible!(inout int, inout int)); 2417 2418 static assert(!isQualifierConvertible!(inout int, int)); 2419 static assert( isQualifierConvertible!(inout int, const int)); 2420 static assert(!isQualifierConvertible!(inout int, immutable int)); 2421 2422 // shared is of course also a qualifier. 2423 static assert(!isQualifierConvertible!(int, shared int)); 2424 static assert(!isQualifierConvertible!(int, const shared int)); 2425 static assert(!isQualifierConvertible!(const int, shared int)); 2426 static assert(!isQualifierConvertible!(const int, const shared int)); 2427 static assert(!isQualifierConvertible!(immutable int, shared int)); 2428 static assert( isQualifierConvertible!(immutable int, const shared int)); 2429 2430 static assert(!isQualifierConvertible!(shared int, int)); 2431 static assert(!isQualifierConvertible!(shared int, const int)); 2432 static assert(!isQualifierConvertible!(shared int, immutable int)); 2433 static assert( isQualifierConvertible!(shared int, shared int)); 2434 static assert( isQualifierConvertible!(shared int, const shared int)); 2435 2436 static assert(!isQualifierConvertible!(const shared int, int)); 2437 static assert(!isQualifierConvertible!(const shared int, const int)); 2438 static assert(!isQualifierConvertible!(const shared int, immutable int)); 2439 static assert(!isQualifierConvertible!(const shared int, shared int)); 2440 static assert( isQualifierConvertible!(const shared int, const shared int)); 2441 2442 // Implicit conversions don't count unless they're based purely on 2443 // qualifiers. 2444 enum E : int 2445 { 2446 a = 1 2447 } 2448 2449 static assert(!isQualifierConvertible!(E, int)); 2450 static assert(!isQualifierConvertible!(E, const int)); 2451 static assert( isQualifierConvertible!(E, E)); 2452 static assert( isQualifierConvertible!(E, const E)); 2453 static assert(!isQualifierConvertible!(E, immutable E)); 2454 2455 static struct AliasThis 2456 { 2457 int i; 2458 alias this = i; 2459 } 2460 2461 static assert(!isQualifierConvertible!(AliasThis, int)); 2462 static assert(!isQualifierConvertible!(AliasThis, const int)); 2463 static assert( isQualifierConvertible!(AliasThis, AliasThis)); 2464 static assert( isQualifierConvertible!(AliasThis, const AliasThis)); 2465 static assert(!isQualifierConvertible!(AliasThis, immutable AliasThis)); 2466 2467 // The qualifiers are irrelevant if the types aren't the same when 2468 // stripped of all qualifers. 2469 static assert(!isQualifierConvertible!(int, long)); 2470 static assert(!isQualifierConvertible!(int, const long)); 2471 static assert(!isQualifierConvertible!(string, const(ubyte)[])); 2472 } 2473 2474 /++ 2475 isQualifierConvertible can be used with partial instantiation so that it 2476 can be passed to a template which takes a unary predicate. 2477 +/ 2478 @safe unittest 2479 { 2480 import phobos.sys.meta : AliasSeq, all, indexOf; 2481 2482 // byte is qualifier convertible to byte and const byte. 2483 static assert(all!(isQualifierConvertible!byte, byte, const byte)); 2484 2485 // const(char[]) at index 2 is the first type in the AliasSeq which string 2486 // is qualifier convertible to. 2487 alias Types = AliasSeq!(int, char[], const(char[]), string, int*); 2488 static assert(indexOf!(isQualifierConvertible!string, Types) == 2); 2489 } 2490 2491 @safe unittest 2492 { 2493 import phobos.sys.meta : AliasSeq; 2494 2495 alias Types = AliasSeq!(int, const int, shared int, inout int, const shared int, 2496 const inout int, inout shared int, const inout shared int, immutable int); 2497 2498 // https://dlang.org/spec/const3.html#implicit_qualifier_conversions 2499 enum _ = 0; 2500 static immutable bool[Types.length][Types.length] conversions = [ 2501 // m c s i cs ci is cis im 2502 [1, 1, _, _, _, _, _, _, _], // mutable 2503 [_, 1, _, _, _, _, _, _, _], // const 2504 [_, _, 1, _, 1, _, _, _, _], // shared 2505 [_, 1, _, 1, _, 1, _, _, _], // inout 2506 [_, _, _, _, 1, _, _, _, _], // const shared 2507 [_, 1, _, _, _, 1, _, _, _], // const inout 2508 [_, _, _, _, 1, _, 1, 1, _], // inout shared 2509 [_, _, _, _, 1, _, _, 1, _], // const inout shared 2510 [_, 1, _, _, 1, 1, _, 1, 1], // immutable 2511 ]; 2512 2513 foreach (i, From; Types) 2514 { 2515 foreach (j, To; Types) 2516 { 2517 static assert(isQualifierConvertible!(From, To) == conversions[i][j], 2518 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`" ~ 2519 " should be `" ~ (conversions[i][j] ? "true`" : "false`")); 2520 } 2521 } 2522 } 2523 2524 /++ 2525 Whether the given values are equal per $(D ==). 2526 2527 All this does is $(D lhs == rhs) but in an eponymous template, so most code 2528 shouldn't use it. It's intended to be used in conjunction with templates 2529 that take a template predicate - such as those in phobos.sys.meta. 2530 2531 The single-argument overload makes it so that it can be partially 2532 instantiated with the first argument, which will often be necessary with 2533 template predicates. 2534 2535 Note that in most cases, even when comparing values at compile time, using 2536 isEqual makes no sense, because you can use CTFE to just compare two values 2537 (or expressions which evaluate to values), but in rare cases where you need 2538 to compare symbols in an $(D AliasSeq) by value with a template predicate 2539 while still leaving them as symbols in an $(D AliasSeq), then isEqual would 2540 be needed. 2541 2542 A prime example of this would be $(D Unique!(isEqual, EnumMembers!MyEnum)), 2543 which results in an $(D AliasSeq) containing the list of members of 2544 $(D MyEnum) but without any duplicate values (e.g. to use when doing code 2545 generation to create a final switch). 2546 2547 Alternatively, code such as $(D [EnumMembers!MyEnum].sort().unique()) could 2548 be used to get a dynamic array of the enum members with no duplicate values 2549 via CTFE, thus avoiding the need for template predicates or anything from 2550 phobos.sys.meta. However, you then have a dynamic array of enum values 2551 rather than an $(D AliasSeq) of symbols for those enum members, which 2552 affects what you can do with type introspection. So, which approach is 2553 better depends on what the code needs to do with the enum members. 2554 2555 In general, however, if code doesn't need an $(D AliasSeq), and an array of 2556 values will do the trick, then it's more efficient to operate on an array of 2557 values with CTFE and avoid using isEqual or other templates to operate on 2558 the values as an $(D AliasSeq). 2559 2560 See_Also: 2561 $(LREF isSameSymbol) 2562 $(LREF isSameType) 2563 +/ 2564 enum isEqual(alias lhs, alias rhs) = lhs == rhs; 2565 2566 /++ Ditto +/ 2567 template isEqual(alias lhs) 2568 { 2569 enum isEqual(alias rhs) = lhs == rhs; 2570 } 2571 2572 /// It acts just like ==, but it's a template. 2573 @safe unittest 2574 { 2575 enum a = 42; 2576 2577 static assert( isEqual!(a, 42)); 2578 static assert( isEqual!(20, 10 + 10)); 2579 2580 static assert(!isEqual!(a, 120)); 2581 static assert(!isEqual!(77, 19 * 7 + 2)); 2582 2583 // b cannot be read at compile time, so it won't work with isEqual. 2584 int b = 99; 2585 static assert(!__traits(compiles, isEqual!(b, 99))); 2586 } 2587 2588 /++ 2589 Comparing some of the differences between an $(D AliasSeq) of enum members 2590 and an array of enum values created from an $(D AliasSeq) of enum members. 2591 +/ 2592 @safe unittest 2593 { 2594 import phobos.sys.meta : AliasSeq, Unique; 2595 2596 enum E 2597 { 2598 a = 0, 2599 b = 22, 2600 c = 33, 2601 d = 0, 2602 e = 256, 2603 f = 33, 2604 g = 7 2605 } 2606 2607 alias uniqueMembers = Unique!(isEqual, EnumMembers!E); 2608 static assert(uniqueMembers.length == 5); 2609 2610 static assert(__traits(isSame, uniqueMembers[0], E.a)); 2611 static assert(__traits(isSame, uniqueMembers[1], E.b)); 2612 static assert(__traits(isSame, uniqueMembers[2], E.c)); 2613 static assert(__traits(isSame, uniqueMembers[3], E.e)); 2614 static assert(__traits(isSame, uniqueMembers[4], E.g)); 2615 2616 static assert(__traits(identifier, uniqueMembers[0]) == "a"); 2617 static assert(__traits(identifier, uniqueMembers[1]) == "b"); 2618 static assert(__traits(identifier, uniqueMembers[2]) == "c"); 2619 static assert(__traits(identifier, uniqueMembers[3]) == "e"); 2620 static assert(__traits(identifier, uniqueMembers[4]) == "g"); 2621 2622 // Same value but different symbol. 2623 static assert(uniqueMembers[0] == E.d); 2624 static assert(!__traits(isSame, uniqueMembers[0], E.d)); 2625 2626 // is expressions compare types, not symbols or values, and these AliasSeqs 2627 // contain the list of symbols for the enum members, not types, so the is 2628 // expression evaluates to false even though the symbols are the same. 2629 static assert(!is(uniqueMembers == AliasSeq!(E.a, E.b, E.c, E.e, E.g))); 2630 2631 // Once the members are converted to an array, the types are the same, and 2632 // the values are the same, but the symbols are not the same. Instead of 2633 // being the symbols E.a, E.b, etc., they're just values with the type E 2634 // which match the values of E.a, E.b, etc. 2635 enum arr = [uniqueMembers]; 2636 static assert(is(typeof(arr) == E[])); 2637 2638 static assert(arr == [E.a, E.b, E.c, E.e, E.g]); 2639 static assert(arr == [E.d, E.b, E.f, E.e, E.g]); 2640 2641 static assert(!__traits(isSame, arr[0], E.a)); 2642 static assert(!__traits(isSame, arr[1], E.b)); 2643 static assert(!__traits(isSame, arr[2], E.c)); 2644 static assert(!__traits(isSame, arr[3], E.e)); 2645 static assert(!__traits(isSame, arr[4], E.g)); 2646 2647 // Since arr[0] is just a value of type E, it's no longer the symbol, E.a, 2648 // even though its type is E, and its value is the same as that of E.a. And 2649 // unlike the actual members of an enum, an element of an array does not 2650 // have an identifier, so __traits(identifier, ...) doesn't work with it. 2651 static assert(!__traits(compiles, __traits(identifier, arr[0]))); 2652 2653 // Similarly, once an enum member from the AliasSeq is assigned to a 2654 // variable, __traits(identifer, ...) operates on the variable, not the 2655 // symbol from the AliasSeq or the value of the variable. 2656 auto var = uniqueMembers[0]; 2657 static assert(__traits(identifier, var) == "var"); 2658 2659 // The same with a manifest constant. 2660 enum constant = uniqueMembers[0]; 2661 static assert(__traits(identifier, constant) == "constant"); 2662 } 2663 2664 /++ 2665 Whether the given symbols are the same symbol. 2666 2667 All this does is $(D __traits(isSame, lhs, rhs)), so most code shouldn't 2668 use it. It's intended to be used in conjunction with templates that take a 2669 template predicate - such as those in phobos.sys.meta. 2670 2671 The single-argument overload makes it so that it can be partially 2672 instantiated with the first argument, which will often be necessary with 2673 template predicates. 2674 2675 See_Also: 2676 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, lhs, rhs))) 2677 $(LREF isEqual) 2678 $(LREF isSameType) 2679 +/ 2680 enum isSameSymbol(alias lhs, alias rhs) = __traits(isSame, lhs, rhs); 2681 2682 /++ Ditto +/ 2683 template isSameSymbol(alias lhs) 2684 { 2685 enum isSameSymbol(alias rhs) = __traits(isSame, lhs, rhs); 2686 } 2687 2688 /// 2689 @safe unittest 2690 { 2691 int i; 2692 int j; 2693 real r; 2694 2695 static assert( isSameSymbol!(i, i)); 2696 static assert(!isSameSymbol!(i, j)); 2697 static assert(!isSameSymbol!(i, r)); 2698 2699 static assert(!isSameSymbol!(j, i)); 2700 static assert( isSameSymbol!(j, j)); 2701 static assert(!isSameSymbol!(j, r)); 2702 2703 static assert(!isSameSymbol!(r, i)); 2704 static assert(!isSameSymbol!(r, j)); 2705 static assert( isSameSymbol!(r, r)); 2706 2707 auto foo() { return 0; } 2708 auto bar() { return 0; } 2709 2710 static assert( isSameSymbol!(foo, foo)); 2711 static assert(!isSameSymbol!(foo, bar)); 2712 static assert(!isSameSymbol!(foo, i)); 2713 2714 static assert(!isSameSymbol!(bar, foo)); 2715 static assert( isSameSymbol!(bar, bar)); 2716 static assert(!isSameSymbol!(bar, i)); 2717 2718 // Types are symbols too. However, in most cases, they should be compared 2719 // as types, not symbols (be it with is expressions or with isSameType), 2720 // because the results aren't consistent between scalar types and 2721 // user-defined types with regards to type qualifiers when they're compared 2722 // as symbols. 2723 static assert( isSameSymbol!(double, double)); 2724 static assert(!isSameSymbol!(double, const double)); 2725 static assert(!isSameSymbol!(double, int)); 2726 static assert( isSameSymbol!(Object, Object)); 2727 static assert( isSameSymbol!(Object, const Object)); 2728 2729 static assert(!isSameSymbol!(i, int)); 2730 static assert( isSameSymbol!(typeof(i), int)); 2731 2732 // Lambdas can be compared with __traits(isSame, ...), 2733 // so they can be compared with isSameSymbol. 2734 static assert( isSameSymbol!(a => a + 42, a => a + 42)); 2735 static assert(!isSameSymbol!(a => a + 42, a => a + 99)); 2736 2737 // Partial instantiation allows it to be used with templates that expect 2738 // a predicate that takes only a single argument. 2739 import phobos.sys.meta : AliasSeq, indexOf; 2740 alias Types = AliasSeq!(i, j, r, int, long, foo); 2741 static assert(indexOf!(isSameSymbol!j, Types) == 1); 2742 static assert(indexOf!(isSameSymbol!int, Types) == 3); 2743 static assert(indexOf!(isSameSymbol!bar, Types) == -1); 2744 } 2745 2746 /++ 2747 Whether the given types are the same type. 2748 2749 All this does is $(D is(T == U)), so most code shouldn't use it. It's 2750 intended to be used in conjunction with templates that take a template 2751 predicate - such as those in phobos.sys.meta. 2752 2753 The single-argument overload makes it so that it can be partially 2754 instantiated with the first argument, which will often be necessary with 2755 template predicates. 2756 2757 See_Also: 2758 $(LREF isEqual) 2759 $(LREF isSameSymbol) 2760 +/ 2761 enum isSameType(T, U) = is(T == U); 2762 2763 /++ Ditto +/ 2764 template isSameType(T) 2765 { 2766 enum isSameType(U) = is(T == U); 2767 } 2768 2769 /// 2770 @safe unittest 2771 { 2772 static assert( isSameType!(long, long)); 2773 static assert(!isSameType!(long, const long)); 2774 static assert(!isSameType!(long, string)); 2775 static assert( isSameType!(string, string)); 2776 2777 int i; 2778 real r; 2779 static assert( isSameType!(int, typeof(i))); 2780 static assert(!isSameType!(int, typeof(r))); 2781 2782 static assert(!isSameType!(real, typeof(i))); 2783 static assert( isSameType!(real, typeof(r))); 2784 2785 // Partial instantiation allows it to be used with templates that expect 2786 // a predicate that takes only a single argument. 2787 import phobos.sys.meta : AliasSeq, indexOf; 2788 alias Types = AliasSeq!(float, string, int, double); 2789 static assert(indexOf!(isSameType!int, Types) == 2); 2790 } 2791 2792 /++ 2793 Evaluates to $(K_TRUE) ifthe given type is a delegate (and to $(K_FALSE) 2794 otherwise). 2795 2796 This is equivalent to $(D is(T == delegate)), so most code shouldn't use 2797 it. It's intended to be used in conjunction with templates that take a 2798 template predicate - such as those in $(MREF phobos, sys, meta). 2799 2800 Note that this does not include implicit conversions or enum types. The 2801 type itself must be a delegate. 2802 2803 Whether taking the address of a function results in a function pointer or a 2804 delegate depends on whether the result includes a context pointer. 2805 2806 Taking the address of a free function or a $(K_STATIC) function gives a 2807 function pointer. Taking the address of a non-$(K_STATIC) nested function 2808 gives a delegate. And the potentially confusing one is non-$(K_STATIC) 2809 member functions, because whether taking their address results in a 2810 function pointer or a delegate depends on whether the address is taken via 2811 the type or via an instance. 2812 2813 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 2814 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 2815 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 2816 of a symbol. 2817 2818 See_Also: 2819 $(LREF isFunction) 2820 $(LREF isFunctionPointer) 2821 $(LREF isReturn) 2822 $(LREF PropertyType) 2823 $(LREF SymbolType) 2824 $(LREF ToFunctionType) 2825 +/ 2826 enum isDelegate(T) = is(T == delegate); 2827 2828 /// 2829 @safe unittest 2830 { 2831 int var; 2832 static assert(!isDelegate!(SymbolType!var)); 2833 static assert(!isDelegate!(PropertyType!var)); 2834 static assert(!isDelegate!(typeof(&var))); 2835 static assert(!is(SymbolType!var == delegate)); 2836 static assert(!is(PropertType!var == delegate)); 2837 static assert(!is(typeof(&var) == delegate)); 2838 2839 static void func() {} 2840 static assert(!isDelegate!(SymbolType!func)); 2841 static assert(!isDelegate!(typeof(&func))); 2842 static assert(!is(SymbolType!func == delegate)); 2843 static assert(!is(typeof(&func) == delegate)); 2844 2845 void funcWithContext() { ++var; } 2846 static assert(!isDelegate!(SymbolType!funcWithContext)); 2847 static assert( isDelegate!(typeof(&funcWithContext))); 2848 static assert(!is(SymbolType!funcWithContext == delegate)); 2849 static assert( is(typeof(&funcWithContext) == delegate)); 2850 2851 int function() funcPtr; 2852 static assert(!isDelegate!(SymbolType!funcPtr)); 2853 static assert(!isDelegate!(PropertyType!funcPtr)); 2854 static assert(!isDelegate!(typeof(&funcPtr))); 2855 static assert(!is(SymbolType!funcPtr == delegate)); 2856 static assert(!is(PropertyType!funcPtr == delegate)); 2857 static assert(!is(typeof(&funcPtr) == delegate)); 2858 2859 int delegate() del; 2860 static assert( isDelegate!(SymbolType!del)); 2861 static assert( isDelegate!(PropertyType!del)); 2862 static assert(!isDelegate!(typeof(&del))); 2863 static assert( is(SymbolType!del == delegate)); 2864 static assert( is(PropertyType!del == delegate)); 2865 static assert(!is(typeof(&del) == delegate)); 2866 2867 @property static int prop() { return 0; } 2868 static assert(!isDelegate!(SymbolType!prop)); 2869 static assert(!isDelegate!(PropertyType!prop)); 2870 static assert(!isDelegate!(typeof(&prop))); 2871 static assert(!is(SymbolType!prop == delegate)); 2872 static assert(!is(PropertyType!prop == delegate)); 2873 static assert(!is(typeof(&prop) == delegate)); 2874 2875 @property int propWithContext() { return var; } 2876 static assert(!isDelegate!(SymbolType!propWithContext)); 2877 static assert(!isDelegate!(PropertyType!propWithContext)); 2878 static assert( isDelegate!(typeof(&propWithContext))); 2879 static assert(!is(SymbolType!propWithContext == delegate)); 2880 static assert(!is(PropertyType!propWithContext == delegate)); 2881 static assert( is(typeof(&propWithContext) == delegate)); 2882 2883 static int function() propFuncPtr() @property { return null; } 2884 static assert(!isDelegate!(SymbolType!propFuncPtr)); 2885 static assert(!isDelegate!(PropertyType!propFuncPtr)); 2886 static assert(!isDelegate!(typeof(&propFuncPtr))); 2887 static assert(!is(SymbolType!propFuncPtr == delegate)); 2888 static assert(!is(PropertyType!propFuncPtr == delegate)); 2889 static assert(!is(typeof(&propFuncPtr) == delegate)); 2890 2891 static int delegate() propDel() @property { return null; } 2892 static assert(!isDelegate!(SymbolType!propDel)); 2893 static assert( isDelegate!(PropertyType!propDel)); 2894 static assert(!isDelegate!(typeof(&propDel))); 2895 static assert(!is(SymbolType!propDel == delegate)); 2896 static assert( is(PropertyType!propDel == delegate)); 2897 static assert(!is(typeof(&propDel) == delegate)); 2898 2899 static struct S 2900 { 2901 void foo() {} 2902 } 2903 static assert(!isDelegate!(SymbolType!(S.foo))); 2904 static assert(!isDelegate!(typeof(&S.foo))); 2905 static assert( isDelegate!(typeof(&S.init.foo))); 2906 static assert(!is(SymbolType!(S.foo) == delegate)); 2907 static assert(!is(typeof(&S.foo) == delegate)); 2908 static assert( is(typeof(&S.init.foo) == delegate)); 2909 2910 struct HasContext 2911 { 2912 void foo() { ++var; } 2913 } 2914 static assert(!isDelegate!(SymbolType!(S.foo))); 2915 static assert(!isDelegate!(typeof(&S.foo))); 2916 static assert( isDelegate!(typeof(&S.init.foo))); 2917 static assert(!is(SymbolType!(S.foo) == delegate)); 2918 static assert(!is(typeof(&S.foo) == delegate)); 2919 static assert( is(typeof(&S.init.foo) == delegate)); 2920 } 2921 2922 /++ 2923 Evaluates to $(K_TRUE) if the given type is a function (and to $(K_FALSE) 2924 otherwise). 2925 2926 This is equivalent to $(D is(T == function)), so most code shouldn't use 2927 it. It's intended to be used in conjunction with templates that take a 2928 template predicate - such as those in $(MREF phobos, sys, meta). 2929 2930 Note that this does not include implicit conversions or enum types. The 2931 type itself must be a function. 2932 2933 It's not currently possible in D to type out the type of a function on its 2934 own, so normally, the only way to get a function type is to get the type of 2935 a symbol which is a function. However, $(LREF ToFunctionType) can be used 2936 to convert a function pointer type to a function type for code that needs 2937 that, though that's likely only to come up in $(K_IS) expressions. 2938 2939 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 2940 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 2941 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 2942 of a symbol. 2943 2944 See_Also: 2945 $(LREF isDelegate) 2946 $(LREF isFunctionPointer) 2947 $(LREF isReturn) 2948 $(LREF PropertyType) 2949 $(LREF SymbolType) 2950 $(LREF ToFunctionType) 2951 +/ 2952 enum isFunction(T) = is(T == function); 2953 2954 /// 2955 @safe unittest 2956 { 2957 int var; 2958 static assert(!isFunction!(SymbolType!var)); 2959 static assert(!isFunction!(PropertyType!var)); 2960 static assert(!isFunction!(typeof(&var))); 2961 static assert(!is(SymbolType!var == function)); 2962 static assert(!is(PropertType!var == function)); 2963 static assert(!is(typeof(&var) == function)); 2964 2965 static void func() {} 2966 static assert( isFunction!(SymbolType!func)); 2967 static assert(!isFunction!(typeof(&func))); 2968 static assert( is(SymbolType!func == function)); 2969 static assert(!is(typeof(&func) == function)); 2970 2971 void funcWithContext() { ++var; } 2972 static assert( isFunction!(SymbolType!funcWithContext)); 2973 static assert(!isFunction!(typeof(&funcWithContext))); 2974 static assert( is(SymbolType!funcWithContext == function)); 2975 static assert(!is(typeof(&funcWithContext) == function)); 2976 2977 int function() funcPtr; 2978 static assert(!isFunction!(SymbolType!funcPtr)); 2979 static assert(!isFunction!(PropertyType!funcPtr)); 2980 static assert(!isFunction!(typeof(&funcPtr))); 2981 static assert(!is(SymbolType!funcPtr == function)); 2982 static assert(!is(PropertyType!funcPtr == function)); 2983 static assert(!is(typeof(&funcPtr) == function)); 2984 2985 int delegate() del; 2986 static assert(!isFunction!(SymbolType!del)); 2987 static assert(!isFunction!(PropertyType!del)); 2988 static assert(!isFunction!(typeof(&del))); 2989 static assert(!is(SymbolType!del == function)); 2990 static assert(!is(PropertyType!del == function)); 2991 static assert(!is(typeof(&del) == function)); 2992 2993 // It's possible to get the pointers to the function and the context from a 2994 // delegate in @system code. 2995 static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr))); 2996 static assert( is(typeof(SymbolType!del.ptr) == void*)); 2997 2998 @property static int prop() { return 0; } 2999 static assert( isFunction!(SymbolType!prop)); 3000 static assert(!isFunction!(PropertyType!prop)); 3001 static assert(!isFunction!(typeof(&prop))); 3002 static assert( is(SymbolType!prop == function)); 3003 static assert(!is(PropertyType!prop == function)); 3004 static assert(!is(typeof(&prop) == function)); 3005 3006 @property int propWithContext() { return var; } 3007 static assert( isFunction!(SymbolType!propWithContext)); 3008 static assert(!isFunction!(PropertyType!propWithContext)); 3009 static assert(!isFunction!(typeof(&propWithContext))); 3010 static assert( is(SymbolType!propWithContext == function)); 3011 static assert(!is(PropertyType!propWithContext == function)); 3012 static assert(!is(typeof(&propWithContext) == function)); 3013 3014 static int function() propFuncPtr() @property { return null; } 3015 static assert( isFunction!(SymbolType!propFuncPtr)); 3016 static assert(!isFunction!(PropertyType!propFuncPtr)); 3017 static assert(!isFunction!(typeof(&propFuncPtr))); 3018 static assert( is(SymbolType!propFuncPtr == function)); 3019 static assert(!is(PropertyType!propFuncPtr == function)); 3020 static assert(!is(typeof(&propFuncPtr) == function)); 3021 3022 static int delegate() propDel() @property { return null; } 3023 static assert( isFunction!(SymbolType!propDel)); 3024 static assert(!isFunction!(PropertyType!propDel)); 3025 static assert(!isFunction!(typeof(&propDel))); 3026 static assert( is(SymbolType!propDel == function)); 3027 static assert(!is(PropertyType!propDel == function)); 3028 static assert(!is(typeof(&propDel) == function)); 3029 3030 static struct S 3031 { 3032 void foo() {} 3033 } 3034 static assert( isFunction!(SymbolType!(S.foo))); 3035 static assert(!isFunction!(typeof(&S.foo))); 3036 static assert(!isFunction!(typeof(&S.init.foo))); 3037 static assert( is(SymbolType!(S.foo) == function)); 3038 static assert(!is(typeof(&S.foo) == function)); 3039 static assert(!is(typeof(&S.init.foo) == function)); 3040 3041 struct HasContext 3042 { 3043 void foo() { ++var; } 3044 } 3045 static assert( isFunction!(SymbolType!(S.foo))); 3046 static assert(!isFunction!(typeof(&S.foo))); 3047 static assert(!isFunction!(typeof(&S.init.foo))); 3048 static assert( is(SymbolType!(S.foo) == function)); 3049 static assert(!is(typeof(&S.foo) == function)); 3050 static assert(!is(typeof(&S.init.foo) == function)); 3051 } 3052 3053 /++ 3054 Evaluates to $(K_TRUE) if the given type is a function pointer (and to 3055 $(K_FALSE) otherwise). 3056 3057 Note that this does not include implicit conversions or enum types. The 3058 type itself must be a function pointer. 3059 3060 Whether taking the address of a function results in a function pointer or a 3061 delegate depends on whether the result includes a context pointer. 3062 3063 Taking the address of a free function or a $(K_STATIC) function gives a 3064 function pointer. Taking the address of a non-$(K_STATIC) nested function 3065 gives a delegate. And the potentially confusing one is non-$(K_STATIC) 3066 member functions, because whether taking their address results in a 3067 function pointer or a delegate depends on whether the address is taken via 3068 the type or via an instance. 3069 3070 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 3071 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 3072 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 3073 of a symbol. 3074 3075 See_Also: 3076 $(LREF isDelegate) 3077 $(LREF isFunction) 3078 $(LREF isReturn) 3079 $(LREF PropertyType) 3080 $(LREF SymbolType) 3081 $(LREF ToFunctionType) 3082 +/ 3083 enum isFunctionPointer(T) = is(T == U*, U) && is(U == function); 3084 3085 /// 3086 @safe unittest 3087 { 3088 int var; 3089 static assert(!isFunctionPointer!(SymbolType!var)); 3090 static assert(!isFunctionPointer!(PropertyType!var)); 3091 static assert(!isFunctionPointer!(typeof(&var))); 3092 3093 static void func() {} 3094 static assert(!isFunctionPointer!(SymbolType!func)); 3095 static assert( isFunctionPointer!(typeof(&func))); 3096 3097 void funcWithContext() { ++var; } 3098 static assert(!isFunctionPointer!(SymbolType!funcWithContext)); 3099 static assert(!isFunctionPointer!(typeof(&funcWithContext))); 3100 3101 int function() funcPtr; 3102 static assert( isFunctionPointer!(SymbolType!funcPtr)); 3103 static assert( isFunctionPointer!(PropertyType!funcPtr)); 3104 static assert(!isFunctionPointer!(typeof(&funcPtr))); 3105 3106 int delegate() del; 3107 static assert(!isFunctionPointer!(SymbolType!del)); 3108 static assert(!isFunctionPointer!(PropertyType!del)); 3109 static assert(!isFunctionPointer!(typeof(&del))); 3110 3111 // It's possible to get the pointers to the function and the context from a 3112 // delegate in @system code. 3113 static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr))); 3114 static assert( is(typeof(SymbolType!del.ptr) == void*)); 3115 3116 @property static int prop() { return 0; } 3117 static assert(!isFunctionPointer!(SymbolType!prop)); 3118 static assert(!isFunctionPointer!(PropertyType!prop)); 3119 static assert( isFunctionPointer!(typeof(&prop))); 3120 3121 @property int propWithContext() { return var; } 3122 static assert(!isFunctionPointer!(SymbolType!propWithContext)); 3123 static assert(!isFunctionPointer!(PropertyType!propWithContext)); 3124 static assert(!isFunctionPointer!(typeof(&propWithContext))); 3125 3126 static int function() propFuncPtr() @property { return null; } 3127 static assert(!isFunctionPointer!(SymbolType!propFuncPtr)); 3128 static assert( isFunctionPointer!(PropertyType!propFuncPtr)); 3129 static assert( isFunctionPointer!(typeof(&propFuncPtr))); 3130 3131 static int delegate() propDel() @property { return null; } 3132 static assert(!isFunctionPointer!(SymbolType!propDel)); 3133 static assert(!isFunctionPointer!(PropertyType!propDel)); 3134 static assert( isFunctionPointer!(typeof(&propDel))); 3135 3136 static struct S 3137 { 3138 void foo() {} 3139 } 3140 static assert(!isFunctionPointer!(SymbolType!(S.foo))); 3141 static assert( isFunctionPointer!(typeof(&S.foo))); 3142 static assert(!isFunctionPointer!(typeof(&S.init.foo))); 3143 3144 struct HasContext 3145 { 3146 void foo() { ++var; } 3147 } 3148 static assert(!isFunctionPointer!(SymbolType!(S.foo))); 3149 static assert( isFunctionPointer!(typeof(&S.foo))); 3150 static assert(!isFunctionPointer!(typeof(&S.init.foo))); 3151 } 3152 3153 /++ 3154 Evaluates to $(K_TRUE) if the given type is a function, function pointer, 3155 or delegate (and to $(K_FALSE) otherwise). 3156 3157 This is equivalent to $(D is(T == return)), so most code shouldn't use 3158 it. It's intended to be used in conjunction with templates that take a 3159 template predicate - such as those in $(MREF phobos, sys, meta). 3160 3161 Note that this does not include implicit conversions or enum types. The 3162 type itself must be a function, function pointer, or delegate. 3163 3164 See the documentation for $(LREF SymbolType) and $(LREF PropertyType) to 3165 see the quirks involving $(K_PROPERTY) and why either $(LREF SymbolType) or 3166 $(LREF PropertyType) should be used rather than $(K_TYPEOF) to get the type 3167 of a symbol. 3168 3169 See_Also: 3170 $(LREF isDelegate) 3171 $(LREF isFunction) 3172 $(LREF isFunctionPointer) 3173 $(LREF PropertyType) 3174 $(LREF SymbolType) 3175 $(LREF ToFunctionType) 3176 +/ 3177 enum isReturn(T) = is(T == return); 3178 3179 /// 3180 @safe unittest 3181 { 3182 int var; 3183 static assert(!isReturn!(SymbolType!var)); 3184 static assert(!isReturn!(PropertyType!var)); 3185 static assert(!isReturn!(typeof(&var))); 3186 static assert(!is(SymbolType!var == return)); 3187 static assert(!is(PropertType!var == return)); 3188 static assert(!is(typeof(&var) == return)); 3189 3190 static void func() {} 3191 static assert( isReturn!(SymbolType!func)); 3192 static assert( isReturn!(typeof(&func))); 3193 static assert( is(SymbolType!func == return)); 3194 static assert( is(typeof(&func) == return)); 3195 3196 void funcWithContext() { ++var; } 3197 static assert( isReturn!(SymbolType!funcWithContext)); 3198 static assert( isReturn!(typeof(&funcWithContext))); 3199 static assert( is(SymbolType!funcWithContext == return)); 3200 static assert( is(typeof(&funcWithContext) == return)); 3201 3202 int function() funcPtr; 3203 static assert( isReturn!(SymbolType!funcPtr)); 3204 static assert( isReturn!(PropertyType!funcPtr)); 3205 static assert(!isReturn!(typeof(&funcPtr))); 3206 static assert( is(SymbolType!funcPtr == return)); 3207 static assert( is(PropertyType!funcPtr == return)); 3208 static assert(!is(typeof(&funcPtr) == return)); 3209 3210 int delegate() del; 3211 static assert( isReturn!(SymbolType!del)); 3212 static assert( isReturn!(PropertyType!del)); 3213 static assert(!isReturn!(typeof(&del))); 3214 static assert( is(SymbolType!del == return)); 3215 static assert( is(PropertyType!del == return)); 3216 static assert(!is(typeof(&del) == return)); 3217 3218 // It's possible to get the pointers to the function and the context from a 3219 // delegate in @system code. 3220 static assert( isFunctionPointer!(typeof(SymbolType!del.funcptr))); 3221 static assert( is(typeof(SymbolType!del.ptr) == void*)); 3222 3223 @property static int prop() { return 0; } 3224 static assert( isReturn!(SymbolType!prop)); 3225 static assert(!isReturn!(PropertyType!prop)); 3226 static assert( isReturn!(typeof(&prop))); 3227 static assert( is(SymbolType!prop == return)); 3228 static assert(!is(PropertyType!prop == return)); 3229 static assert( is(typeof(&prop) == return)); 3230 3231 @property int propWithContext() { return var; } 3232 static assert( isReturn!(SymbolType!propWithContext)); 3233 static assert(!isReturn!(PropertyType!propWithContext)); 3234 static assert( isReturn!(typeof(&propWithContext))); 3235 static assert( is(SymbolType!propWithContext == return)); 3236 static assert(!is(PropertyType!propWithContext == return)); 3237 static assert( is(typeof(&propWithContext) == return)); 3238 3239 static int function() propFuncPtr() @property { return null; } 3240 static assert( isReturn!(SymbolType!propFuncPtr)); 3241 static assert( isReturn!(PropertyType!propFuncPtr)); 3242 static assert( isReturn!(typeof(&propFuncPtr))); 3243 static assert( is(SymbolType!propFuncPtr == return)); 3244 static assert( is(PropertyType!propFuncPtr == return)); 3245 static assert( is(typeof(&propFuncPtr) == return)); 3246 3247 static int delegate() propDel() @property { return null; } 3248 static assert( isReturn!(SymbolType!propDel)); 3249 static assert( isReturn!(PropertyType!propDel)); 3250 static assert( isReturn!(typeof(&propDel))); 3251 static assert( is(SymbolType!propDel == return)); 3252 static assert( is(PropertyType!propDel == return)); 3253 static assert( is(typeof(&propDel) == return)); 3254 3255 static struct S 3256 { 3257 void foo() {} 3258 } 3259 static assert( isReturn!(SymbolType!(S.foo))); 3260 static assert( isReturn!(typeof(&S.foo))); 3261 static assert( isReturn!(typeof(&S.init.foo))); 3262 static assert( is(SymbolType!(S.foo) == return)); 3263 static assert( is(typeof(&S.foo) == return)); 3264 static assert( is(typeof(&S.init.foo) == return)); 3265 3266 struct HasContext 3267 { 3268 void foo() { ++var; } 3269 } 3270 static assert( isReturn!(SymbolType!(S.foo))); 3271 static assert( isReturn!(typeof(&S.foo))); 3272 static assert( isReturn!(typeof(&S.init.foo))); 3273 static assert( is(SymbolType!(S.foo) == return)); 3274 static assert( is(typeof(&S.foo) == return)); 3275 static assert( is(typeof(&S.init.foo) == return)); 3276 } 3277 3278 /++ 3279 Converts a function type, function pointer type, or delegate type to the 3280 corresponding function type. 3281 3282 For a function, the result is the same as the given type. 3283 3284 For a function pointer or delegate, the result is the same as it would be 3285 for a function with the same return type, the same set of parameters, and 3286 the same set of attributes. 3287 3288 Another way to look at it would be that it's the type that comes from 3289 dereferencing the function pointer. And while it's not technically possible 3290 to dereference a delegate, it's conceptually the same thing, since a 3291 delegate is essentially a fat pointer to a function in the sense that it 3292 contains a pointer to a function and a pointer to the function's context. 3293 The result of ToFunctionType is the type of that function. 3294 3295 Note that code which has a symbol which is a function should use 3296 $(LREF SymbolType) rather than $(K_TYPEOF) to get the type of the function 3297 in order to avoid issues with regards to $(K_PROPERTY) (see the 3298 documentation for $(LREF SymbolType) for details). 3299 3300 See_Also: 3301 $(LREF SymbolType) 3302 +/ 3303 template ToFunctionType(T) 3304 if (is(T == return)) 3305 { 3306 // Function pointers. 3307 static if (is(T == U*, U) && is(U == function)) 3308 alias ToFunctionType = U; 3309 // Delegates. 3310 else static if (is(T U == delegate)) 3311 alias ToFunctionType = U; 3312 // Functions. 3313 else 3314 alias ToFunctionType = T; 3315 } 3316 3317 /// 3318 @safe unittest 3319 { 3320 static string func(int) { return ""; } 3321 auto funcPtr = &func; 3322 3323 static assert( is(ToFunctionType!(SymbolType!func) == SymbolType!func)); 3324 static assert( is(ToFunctionType!(SymbolType!funcPtr) == SymbolType!func)); 3325 static assert(!is(SymbolType!funcPtr == function)); 3326 static assert( is(ToFunctionType!(SymbolType!funcPtr) == function)); 3327 3328 int var; 3329 int funcWithContext(string) { return var; } 3330 auto funcDel = &funcWithContext; 3331 3332 static assert( is(ToFunctionType!(SymbolType!funcWithContext) == 3333 SymbolType!funcWithContext)); 3334 static assert( is(ToFunctionType!(SymbolType!funcDel) == 3335 SymbolType!funcWithContext)); 3336 static assert( is(SymbolType!funcWithContext == function)); 3337 static assert(!is(SymbolType!funcDel == function)); 3338 static assert( is(SymbolType!funcDel == delegate)); 3339 static assert( is(ToFunctionType!(SymbolType!funcDel) == function)); 3340 3341 static @property int prop() { return 0; } 3342 static assert( is(SymbolType!prop == function)); 3343 static assert(!is(SymbolType!prop == delegate)); 3344 static assert( is(SymbolType!prop == return)); 3345 static assert( is(SymbolType!prop == 3346 ToFunctionType!(int function() @property @safe pure 3347 nothrow @nogc))); 3348 static assert( is(ToFunctionType!(SymbolType!prop) == SymbolType!prop)); 3349 3350 // This is an example of why SymbolType should be used rather than typeof 3351 // when using ToFunctionType (or getting the type of any symbol which might 3352 // be a function when you want the actual type of the symbol and don't want 3353 // to end up with its return type instead). 3354 static assert( is(typeof(prop) == int)); 3355 static assert(!is(typeof(prop) == function)); 3356 static assert(!__traits(compiles, ToFunctionType!(typeof(prop)))); 3357 3358 auto propPtr = ∝ 3359 static assert(!is(typeof(propPtr) == function)); 3360 static assert(!is(SymbolType!propPtr == function)); 3361 static assert( isFunctionPointer!(typeof(propPtr))); 3362 static assert( is(ToFunctionType!(SymbolType!propPtr) == function)); 3363 3364 static assert( is(SymbolType!propPtr == 3365 int function() @property @safe pure nothrow @nogc)); 3366 static assert(!is(ToFunctionType!(SymbolType!propPtr) == 3367 int function() @property @safe pure nothrow @nogc)); 3368 static assert( is(ToFunctionType!(SymbolType!propPtr) == 3369 ToFunctionType!(int function() @property @safe pure 3370 nothrow @nogc))); 3371 3372 @property void propWithContext(int i) { var += i; } 3373 static assert( is(SymbolType!propWithContext == function)); 3374 static assert( is(SymbolType!propWithContext == 3375 ToFunctionType!(void function(int) @property @safe pure 3376 nothrow @nogc))); 3377 static assert( is(ToFunctionType!(SymbolType!propWithContext) == 3378 SymbolType!propWithContext)); 3379 3380 // typeof fails to compile with setter properties, complaining about there 3381 // not being enough arguments, because it's treating the function as an 3382 // expression - and since such an expression would call the function, the 3383 // expression isn't valid if there aren't enough function arguments. 3384 static assert(!__traits(compiles, typeof(propWithContext))); 3385 3386 auto propDel = &propWithContext; 3387 static assert(!is(SymbolType!propDel == function)); 3388 static assert( is(SymbolType!propDel == delegate)); 3389 static assert( is(SymbolType!propDel == return)); 3390 static assert( is(ToFunctionType!(SymbolType!propDel) == function)); 3391 static assert( is(ToFunctionType!(SymbolType!propDel) == 3392 SymbolType!propWithContext)); 3393 3394 static assert( is(SymbolType!propDel == 3395 void delegate(int) @property @safe pure nothrow @nogc)); 3396 static assert(!is(ToFunctionType!(SymbolType!propDel) == 3397 void delegate(int) @property @safe pure nothrow @nogc)); 3398 static assert(!is(ToFunctionType!(SymbolType!propDel) == 3399 void function(int) @property @safe pure nothrow @nogc)); 3400 static assert( is(ToFunctionType!(SymbolType!propDel) == 3401 ToFunctionType!(void function(int) @property @safe pure 3402 nothrow @nogc))); 3403 3404 // Delegates have a funcptr property and a ptr property (which can only be 3405 // used in @system code) which give the pointer to the function and the 3406 // pointer to the context respectively. 3407 static assert( is(ToFunctionType!(SymbolType!propDel) == 3408 typeof(*SymbolType!propDel.funcptr))); 3409 static assert( is(typeof(SymbolType!propDel.ptr) == void*)); 3410 3411 static struct S 3412 { 3413 string foo(int); 3414 string bar(int, int); 3415 @property void prop(string); 3416 } 3417 3418 static assert( is(ToFunctionType!(SymbolType!(S.foo)) == 3419 ToFunctionType!(string function(int)))); 3420 static assert( is(ToFunctionType!(SymbolType!(S.bar)) == 3421 ToFunctionType!(string function(int, int)))); 3422 static assert( is(ToFunctionType!(SymbolType!(S.prop)) == 3423 ToFunctionType!(void function(string) @property))); 3424 } 3425 3426 @safe unittest 3427 { 3428 // Unfortunately, in this case, we get linker errors when taking the address 3429 // of the functions if we avoid inference by not giving function bodies. 3430 // So if we don't want to list all of those attributes in the tests, we have 3431 // to stop the inference in another way. 3432 static int var; 3433 static void killAttributes() @system { ++var; throw new Exception("message"); } 3434 3435 static struct S 3436 { 3437 int func1() { killAttributes(); return 0; } 3438 void func2(int) { killAttributes(); } 3439 3440 static int func3() { killAttributes(); return 0; } 3441 static void func4(int) { killAttributes(); } 3442 3443 @property int func5() { killAttributes(); return 0; } 3444 @property void func6(int) { killAttributes(); } 3445 } 3446 3447 static assert( is(SymbolType!(S.func1) == ToFunctionType!(int function()))); 3448 static assert( is(SymbolType!(S.func2) == ToFunctionType!(void function(int)))); 3449 static assert( is(SymbolType!(S.func3) == ToFunctionType!(int function()))); 3450 static assert( is(SymbolType!(S.func4) == ToFunctionType!(void function(int)))); 3451 static assert( is(SymbolType!(S.func5) == ToFunctionType!(int function() @property))); 3452 static assert( is(SymbolType!(S.func6) == ToFunctionType!(void function(int) @property))); 3453 3454 static assert( is(ToFunctionType!(SymbolType!(S.func1)) == ToFunctionType!(int function()))); 3455 static assert( is(ToFunctionType!(SymbolType!(S.func2)) == ToFunctionType!(void function(int)))); 3456 static assert( is(ToFunctionType!(SymbolType!(S.func3)) == ToFunctionType!(int function()))); 3457 static assert( is(ToFunctionType!(SymbolType!(S.func4)) == ToFunctionType!(void function(int)))); 3458 static assert( is(ToFunctionType!(SymbolType!(S.func5)) == ToFunctionType!(int function() @property))); 3459 static assert( is(ToFunctionType!(SymbolType!(S.func6)) == 3460 ToFunctionType!(void function(int) @property))); 3461 3462 auto ptr1 = &S.init.func1; 3463 auto ptr2 = &S.init.func2; 3464 auto ptr3 = &S.func3; 3465 auto ptr4 = &S.func4; 3466 auto ptr5 = &S.init.func5; 3467 auto ptr6 = &S.init.func6; 3468 3469 // For better or worse, static member functions can be accessed through 3470 // instance of the type as well as through the type. 3471 auto ptr3Instance = &S.init.func3; 3472 auto ptr4Instance = &S.init.func4; 3473 3474 static assert( is(SymbolType!ptr1 == int delegate())); 3475 static assert( is(SymbolType!ptr2 == void delegate(int))); 3476 static assert( is(SymbolType!ptr3 == int function())); 3477 static assert( is(SymbolType!ptr4 == void function(int))); 3478 static assert( is(SymbolType!ptr5 == int delegate() @property)); 3479 static assert( is(SymbolType!ptr6 == void delegate(int) @property)); 3480 3481 static assert( is(SymbolType!ptr3Instance == int function())); 3482 static assert( is(SymbolType!ptr4Instance == void function(int))); 3483 3484 static assert( is(ToFunctionType!(SymbolType!ptr1) == ToFunctionType!(int function()))); 3485 static assert( is(ToFunctionType!(SymbolType!ptr2) == ToFunctionType!(void function(int)))); 3486 static assert( is(ToFunctionType!(SymbolType!ptr3) == ToFunctionType!(int function()))); 3487 static assert( is(ToFunctionType!(SymbolType!ptr4) == ToFunctionType!(void function(int)))); 3488 static assert( is(ToFunctionType!(SymbolType!ptr5) == ToFunctionType!(int function() @property))); 3489 static assert( is(ToFunctionType!(SymbolType!ptr6) == ToFunctionType!(void function(int) @property))); 3490 3491 static assert( is(ToFunctionType!(SymbolType!ptr3Instance) == ToFunctionType!(int function()))); 3492 static assert( is(ToFunctionType!(SymbolType!ptr4Instance) == ToFunctionType!(void function(int)))); 3493 } 3494 3495 /++ 3496 Evaluates to an $(D AliasSeq) of the names (as $(D string)s) of the member 3497 variables of an aggregate type (i.e. a struct, class, interface, or union). 3498 3499 These are fields which take up memory space within an instance of the type 3500 (i.e. not enums / manifest constants, since they don't take up memory 3501 space, and not static member variables, since they don't take up memory 3502 space within an instance). 3503 3504 Hidden fields (like the virtual function table pointer or the context 3505 pointer for nested types) are not included. 3506 3507 For classes, only the direct member variables are included and not those 3508 of any base classes. 3509 3510 For interfaces, the result of FieldNames is always empty, because 3511 interfaces cannot have member variables. However, because interfaces are 3512 aggregate types, they work with FieldNames for consistency so that code 3513 that's written to work on aggregate types doesn't have to worry about 3514 whether it's dealing with an interface. 3515 3516 See_Also: 3517 $(LREF FieldSymbols) 3518 $(LREF FieldTypes) 3519 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 3520 +/ 3521 template FieldNames(T) 3522 if (isAggregateType!T) 3523 { 3524 import phobos.sys.meta : AliasSeq; 3525 3526 static if (is(T == struct) && __traits(isNested, T)) 3527 private alias Fields = AliasSeq!(T.tupleof[0 .. $ - 1]); 3528 else 3529 private alias Fields = T.tupleof; 3530 3531 alias FieldNames = AliasSeq!(); 3532 static foreach (Field; Fields) 3533 FieldNames = AliasSeq!(FieldNames, Field.stringof); 3534 } 3535 3536 /// 3537 @safe unittest 3538 { 3539 import phobos.sys.meta : AliasSeq; 3540 3541 struct S 3542 { 3543 int x; 3544 float y; 3545 } 3546 static assert(FieldNames!S == AliasSeq!("x", "y")); 3547 3548 // Since the AliasSeq contains values, all of which are of the same type, 3549 // it can be used to create a dynamic array, which would be more 3550 // efficient than operating on an AliasSeq in the cases where an 3551 // AliasSeq is not necessary. 3552 static assert([FieldNames!S] == ["x", "y"]); 3553 3554 class C 3555 { 3556 // static variables are not included. 3557 static int var; 3558 3559 // Manifest constants are not included. 3560 enum lang = "dlang"; 3561 3562 // Functions are not included, even if they're @property functions. 3563 @property int foo() { return 42; } 3564 3565 string s; 3566 int i; 3567 int[] arr; 3568 } 3569 static assert(FieldNames!C == AliasSeq!("s", "i", "arr")); 3570 3571 static assert([FieldNames!C] == ["s", "i", "arr"]); 3572 3573 // Only direct member variables are included. Member variables from any base 3574 // classes are not. 3575 class D : C 3576 { 3577 real r; 3578 } 3579 static assert(FieldNames!D == AliasSeq!"r"); 3580 3581 static assert([FieldNames!D] == ["r"]); 3582 3583 // FieldNames will always be empty for an interface, since it's not legal 3584 // for interfaces to have member variables. 3585 interface I 3586 { 3587 } 3588 static assert(FieldNames!I.length == 0); 3589 3590 union U 3591 { 3592 int i; 3593 double d; 3594 long l; 3595 S s; 3596 } 3597 static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s")); 3598 3599 static assert([FieldNames!U] == ["i", "d", "l", "s"]);; 3600 3601 // FieldNames only operates on aggregate types. 3602 static assert(!__traits(compiles, FieldNames!int)); 3603 static assert(!__traits(compiles, FieldNames!(S*))); 3604 static assert(!__traits(compiles, FieldNames!(C[]))); 3605 } 3606 3607 @safe unittest 3608 { 3609 import phobos.sys.meta : AliasSeq; 3610 3611 { 3612 static struct S0 {} 3613 static assert(FieldNames!S0.length == 0); 3614 3615 static struct S1 { int a; } 3616 static assert(FieldNames!S1 == AliasSeq!"a"); 3617 3618 static struct S2 { int a; string b; } 3619 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 3620 3621 static struct S3 { int a; string b; real c; } 3622 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 3623 } 3624 { 3625 int i; 3626 struct S0 { void foo() { i = 0; }} 3627 static assert(FieldNames!S0.length == 0); 3628 static assert(__traits(isNested, S0)); 3629 3630 struct S1 { int a; void foo() { i = 0; } } 3631 static assert(FieldNames!S1 == AliasSeq!"a"); 3632 static assert(__traits(isNested, S1)); 3633 3634 struct S2 { int a; string b; void foo() { i = 0; } } 3635 static assert(FieldNames!S2 == AliasSeq!("a", "b")); 3636 static assert(__traits(isNested, S2)); 3637 3638 struct S3 { int a; string b; real c; void foo() { i = 0; } } 3639 static assert(FieldNames!S3 == AliasSeq!("a", "b", "c")); 3640 static assert(__traits(isNested, S3)); 3641 } 3642 { 3643 static class C0 {} 3644 static assert(FieldNames!C0.length == 0); 3645 3646 static class C1 { int a; } 3647 static assert(FieldNames!C1 == AliasSeq!"a"); 3648 3649 static class C2 { int a; string b; } 3650 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 3651 3652 static class C3 { int a; string b; real c; } 3653 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 3654 3655 static class D0 : C3 {} 3656 static assert(FieldNames!D0.length == 0); 3657 3658 static class D1 : C3 { bool x; } 3659 static assert(FieldNames!D1 == AliasSeq!"x"); 3660 3661 static class D2 : C3 { bool x; int* y; } 3662 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 3663 3664 static class D3 : C3 { bool x; int* y; short[] z; } 3665 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 3666 } 3667 { 3668 int i; 3669 class C0 { void foo() { i = 0; }} 3670 static assert(FieldNames!C0.length == 0); 3671 static assert(__traits(isNested, C0)); 3672 3673 class C1 { int a; void foo() { i = 0; } } 3674 static assert(FieldNames!C1 == AliasSeq!"a"); 3675 static assert(__traits(isNested, C1)); 3676 3677 class C2 { int a; string b; void foo() { i = 0; } } 3678 static assert(FieldNames!C2 == AliasSeq!("a", "b")); 3679 static assert(__traits(isNested, C2)); 3680 3681 class C3 { int a; string b; real c; void foo() { i = 0; } } 3682 static assert(FieldNames!C3 == AliasSeq!("a", "b", "c")); 3683 static assert(__traits(isNested, C3)); 3684 3685 class D0 : C3 {} 3686 static assert(FieldNames!D0.length == 0); 3687 static assert(__traits(isNested, D0)); 3688 3689 class D1 : C3 { bool x; } 3690 static assert(FieldNames!D1 == AliasSeq!"x"); 3691 static assert(__traits(isNested, D1)); 3692 3693 class D2 : C3 { bool x; int* y; } 3694 static assert(FieldNames!D2 == AliasSeq!("x", "y")); 3695 static assert(__traits(isNested, D2)); 3696 3697 class D3 : C3 { bool x; int* y; short[] z; } 3698 static assert(FieldNames!D3 == AliasSeq!("x", "y", "z")); 3699 static assert(__traits(isNested, D3)); 3700 } 3701 { 3702 static union U0 {} 3703 static assert(FieldNames!U0.length == 0); 3704 3705 static union U1 { int a; } 3706 static assert(FieldNames!U1 == AliasSeq!"a"); 3707 3708 static union U2 { int a; string b; } 3709 static assert(FieldNames!U2 == AliasSeq!("a", "b")); 3710 3711 static union U3 { int a; string b; real c; } 3712 static assert(FieldNames!U3 == AliasSeq!("a", "b", "c")); 3713 } 3714 { 3715 static struct S 3716 { 3717 enum e = 42; 3718 static str = "foobar"; 3719 3720 string name() { return "foo"; } 3721 3722 int[] arr; 3723 3724 struct Inner1 { int i; } 3725 3726 static struct Inner2 { long gnol; } 3727 3728 union { int a; string b; } 3729 3730 alias Foo = Inner1; 3731 } 3732 3733 static assert(FieldNames!S == AliasSeq!("arr", "a", "b")); 3734 static assert(FieldNames!(const S) == AliasSeq!("arr", "a", "b")); 3735 static assert(FieldNames!(S.Inner1) == AliasSeq!"i"); 3736 static assert(FieldNames!(S.Inner2) == AliasSeq!"gnol"); 3737 } 3738 } 3739 3740 /++ 3741 Evaluates to an $(D AliasSeq) of the symbols for the member variables of an 3742 aggregate type (i.e. a struct, class, interface, or union). 3743 3744 These are fields which take up memory space within an instance of the type 3745 (i.e. not enums / manifest constants, since they don't take up memory 3746 space, and not static member variables, since they don't take up memory 3747 space within an instance). 3748 3749 Hidden fields (like the virtual function table pointer or the context 3750 pointer for nested types) are not included. 3751 3752 For classes, only the direct member variables are included and not those 3753 of any base classes. 3754 3755 For interfaces, the result of FieldSymbols is always empty, because 3756 interfaces cannot have member variables. However, because interfaces are 3757 aggregate types, they work with FieldSymbols for consistency so that code 3758 that's written to work on aggregate types doesn't have to worry about 3759 whether it's dealing with an interface. 3760 3761 In most cases, $(D FieldSymbols!T) has the same result as $(D T.tupleof). 3762 The difference is that for nested structs with a context pointer, 3763 $(D T.tupleof) includes the context pointer, whereas $(D FieldSymbols!T) 3764 does not. For non-nested structs, and for classes, interfaces, and unions, 3765 $(D FieldSymbols!T) and $(D T.tupleof) are the same. 3766 3767 So, for most cases, $(D T.tupleof) is sufficient and avoids instantiating 3768 an additional template, but FieldSymbols is provided so that the code that 3769 needs to avoid including context pointers in the list of fields can do so 3770 without the programmer having to figure how to do that correctly. It also 3771 provides a template that's equivalent to what $(LREF FieldNames) and 3772 $(LREF FieldTypes) do in terms of which fields it gives (the difference of 3773 course then being whether you get the symbols, names, or types for the 3774 fields), whereas the behavior for $(D tupleof) is subtly different. 3775 3776 See_Also: 3777 $(LREF FieldNames) 3778 $(LREF FieldTypes) 3779 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 3780 $(DDSUBLINK spec/traits, isNested, $(D __traits(isNested, ...))). 3781 $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, ...))). 3782 +/ 3783 template FieldSymbols(T) 3784 if (isAggregateType!T) 3785 { 3786 static if (is(T == struct) && __traits(isNested, T)) 3787 { 3788 import phobos.sys.meta : AliasSeq; 3789 alias FieldSymbols = AliasSeq!(T.tupleof[0 .. $ - 1]); 3790 } 3791 else 3792 alias FieldSymbols = T.tupleof; 3793 } 3794 3795 /// 3796 @safe unittest 3797 { 3798 import phobos.sys.meta : AliasSeq; 3799 3800 struct S 3801 { 3802 int x; 3803 float y; 3804 } 3805 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.x, S.y))); 3806 3807 // FieldSymbols!S and S.tupleof are the same, because S is not nested. 3808 static assert(__traits(isSame, FieldSymbols!S, S.tupleof)); 3809 3810 // Note that type qualifiers _should_ be passed on to the result, but due 3811 // to https://issues.dlang.org/show_bug.cgi?id=24516, they aren't. 3812 // FieldTypes does not have this problem, because it aliases the types 3813 // rather than the symbols, so if you need the types from the symbols, you 3814 // should use either FieldTypes or tupleof until the compiler bug has been 3815 // fixed (and if you use tupleof, you need to avoid aliasing the result 3816 // before getting the types from it). 3817 static assert(is(typeof(FieldSymbols!S[0]) == int)); 3818 3819 // These currently fail when they shouldn't: 3820 //static assert(is(typeof(FieldSymbols!(const S)[0]) == const int)); 3821 //static assert(is(typeof(FieldSymbols!(shared S)[0]) == shared int)); 3822 3823 class C 3824 { 3825 // static variables are not included. 3826 static int var; 3827 3828 // Manifest constants are not included. 3829 enum lang = "dlang"; 3830 3831 // Functions are not included, even if they're @property functions. 3832 @property int foo() { return 42; } 3833 3834 string s; 3835 int i; 3836 int[] arr; 3837 } 3838 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.s, C.i, C.arr))); 3839 3840 // FieldSymbols!C and C.tupleof have the same symbols, because they are 3841 // always the same for classes. 3842 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 3843 3844 // Only direct member variables are included. Member variables from any base 3845 // classes are not. 3846 class D : C 3847 { 3848 real r; 3849 } 3850 static assert(__traits(isSame, FieldSymbols!D, AliasSeq!(D.r))); 3851 static assert(__traits(isSame, FieldSymbols!D, D.tupleof)); 3852 3853 // FieldSymbols will always be empty for an interface, since it's not legal 3854 // for interfaces to have member variables. 3855 interface I 3856 { 3857 } 3858 static assert(FieldSymbols!I.length == 0); 3859 static assert(I.tupleof.length == 0); 3860 3861 union U 3862 { 3863 int i; 3864 double d; 3865 long l; 3866 S s; 3867 } 3868 static assert(__traits(isSame, FieldSymbols!U, AliasSeq!(U.i, U.d, U.l, U.s))); 3869 3870 // FieldSymbols!C and C.tupleof have the same symbols, because they are 3871 // always the same for unions. 3872 static assert(__traits(isSame, FieldSymbols!U, U.tupleof)); 3873 3874 // FieldSymbols only operates on aggregate types. 3875 static assert(!__traits(compiles, FieldSymbols!int)); 3876 static assert(!__traits(compiles, FieldSymbols!(S*))); 3877 static assert(!__traits(compiles, FieldSymbols!(C[]))); 3878 } 3879 3880 /// Some examples with nested types. 3881 @safe unittest 3882 { 3883 import phobos.sys.meta : AliasSeq; 3884 3885 int outside; 3886 3887 struct S 3888 { 3889 long l; 3890 string s; 3891 3892 void foo() { outside = 2; } 3893 } 3894 static assert(__traits(isNested, S)); 3895 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.l, S.s))); 3896 3897 // FieldSymbols!S and S.tupleof are not the same, because S is nested, and 3898 // the context pointer to the outer scope is included in S.tupleof, whereas 3899 // it is excluded from FieldSymbols!S. 3900 static assert(__traits(isSame, S.tupleof[0 .. $ - 1], AliasSeq!(S.l, S.s))); 3901 static assert(S.tupleof[$ - 1].stringof == "this"); 3902 3903 class C 3904 { 3905 bool b; 3906 int* ptr; 3907 3908 void foo() { outside = 7; } 3909 } 3910 static assert(__traits(isNested, C)); 3911 static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.b, C.ptr))); 3912 3913 // FieldSymbols!C and C.tupleof have the same symbols, because they are 3914 // always the same for classes. No context pointer is provided as part of 3915 // tupleof for nested classes. 3916 static assert(__traits(isSame, FieldSymbols!C, C.tupleof)); 3917 3918 // __traits(isNested, ...) is never true for interfaces or unions, since 3919 // they cannot have a context pointer to an outer scope. So, tupleof and 3920 // FieldSymbols will always be the same for interfaces and unions. 3921 } 3922 3923 @safe unittest 3924 { 3925 import phobos.sys.meta : AliasSeq; 3926 3927 { 3928 static struct S0 {} 3929 static assert(FieldSymbols!S0.length == 0); 3930 3931 static struct S1 { int a; } 3932 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 3933 3934 static struct S2 { int a; string b; } 3935 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 3936 3937 static struct S3 { int a; string b; real c; } 3938 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 3939 } 3940 { 3941 int i; 3942 struct S0 { void foo() { i = 0; }} 3943 static assert(FieldSymbols!S0.length == 0); 3944 static assert(__traits(isNested, S0)); 3945 3946 struct S1 { int a; void foo() { i = 0; } } 3947 static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a))); 3948 static assert(__traits(isNested, S1)); 3949 3950 struct S2 { int a; string b; void foo() { i = 0; } } 3951 static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b))); 3952 static assert(__traits(isNested, S2)); 3953 3954 struct S3 { int a; string b; real c; void foo() { i = 0; } } 3955 static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c))); 3956 static assert(__traits(isNested, S3)); 3957 } 3958 { 3959 static class C0 {} 3960 static assert(FieldSymbols!C0.length == 0); 3961 3962 static class C1 { int a; } 3963 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 3964 3965 static class C2 { int a; string b; } 3966 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 3967 3968 static class C3 { int a; string b; real c; } 3969 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 3970 3971 static class D0 : C3 {} 3972 static assert(FieldSymbols!D0.length == 0); 3973 3974 static class D1 : C3 { bool x; } 3975 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 3976 3977 static class D2 : C3 { bool x; int* y; } 3978 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 3979 3980 static class D3 : C3 { bool x; int* y; short[] z; } 3981 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 3982 } 3983 { 3984 int i; 3985 class C0 { void foo() { i = 0; }} 3986 static assert(FieldSymbols!C0.length == 0); 3987 static assert(__traits(isNested, C0)); 3988 3989 class C1 { int a; void foo() { i = 0; } } 3990 static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a))); 3991 static assert(__traits(isNested, C1)); 3992 3993 class C2 { int a; string b; void foo() { i = 0; } } 3994 static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b))); 3995 static assert(__traits(isNested, C2)); 3996 3997 class C3 { int a; string b; real c; void foo() { i = 0; } } 3998 static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c))); 3999 static assert(__traits(isNested, C3)); 4000 4001 class D0 : C3 {} 4002 static assert(FieldSymbols!D0.length == 0); 4003 static assert(__traits(isNested, D0)); 4004 4005 class D1 : C3 { bool x; } 4006 static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x))); 4007 static assert(__traits(isNested, D1)); 4008 4009 class D2 : C3 { bool x; int* y; } 4010 static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y))); 4011 static assert(__traits(isNested, D2)); 4012 4013 class D3 : C3 { bool x; int* y; short[] z; } 4014 static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z))); 4015 static assert(__traits(isNested, D3)); 4016 } 4017 { 4018 static union U0 {} 4019 static assert(FieldSymbols!U0.length == 0); 4020 4021 static union U1 { int a; } 4022 static assert(__traits(isSame, FieldSymbols!U1, AliasSeq!(U1.a))); 4023 4024 static union U2 { int a; string b; } 4025 static assert(__traits(isSame, FieldSymbols!U2, AliasSeq!(U2.a, U2.b))); 4026 4027 static union U3 { int a; string b; real c; } 4028 static assert(__traits(isSame, FieldSymbols!U3, AliasSeq!(U3.a, U3.b, U3.c))); 4029 } 4030 { 4031 static struct S 4032 { 4033 enum e = 42; 4034 static str = "foobar"; 4035 4036 string name() { return "foo"; } 4037 4038 int[] arr; 4039 4040 struct Inner1 { int i; } 4041 4042 static struct Inner2 { long gnol; } 4043 4044 union { int a; string b; } 4045 4046 alias Foo = Inner1; 4047 } 4048 4049 static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.arr, S.a, S.b))); 4050 static assert(__traits(isSame, FieldSymbols!(const S), AliasSeq!(S.arr, S.a, S.b))); 4051 static assert(__traits(isSame, FieldSymbols!(S.Inner1), AliasSeq!(S.Inner1.i))); 4052 static assert(__traits(isSame, FieldSymbols!(S.Inner2), AliasSeq!(S.Inner2.gnol))); 4053 } 4054 } 4055 4056 /++ 4057 Evaluates to an $(D AliasSeq) of the types of the member variables of an 4058 aggregate type (i.e. a struct, class, interface, or union). 4059 4060 These are fields which take up memory space within an instance of the type 4061 (i.e. not enums / manifest constants, since they don't take up memory 4062 space, and not static member variables, since they don't take up memory 4063 space within an instance). 4064 4065 Hidden fields (like the virtual function table pointer or the context 4066 pointer for nested types) are not included. 4067 4068 For classes, only the direct member variables are included and not those 4069 of any base classes. 4070 4071 For interfaces, the result of FieldTypes is always empty, because 4072 interfaces cannot have member variables. However, because interfaces are 4073 aggregate types, they work with FieldTypes for consistency so that code 4074 that's written to work on aggregate types doesn't have to worry about 4075 whether it's dealing with an interface. 4076 4077 See_Also: 4078 $(LREF FieldNames) 4079 $(LREF FieldSymbols) 4080 $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof)) 4081 +/ 4082 template FieldTypes(T) 4083 if (isAggregateType!T) 4084 { 4085 static if (is(T == struct) && __traits(isNested, T)) 4086 alias FieldTypes = typeof(T.tupleof[0 .. $ - 1]); 4087 else 4088 alias FieldTypes = typeof(T.tupleof); 4089 } 4090 4091 /// 4092 @safe unittest 4093 { 4094 import phobos.sys.meta : AliasSeq; 4095 4096 struct S 4097 { 4098 int x; 4099 float y; 4100 } 4101 static assert(is(FieldTypes!S == AliasSeq!(int, float))); 4102 4103 // Type qualifers will be passed on to the result. 4104 static assert(is(FieldTypes!(const S) == AliasSeq!(const int, const float))); 4105 static assert(is(FieldTypes!(shared S) == AliasSeq!(shared int, shared float))); 4106 4107 class C 4108 { 4109 // static variables are not included. 4110 static int var; 4111 4112 // Manifest constants are not included. 4113 enum lang = "dlang"; 4114 4115 // Functions are not included, even if they're @property functions. 4116 @property int foo() { return 42; } 4117 4118 string s; 4119 int i; 4120 int[] arr; 4121 } 4122 static assert(is(FieldTypes!C == AliasSeq!(string, int, int[]))); 4123 4124 // Only direct member variables are included. Member variables from any base 4125 // classes are not. 4126 class D : C 4127 { 4128 real r; 4129 } 4130 static assert(is(FieldTypes!D == AliasSeq!real)); 4131 4132 // FieldTypes will always be empty for an interface, since it's not legal 4133 // for interfaces to have member variables. 4134 interface I 4135 { 4136 } 4137 static assert(FieldTypes!I.length == 0); 4138 4139 union U 4140 { 4141 int i; 4142 double d; 4143 long l; 4144 S s; 4145 } 4146 static assert(is(FieldTypes!U == AliasSeq!(int, double, long, S))); 4147 4148 // FieldTypes only operates on aggregate types. 4149 static assert(!__traits(compiles, FieldTypes!int)); 4150 static assert(!__traits(compiles, FieldTypes!(S*))); 4151 static assert(!__traits(compiles, FieldTypes!(C[]))); 4152 } 4153 4154 @safe unittest 4155 { 4156 import phobos.sys.meta : AliasSeq; 4157 4158 { 4159 static struct S0 {} 4160 static assert(FieldTypes!S0.length == 0); 4161 4162 static struct S1 { int a; } 4163 static assert(is(FieldTypes!S1 == AliasSeq!int)); 4164 4165 static struct S2 { int a; string b; } 4166 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 4167 4168 static struct S3 { int a; string b; real c; } 4169 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 4170 } 4171 { 4172 int i; 4173 struct S0 { void foo() { i = 0; }} 4174 static assert(FieldTypes!S0.length == 0); 4175 static assert(__traits(isNested, S0)); 4176 4177 struct S1 { int a; void foo() { i = 0; } } 4178 static assert(is(FieldTypes!S1 == AliasSeq!int)); 4179 static assert(__traits(isNested, S1)); 4180 4181 struct S2 { int a; string b; void foo() { i = 0; } } 4182 static assert(is(FieldTypes!S2 == AliasSeq!(int, string))); 4183 static assert(__traits(isNested, S2)); 4184 4185 struct S3 { int a; string b; real c; void foo() { i = 0; } } 4186 static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real))); 4187 static assert(__traits(isNested, S3)); 4188 } 4189 { 4190 static class C0 {} 4191 static assert(FieldTypes!C0.length == 0); 4192 4193 static class C1 { int a; } 4194 static assert(is(FieldTypes!C1 == AliasSeq!int)); 4195 4196 static class C2 { int a; string b; } 4197 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 4198 4199 static class C3 { int a; string b; real c; } 4200 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 4201 4202 static class D0 : C3 {} 4203 static assert(FieldTypes!D0.length == 0); 4204 4205 static class D1 : C3 { bool x; } 4206 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 4207 4208 static class D2 : C3 { bool x; int* y; } 4209 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 4210 4211 static class D3 : C3 { bool x; int* y; short[] z; } 4212 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 4213 } 4214 { 4215 int i; 4216 class C0 { void foo() { i = 0; }} 4217 static assert(FieldTypes!C0.length == 0); 4218 static assert(__traits(isNested, C0)); 4219 4220 class C1 { int a; void foo() { i = 0; } } 4221 static assert(is(FieldTypes!C1 == AliasSeq!int)); 4222 static assert(__traits(isNested, C1)); 4223 4224 class C2 { int a; string b; void foo() { i = 0; } } 4225 static assert(is(FieldTypes!C2 == AliasSeq!(int, string))); 4226 static assert(__traits(isNested, C2)); 4227 4228 class C3 { int a; string b; real c; void foo() { i = 0; } } 4229 static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real))); 4230 static assert(__traits(isNested, C3)); 4231 4232 class D0 : C3 {} 4233 static assert(FieldTypes!D0.length == 0); 4234 static assert(__traits(isNested, D0)); 4235 4236 class D1 : C3 { bool x; } 4237 static assert(is(FieldTypes!D1 == AliasSeq!bool)); 4238 static assert(__traits(isNested, D1)); 4239 4240 class D2 : C3 { bool x; int* y; } 4241 static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*))); 4242 static assert(__traits(isNested, D2)); 4243 4244 class D3 : C3 { bool x; int* y; short[] z; } 4245 static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[]))); 4246 static assert(__traits(isNested, D3)); 4247 } 4248 { 4249 static union U0 {} 4250 static assert(FieldTypes!U0.length == 0); 4251 4252 static union U1 { int a; } 4253 static assert(is(FieldTypes!U1 == AliasSeq!int)); 4254 4255 static union U2 { int a; string b; } 4256 static assert(is(FieldTypes!U2 == AliasSeq!(int, string))); 4257 4258 static union U3 { int a; string b; real c; } 4259 static assert(is(FieldTypes!U3 == AliasSeq!(int, string, real))); 4260 } 4261 { 4262 static struct S 4263 { 4264 enum e = 42; 4265 static str = "foobar"; 4266 4267 string name() { return "foo"; } 4268 4269 int[] arr; 4270 4271 struct Inner1 { int i; } 4272 4273 static struct Inner2 { long gnol; } 4274 4275 union { int a; string b; } 4276 4277 alias Foo = Inner1; 4278 } 4279 4280 static assert(is(FieldTypes!S == AliasSeq!(int[], int, string))); 4281 static assert(is(FieldTypes!(const S) == AliasSeq!(const(int[]), const int, const string))); 4282 static assert(is(FieldTypes!(S.Inner1) == AliasSeq!int)); 4283 static assert(is(FieldTypes!(S.Inner2) == AliasSeq!long)); 4284 } 4285 } 4286 4287 /++ 4288 Whether assigning to a variable of the given type involves either a 4289 user-defined $(D opAssign) or a compiler-generated $(D opAssign) rather than 4290 using the default assignment behavior (which would use $(D memcpy)). The 4291 $(D opAssign) must accept the same type (with compatible qualifiers) as the 4292 type which the $(D opAssign) is declared on for it to count for 4293 hasComplexAssignment. 4294 4295 The compiler will generate an $(D opAssign) for a struct when a member 4296 variable of that struct defines an $(D opAssign). It will also generate one 4297 when the struct has a postblit constructor or destructor (and those can be 4298 either user-defined or compiler-generated). 4299 4300 However, due to $(BUGZILLA 24834), the compiler does not currently generate 4301 an $(D opAssign) for structs that define a copy constructor, and so 4302 hasComplexAssignment is $(D false) for such types unless they have an 4303 explicit $(D opAssign), or the compiler generates one due to a member 4304 variable having an $(D opAssign). 4305 4306 Note that hasComplexAssignment is also $(D true) for static arrays whose 4307 element type has an $(D opAssign), since while the static array itself does 4308 not have an $(D opAssign), the compiler must use the $(D opAssign) of the 4309 elements when assigning to the static array. 4310 4311 Due to $(BUGZILLA 24833), enums never have complex assignment even if their 4312 base type does. Their $(D opAssign) is never called, resulting in incorrect 4313 behavior for such enums. So, because the compiler does not treat them as 4314 having complex assignment, hasComplexAssignment is $(D false) for them. 4315 4316 No other types (including class references, pointers, and unions) 4317 ever have an $(D opAssign) and thus hasComplexAssignment is never $(D true) 4318 for them. It is particularly important to note that unions never have an 4319 $(D opAssign), so if a struct contains a union which contains one or more 4320 members which have an $(D opAssign), that struct will have to have a 4321 user-defined $(D opAssign) which explicitly assigns to the correct member 4322 of the union if you don't want the current value of the union to simply be 4323 memcopied when assigning to the struct. 4324 4325 One big reason that code would need to worry about hasComplexAssignment is 4326 if void initialization is used anywhere. While it might be okay to assign 4327 to uninitialized memory for a type where assignment does a memcopy, 4328 assigning to uninitialized memory will cause serious issues with any 4329 $(D opAssign) which looks at the object before assigning to it (e.g. 4330 because the type uses reference counting). In such cases, 4331 $(REF copyEmplace, core, sys, lifetime) needs to be used instead of 4332 assignment. 4333 4334 See_Also: 4335 $(LREF hasComplexCopying) 4336 $(LREF hasComplexDestruction) 4337 $(DDSUBLINK spec/operatoroverloading, assignment, 4338 The language spec for overloading assignment) 4339 $(DDSUBLINK spec/struct, assign-overload, 4340 The language spec for $(D opAssign) on structs) 4341 +/ 4342 template hasComplexAssignment(T) 4343 { 4344 import core.internal.traits : hasElaborateAssign; 4345 alias hasComplexAssignment = hasElaborateAssign!T; 4346 } 4347 4348 /// 4349 @safe unittest 4350 { 4351 static assert(!hasComplexAssignment!int); 4352 static assert(!hasComplexAssignment!real); 4353 static assert(!hasComplexAssignment!string); 4354 static assert(!hasComplexAssignment!(int[])); 4355 static assert(!hasComplexAssignment!(int[42])); 4356 static assert(!hasComplexAssignment!(int[string])); 4357 static assert(!hasComplexAssignment!Object); 4358 4359 static struct NoOpAssign 4360 { 4361 int i; 4362 } 4363 static assert(!hasComplexAssignment!NoOpAssign); 4364 4365 // For complex assignment, the parameter type must match the type of the 4366 // struct (with compatible qualifiers), but refness does not matter (though 4367 // it will obviously affect whether rvalues will be accepted as well as 4368 // whether non-copyable types will be accepted). 4369 static struct HasOpAssign 4370 { 4371 void opAssign(HasOpAssign) {} 4372 } 4373 static assert( hasComplexAssignment!HasOpAssign); 4374 static assert(!hasComplexAssignment!(const(HasOpAssign))); 4375 4376 static struct HasOpAssignRef 4377 { 4378 void opAssign(ref HasOpAssignRef) {} 4379 } 4380 static assert( hasComplexAssignment!HasOpAssignRef); 4381 static assert(!hasComplexAssignment!(const(HasOpAssignRef))); 4382 4383 static struct HasOpAssignAutoRef 4384 { 4385 void opAssign()(auto ref HasOpAssignAutoRef) {} 4386 } 4387 static assert( hasComplexAssignment!HasOpAssignAutoRef); 4388 static assert(!hasComplexAssignment!(const(HasOpAssignAutoRef))); 4389 4390 // Assigning a mutable value works when opAssign takes const, because 4391 // mutable implicitly converts to const, but assigning to a const variable 4392 // does not work, so normally, a const object is not considered to have 4393 // complex assignment. 4394 static struct HasOpAssignC 4395 { 4396 void opAssign(const HasOpAssignC) {} 4397 } 4398 static assert( hasComplexAssignment!HasOpAssignC); 4399 static assert(!hasComplexAssignment!(const(HasOpAssignC))); 4400 4401 // If opAssign is const, then assigning to a const variable will work, and a 4402 // const object will have complex assignment. However, such a type would 4403 // not normally make sense, since it can't actually be mutated by opAssign. 4404 static struct HasConstOpAssignC 4405 { 4406 void opAssign(const HasConstOpAssignC) const {} 4407 } 4408 static assert( hasComplexAssignment!HasConstOpAssignC); 4409 static assert( hasComplexAssignment!(const(HasConstOpAssignC))); 4410 4411 // For a type to have complex assignment, the types must match aside from 4412 // the qualifiers. So, an opAssign which takes another type does not count 4413 // as complex assignment. 4414 static struct OtherOpAssign 4415 { 4416 void opAssign(int) {} 4417 } 4418 static assert(!hasComplexAssignment!OtherOpAssign); 4419 4420 // The return type doesn't matter for complex assignment, though normally, 4421 // opAssign should either return a reference to the this reference (so that 4422 // assignments can be chained) or void. 4423 static struct HasOpAssignWeirdRet 4424 { 4425 int opAssign(HasOpAssignWeirdRet) { return 42; } 4426 } 4427 static assert( hasComplexAssignment!HasOpAssignWeirdRet); 4428 4429 // The compiler will generate an assignment operator if a member variable 4430 // has one. 4431 static struct HasMemberWithOpAssign 4432 { 4433 HasOpAssign s; 4434 } 4435 static assert( hasComplexAssignment!HasMemberWithOpAssign); 4436 4437 // The compiler will generate an assignment operator if the type has a 4438 // postblit constructor or a destructor. 4439 static struct HasDtor 4440 { 4441 ~this() {} 4442 } 4443 static assert( hasComplexAssignment!HasDtor); 4444 4445 // If a struct has @disabled opAssign (and thus assigning to a variable of 4446 // that type will result in a compilation error), then 4447 // hasComplexAssignment is false. 4448 // Code that wants to check whether assignment works will need to test that 4449 // assigning to a variable of that type compiles (which could need to test 4450 // both an lvalue and an rvalue depending on the exact sort of assignment 4451 // the code is actually going to do). 4452 static struct DisabledOpAssign 4453 { 4454 @disable void opAssign(DisabledOpAssign); 4455 } 4456 static assert(!hasComplexAssignment!DisabledOpAssign); 4457 static assert(!__traits(compiles, { DisabledOpAssign s; 4458 s = rvalueOf!DisabledOpAssign; 4459 s = lvalueOf!DisabledOpAssign; })); 4460 static assert(!is(typeof({ DisabledOpAssign s; 4461 s = rvalueOf!DisabledOpAssign; 4462 s = lvalueOf!DisabledOpAssign; }))); 4463 4464 // Static arrays have complex assignment if their elements do. 4465 static assert( hasComplexAssignment!(HasOpAssign[1])); 4466 4467 // Static arrays with no elements do not have complex assignment, because 4468 // there's nothing to assign to. 4469 static assert(!hasComplexAssignment!(HasOpAssign[0])); 4470 4471 // Dynamic arrays do not have complex assignment, because assigning to them 4472 // just slices them rather than assigning to their elements. Assigning to 4473 // an array with a slice operation - e.g. arr[0 .. 5] = other[0 .. 5]; - 4474 // does use opAssign if the elements have it, but since assigning to the 4475 // array itself does not, hasComplexAssignment is false for dynamic arrays. 4476 static assert(!hasComplexAssignment!(HasOpAssign[])); 4477 4478 // Classes and unions do not have complex assignment even if they have 4479 // members which do. 4480 class C 4481 { 4482 HasOpAssign s; 4483 } 4484 static assert(!hasComplexAssignment!C); 4485 4486 union U 4487 { 4488 HasOpAssign s; 4489 } 4490 static assert(!hasComplexAssignment!U); 4491 4492 // https://issues.dlang.org/show_bug.cgi?id=24833 4493 // This static assertion fails, because the compiler 4494 // currently ignores assignment operators for enum types. 4495 enum E : HasOpAssign { a = HasOpAssign.init } 4496 //static assert( hasComplexAssignment!E); 4497 } 4498 4499 @safe unittest 4500 { 4501 import phobos.sys.meta : AliasSeq; 4502 4503 { 4504 struct S1 { int i; } 4505 struct S2 { real r; } 4506 struct S3 { string s; } 4507 struct S4 { int[] arr; } 4508 struct S5 { int[0] arr; } 4509 struct S6 { int[42] arr; } 4510 struct S7 { int[string] aa; } 4511 4512 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 4513 { 4514 static assert(!hasComplexAssignment!T); 4515 static assert(!hasComplexAssignment!(T[0])); 4516 static assert(!hasComplexAssignment!(T[42])); 4517 static assert(!hasComplexAssignment!(T[])); 4518 } 4519 } 4520 4521 // Basic variations of opAssign. 4522 { 4523 static struct S { void opAssign(S) {} } 4524 static assert( hasComplexAssignment!S); 4525 4526 static struct S2 { S s; } 4527 static assert( hasComplexAssignment!S2); 4528 } 4529 { 4530 static struct S { void opAssign(ref S) {} } 4531 static assert( hasComplexAssignment!S); 4532 4533 static struct S2 { S s; } 4534 static assert( hasComplexAssignment!S2); 4535 } 4536 { 4537 static struct S { void opAssign()(auto ref S) {} } 4538 static assert( hasComplexAssignment!S); 4539 4540 static struct S2 { S s; } 4541 static assert( hasComplexAssignment!S2); 4542 } 4543 { 4544 static struct S { ref opAssign(S) { return this; } } 4545 static assert( hasComplexAssignment!S); 4546 4547 static struct S2 { S s; } 4548 static assert( hasComplexAssignment!S2); 4549 } 4550 { 4551 static struct S { ref opAssign(ref S) { return this; } } 4552 static assert( hasComplexAssignment!S); 4553 4554 static struct S2 { S s; } 4555 static assert( hasComplexAssignment!S2); 4556 } 4557 { 4558 static struct S { ref opAssign()(auto ref S) { return this; } } 4559 static assert( hasComplexAssignment!S); 4560 4561 static struct S2 { S s; } 4562 static assert( hasComplexAssignment!S2); 4563 } 4564 { 4565 static struct S { ref opAssign(T)(auto ref T) { return this; } } 4566 static assert( hasComplexAssignment!S); 4567 4568 static struct S2 { S s; } 4569 static assert( hasComplexAssignment!S2); 4570 } 4571 4572 // Non-complex opAssign. 4573 { 4574 static struct S { ref opAssign(int) { return this; } } 4575 static assert(!hasComplexAssignment!S); 4576 4577 static struct S2 { S s; } 4578 static assert(!hasComplexAssignment!S2); 4579 } 4580 { 4581 struct Other {} 4582 static struct S { ref opAssign(Other) { return this; } } 4583 static assert(!hasComplexAssignment!S); 4584 4585 static struct S2 { S s; } 4586 static assert(!hasComplexAssignment!S2); 4587 } 4588 4589 // Multiple opAssigns. 4590 { 4591 static struct S 4592 { 4593 void opAssign(S) {} 4594 void opAssign(int) {} 4595 } 4596 static assert( hasComplexAssignment!S); 4597 4598 static struct S2 { S s; } 4599 static assert( hasComplexAssignment!S2); 4600 } 4601 { 4602 // This just flips the order of the previous test to catch potential 4603 // bugs related to the order of declaration, since that's occasionally 4604 // popped up in the compiler in other contexts. 4605 static struct S 4606 { 4607 void opAssign(int) {} 4608 void opAssign(S) {} 4609 } 4610 static assert( hasComplexAssignment!S); 4611 4612 static struct S2 { S s; } 4613 static assert( hasComplexAssignment!S2); 4614 } 4615 { 4616 static struct S 4617 { 4618 void opAssign(S) {} 4619 void opAssign(ref S) {} 4620 void opAssign(const ref S) {} 4621 } 4622 static assert( hasComplexAssignment!S); 4623 4624 static struct S2 { S s; } 4625 static assert( hasComplexAssignment!S2); 4626 } 4627 4628 // Make sure that @disabled alternate opAssigns don't cause issues. 4629 { 4630 static struct S 4631 { 4632 void opAssign(S) {} 4633 @disable void opAssign(ref S) {} 4634 } 4635 static assert( hasComplexAssignment!S); 4636 4637 // See https://issues.dlang.org/show_bug.cgi?id=24854 4638 // The compiler won't generate any opAssign (even if it theoretically 4639 // can) if the member variable has an @disabled opAssign which counts as 4640 // complex assignment. 4641 static struct S2 { S s; } 4642 static assert(!hasComplexAssignment!S2); 4643 } 4644 { 4645 static struct S 4646 { 4647 void opAssign(T)(T) {} 4648 @disable void opAssign(T)(ref T) {} 4649 } 4650 static assert( hasComplexAssignment!S); 4651 4652 static struct S2 { S s; } 4653 static assert(!hasComplexAssignment!S2); 4654 } 4655 { 4656 static struct S 4657 { 4658 @disable void opAssign(S) {} 4659 void opAssign(ref S) {} 4660 } 4661 static assert( hasComplexAssignment!S); 4662 4663 static struct S2 { S s; } 4664 static assert(!hasComplexAssignment!S2); 4665 } 4666 { 4667 static struct S 4668 { 4669 @disable void opAssign(T)(T) {} 4670 void opAssign(T)(ref T) {} 4671 } 4672 static assert( hasComplexAssignment!S); 4673 4674 static struct S2 { S s; } 4675 static assert(!hasComplexAssignment!S2); 4676 } 4677 { 4678 static struct S 4679 { 4680 void opAssign(S) {} 4681 @disable void opAssign(int) {} 4682 } 4683 static assert( hasComplexAssignment!S); 4684 4685 static struct S2 { S s; } 4686 static assert( hasComplexAssignment!S2); 4687 } 4688 { 4689 // The same as the previous test but in reverse order just to catch 4690 // compiler bugs related to the order of declaration. 4691 static struct S 4692 { 4693 @disable void opAssign(int) {} 4694 void opAssign(S) {} 4695 } 4696 static assert( hasComplexAssignment!S); 4697 4698 static struct S2 { S s; } 4699 static assert( hasComplexAssignment!S2); 4700 } 4701 4702 // Generated opAssign due to other functions. 4703 { 4704 static struct S { this(this) {} } 4705 static assert( hasComplexAssignment!S); 4706 4707 static struct S2 { S s; } 4708 static assert( hasComplexAssignment!S2); 4709 } 4710 // https://issues.dlang.org/show_bug.cgi?id=24834 4711 /+ 4712 { 4713 static struct S { this(ref S) {} } 4714 static assert( hasComplexAssignment!S); 4715 4716 static struct S2 { S s; } 4717 static assert( hasComplexAssignment!S2); 4718 } 4719 +/ 4720 { 4721 static struct S { ~this() {} } 4722 static assert( hasComplexAssignment!S); 4723 4724 static struct S2 { S s; } 4725 static assert( hasComplexAssignment!S2); 4726 } 4727 4728 { 4729 static struct S 4730 { 4731 this(this) {} 4732 @disable void opAssign()(auto ref S) {} 4733 } 4734 static assert(!hasComplexAssignment!S); 4735 4736 static struct S2 { S s; } 4737 static assert(!hasComplexAssignment!S2); 4738 } 4739 { 4740 static struct S 4741 { 4742 this(this) {} 4743 void opAssign()(auto ref S) {} 4744 @disable void opAssign(int) {} 4745 } 4746 static assert( hasComplexAssignment!S); 4747 4748 static struct S2 { S s; } 4749 static assert( hasComplexAssignment!S2); 4750 } 4751 4752 // Static arrays 4753 { 4754 static struct S { void opAssign(S) {} } 4755 static assert( hasComplexAssignment!S); 4756 4757 static assert(!hasComplexAssignment!(S[0])); 4758 static assert( hasComplexAssignment!(S[12])); 4759 static assert(!hasComplexAssignment!(S[])); 4760 4761 static struct S2 { S[42] s; } 4762 static assert( hasComplexAssignment!S2); 4763 } 4764 } 4765 4766 /++ 4767 Whether copying an object of the given type involves either a user-defined 4768 copy / postblit constructor or a compiler-generated copy / postblit 4769 constructor rather than using the default copying behavior (which would use 4770 $(D memcpy)). 4771 4772 The compiler will generate a copy / postblit constructor for a struct when 4773 a member variable of that struct defines a copy / postblit constructor. 4774 4775 Note that hasComplexCopying is also $(D true) for static arrays whose 4776 element type has a copy constructor or postblit constructor, since while 4777 the static array itself does not have a copy constructor or postblit 4778 constructor, the compiler must use the copy / postblit constructor of the 4779 elements when copying the static array. 4780 4781 Due to $(BUGZILLA 24833), enums never have complex copying even if their 4782 base type does. Their copy / postblit constructor is never called, 4783 resulting in incorrect behavior for such enums. So, because the compiler 4784 does not treat them as having complex copying, hasComplexCopying is 4785 $(D false) for them. 4786 4787 No other types (including class references, pointers, and unions) ever have 4788 a copy constructor or postblit constructor and thus hasComplexCopying is 4789 never $(D true) for them. It is particularly important to note that unions 4790 never have a copy constructor or postblit constructor, so if a struct 4791 contains a union which contains one or more members which have a copy 4792 constructor or postblit constructor, that struct will have to have a 4793 user-defined copy constructor or posthblit constructor which explicitly 4794 copies the correct member of the union if you don't want the current value 4795 of the union to simply be memcopied when copying the struct. 4796 4797 If a particular piece of code cares about the existence of a copy 4798 constructor or postblit constructor specifically rather than if a type has 4799 one or the other, the traits 4800 $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T))) 4801 and 4802 $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) can 4803 be used, though note that they will not be true for static arrays. 4804 4805 See_Also: 4806 $(LREF hasComplexAssignment) 4807 $(LREF hasComplexDestruction) 4808 $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T))) 4809 $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) 4810 $(DDSUBLINK spec/traits, isCopyable, $(D __traits(isCopyable, T))) 4811 $(DDSUBLINK spec/structs, struct-copy-constructor, The language spec for copy constructors) 4812 $(DDSUBLINK spec/structs, struct-postblit, The language spec for postblit constructors) 4813 +/ 4814 template hasComplexCopying(T) 4815 { 4816 import core.internal.traits : hasElaborateCopyConstructor; 4817 alias hasComplexCopying = hasElaborateCopyConstructor!T; 4818 } 4819 4820 /// 4821 @safe unittest 4822 { 4823 static assert(!hasComplexCopying!int); 4824 static assert(!hasComplexCopying!real); 4825 static assert(!hasComplexCopying!string); 4826 static assert(!hasComplexCopying!(int[])); 4827 static assert(!hasComplexCopying!(int[42])); 4828 static assert(!hasComplexCopying!(int[string])); 4829 static assert(!hasComplexCopying!Object); 4830 4831 static struct NoCopyCtor1 4832 { 4833 int i; 4834 } 4835 static assert(!hasComplexCopying!NoCopyCtor1); 4836 static assert(!__traits(hasCopyConstructor, NoCopyCtor1)); 4837 static assert(!__traits(hasPostblit, NoCopyCtor1)); 4838 4839 static struct NoCopyCtor2 4840 { 4841 int i; 4842 4843 this(int i) 4844 { 4845 this.i = i; 4846 } 4847 } 4848 static assert(!hasComplexCopying!NoCopyCtor2); 4849 static assert(!__traits(hasCopyConstructor, NoCopyCtor2)); 4850 static assert(!__traits(hasPostblit, NoCopyCtor2)); 4851 4852 struct HasCopyCtor 4853 { 4854 this(ref HasCopyCtor) 4855 { 4856 } 4857 } 4858 static assert( hasComplexCopying!HasCopyCtor); 4859 static assert( __traits(hasCopyConstructor, HasCopyCtor)); 4860 static assert(!__traits(hasPostblit, HasCopyCtor)); 4861 4862 // hasComplexCopying does not take constness into account. 4863 // Code that wants to check whether copying works will need to test 4864 // __traits(isCopyable, T) or test that copying compiles. 4865 static assert( hasComplexCopying!(const HasCopyCtor)); 4866 static assert( __traits(hasCopyConstructor, const HasCopyCtor)); 4867 static assert(!__traits(hasPostblit, const HasCopyCtor)); 4868 static assert(!__traits(isCopyable, const HasCopyCtor)); 4869 static assert(!__traits(compiles, { const HasCopyCtor h; 4870 auto h2 = h; })); 4871 static assert(!is(typeof({ const HasCopyCtor h1; 4872 auto h2 = h1; }))); 4873 4874 // An rvalue constructor is not a copy constructor. 4875 struct HasRValueCtor 4876 { 4877 this(HasRValueCtor) 4878 { 4879 } 4880 } 4881 static assert(!hasComplexCopying!HasRValueCtor); 4882 static assert(!__traits(hasCopyConstructor, HasRValueCtor)); 4883 static assert(!__traits(hasPostblit, HasRValueCtor)); 4884 4885 struct HasPostblit 4886 { 4887 this(this) 4888 { 4889 } 4890 } 4891 static assert( hasComplexCopying!HasPostblit); 4892 static assert(!__traits(hasCopyConstructor, HasPostblit)); 4893 static assert( __traits(hasPostblit, HasPostblit)); 4894 4895 // The compiler will generate a copy constructor if a member variable 4896 // has one. 4897 static struct HasMemberWithCopyCtor 4898 { 4899 HasCopyCtor s; 4900 } 4901 static assert( hasComplexCopying!HasMemberWithCopyCtor); 4902 4903 // The compiler will generate a postblit constructor if a member variable 4904 // has one. 4905 static struct HasMemberWithPostblit 4906 { 4907 HasPostblit s; 4908 } 4909 static assert( hasComplexCopying!HasMemberWithPostblit); 4910 4911 // If a struct has @disabled copying, hasComplexCopying is still true. 4912 // Code that wants to check whether copying works will need to test 4913 // __traits(isCopyable, T) or test that copying compiles. 4914 static struct DisabledCopying 4915 { 4916 @disable this(this); 4917 @disable this(ref DisabledCopying); 4918 } 4919 static assert( hasComplexCopying!DisabledCopying); 4920 static assert(!__traits(isCopyable, DisabledCopying)); 4921 static assert(!__traits(compiles, { DisabledCopying dc1; 4922 auto dc2 = dc1; })); 4923 static assert(!is(typeof({ DisabledCopying dc1; 4924 auto dc2 = dc1; }))); 4925 4926 // Static arrays have complex copying if their elements do. 4927 static assert( hasComplexCopying!(HasCopyCtor[1])); 4928 static assert( hasComplexCopying!(HasPostblit[1])); 4929 4930 // Static arrays with no elements do not have complex copying, because 4931 // there's nothing to copy. 4932 static assert(!hasComplexCopying!(HasCopyCtor[0])); 4933 static assert(!hasComplexCopying!(HasPostblit[0])); 4934 4935 // Dynamic arrays do not have complex copying, because copying them 4936 // just slices them rather than copying their elements. 4937 static assert(!hasComplexCopying!(HasCopyCtor[])); 4938 static assert(!hasComplexCopying!(HasPostblit[])); 4939 4940 // Classes and unions do not have complex copying even if they have 4941 // members which do. 4942 class C 4943 { 4944 HasCopyCtor s; 4945 } 4946 static assert(!hasComplexCopying!C); 4947 4948 union U 4949 { 4950 HasCopyCtor s; 4951 } 4952 static assert(!hasComplexCopying!U); 4953 4954 // https://issues.dlang.org/show_bug.cgi?id=24833 4955 // This static assertion fails, because the compiler 4956 // currently ignores assignment operators for enum types. 4957 enum E : HasCopyCtor { a = HasCopyCtor.init } 4958 //static assert( hasComplexCopying!E); 4959 } 4960 4961 @safe unittest 4962 { 4963 import phobos.sys.meta : AliasSeq; 4964 4965 { 4966 struct S1 { int i; } 4967 struct S2 { real r; } 4968 struct S3 { string s; } 4969 struct S4 { int[] arr; } 4970 struct S5 { int[0] arr; } 4971 struct S6 { int[42] arr; } 4972 struct S7 { int[string] aa; } 4973 4974 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 4975 { 4976 static assert(!hasComplexCopying!T); 4977 static assert(!hasComplexCopying!(T[0])); 4978 static assert(!hasComplexCopying!(T[42])); 4979 static assert(!hasComplexCopying!(T[])); 4980 } 4981 } 4982 4983 // Basic variations of copy constructors. 4984 { 4985 static struct S { this(ref S) {} } 4986 static assert( hasComplexCopying!S); 4987 4988 static struct S2 { S s; } 4989 static assert( hasComplexCopying!S2); 4990 } 4991 { 4992 static struct S { this(const ref S) const {} } 4993 static assert( hasComplexCopying!S); 4994 4995 static struct S2 { S s; } 4996 static assert( hasComplexCopying!S2); 4997 } 4998 { 4999 static struct S 5000 { 5001 this(ref S) {} 5002 this(const ref S) const {} 5003 } 5004 static assert( hasComplexCopying!S); 5005 5006 static struct S2 { S s; } 5007 static assert( hasComplexCopying!S2); 5008 } 5009 { 5010 static struct S { this(inout ref S) inout {} } 5011 static assert( hasComplexCopying!S); 5012 5013 static struct S2 { S s; } 5014 static assert( hasComplexCopying!S2); 5015 } 5016 { 5017 static struct S { this(scope ref S) {} } 5018 static assert( hasComplexCopying!S); 5019 5020 static struct S2 { S s; } 5021 static assert( hasComplexCopying!S2); 5022 } 5023 { 5024 static struct S { this(scope ref S) scope {} } 5025 static assert( hasComplexCopying!S); 5026 5027 static struct S2 { S s; } 5028 static assert( hasComplexCopying!S2); 5029 } 5030 { 5031 static struct S { this(ref S) @safe {} } 5032 static assert( hasComplexCopying!S); 5033 5034 static struct S2 { S s; } 5035 static assert( hasComplexCopying!S2); 5036 } 5037 { 5038 static struct S { this(ref S) nothrow {} } 5039 static assert( hasComplexCopying!S); 5040 5041 static struct S2 { S s; } 5042 static assert( hasComplexCopying!S2); 5043 } 5044 { 5045 static struct S { this(scope inout ref S) inout scope @safe pure nothrow @nogc {} } 5046 static assert( hasComplexCopying!S); 5047 5048 static struct S2 { S s; } 5049 static assert( hasComplexCopying!S2); 5050 } 5051 5052 // Basic variations of postblit constructors. 5053 { 5054 static struct S { this(this) {} } 5055 static assert( hasComplexCopying!S); 5056 5057 static struct S2 { S s; } 5058 static assert( hasComplexCopying!S2); 5059 } 5060 { 5061 static struct S { this(this) scope @safe pure nothrow @nogc {} } 5062 static assert( hasComplexCopying!S); 5063 5064 static struct S2 { S s; } 5065 static assert( hasComplexCopying!S2); 5066 } 5067 5068 // Rvalue constructors. 5069 { 5070 static struct S { this(S) {} } 5071 static assert(!hasComplexCopying!S); 5072 5073 static struct S2 { S s; } 5074 static assert(!hasComplexCopying!S2); 5075 } 5076 { 5077 static struct S { this(const S) const {} } 5078 static assert(!hasComplexCopying!S); 5079 5080 static struct S2 { S s; } 5081 static assert(!hasComplexCopying!S2); 5082 } 5083 { 5084 static struct S 5085 { 5086 this(S) {} 5087 this(const S) const {} 5088 } 5089 static assert(!hasComplexCopying!S); 5090 5091 static struct S2 { S s; } 5092 static assert(!hasComplexCopying!S2); 5093 } 5094 { 5095 static struct S { this(inout S) inout {} } 5096 static assert(!hasComplexCopying!S); 5097 5098 static struct S2 { S s; } 5099 static assert(!hasComplexCopying!S2); 5100 } 5101 { 5102 static struct S { this(S) @safe {} } 5103 static assert(!hasComplexCopying!S); 5104 5105 static struct S2 { S s; } 5106 static assert(!hasComplexCopying!S2); 5107 } 5108 { 5109 static struct S { this(S) nothrow {} } 5110 static assert(!hasComplexCopying!S); 5111 5112 static struct S2 { S s; } 5113 static assert(!hasComplexCopying!S2); 5114 } 5115 { 5116 static struct S { this(inout S) inout @safe pure nothrow @nogc {} } 5117 static assert(!hasComplexCopying!S); 5118 5119 static struct S2 { S s; } 5120 static assert(!hasComplexCopying!S2); 5121 } 5122 5123 // @disabled copy constructors. 5124 { 5125 static struct S { @disable this(ref S) {} } 5126 static assert( hasComplexCopying!S); 5127 5128 static struct S2 { S s; } 5129 static assert( hasComplexCopying!S2); 5130 } 5131 { 5132 static struct S { @disable this(const ref S) const {} } 5133 static assert( hasComplexCopying!S); 5134 5135 static struct S2 { S s; } 5136 static assert( hasComplexCopying!S2); 5137 } 5138 { 5139 static struct S 5140 { 5141 @disable this(ref S) {} 5142 this(const ref S) const {} 5143 } 5144 static assert( hasComplexCopying!S); 5145 5146 static struct S2 { S s; } 5147 static assert( hasComplexCopying!S2); 5148 } 5149 { 5150 static struct S 5151 { 5152 this(ref S) {} 5153 @disable this(const ref S) const {} 5154 } 5155 static assert( hasComplexCopying!S); 5156 5157 static struct S2 { S s; } 5158 static assert( hasComplexCopying!S2); 5159 } 5160 { 5161 static struct S 5162 { 5163 @disable this(ref S) {} 5164 @disable this(const ref S) const {} 5165 } 5166 static assert( hasComplexCopying!S); 5167 5168 static struct S2 { S s; } 5169 static assert( hasComplexCopying!S2); 5170 } 5171 5172 // Static arrays 5173 { 5174 static struct S { this(ref S) {} } 5175 static assert( hasComplexCopying!S); 5176 5177 static assert(!hasComplexCopying!(S[0])); 5178 static assert( hasComplexCopying!(S[12])); 5179 static assert(!hasComplexCopying!(S[])); 5180 5181 static struct S2 { S[42] s; } 5182 static assert( hasComplexCopying!S2); 5183 } 5184 { 5185 static struct S { this(this) {} } 5186 static assert( hasComplexCopying!S); 5187 5188 static assert(!hasComplexCopying!(S[0])); 5189 static assert( hasComplexCopying!(S[12])); 5190 static assert(!hasComplexCopying!(S[])); 5191 5192 static struct S2 { S[42] s; } 5193 static assert( hasComplexCopying!S2); 5194 } 5195 } 5196 5197 /++ 5198 Whether the given type has either a user-defined destructor or a 5199 compiler-generated destructor. 5200 5201 The compiler will generate a destructor for a struct when a member variable 5202 of that struct defines a destructor. 5203 5204 Note that hasComplexDestruction is also $(D true) for static arrays whose 5205 element type has a destructor, since while the static array itself does not 5206 have a destructor, the compiler must use the destructor of the elements 5207 when destroying the static array. 5208 5209 Due to $(BUGZILLA 24833), enums never have complex destruction even if their 5210 base type does. Their destructor is never called, resulting in incorrect 5211 behavior for such enums. So, because the compiler does not treat them as 5212 having complex destruction, hasComplexDestruction is $(D false) for them. 5213 5214 Note that while the $(DDSUBLINK spec/class, destructors, language spec) 5215 currently refers to $(D ~this()) on classes as destructors (whereas the 5216 runtime refers to them as finalizers, and they're arguably finalizers 5217 rather than destructors given how they work), classes are not considered to 5218 have complex destruction. Under normal circumstances, it's just the GC or 5219 $(REF1 destroy, object) which calls the destructor / finalizer on a class 5220 (and it's not guaranteed that a class destructor / finalizer will even ever 5221 be called), which is in stark contrast to structs, which normally live on 5222 the stack and need to be destroyed when they leave scope. So, 5223 hasComplexDestruction is concerned with whether that type will have a 5224 destructor that's run when it leaves scope and not with what happens when 5225 the GC destroys an object prior to freeing its memory. 5226 5227 No other types (including pointers and unions) ever have a destructor and 5228 thus hasComplexDestruction is never $(D true) for them. It is particularly 5229 important to note that unions never have a destructor, so if a struct 5230 contains a union which contains one or more members which have a 5231 destructor, that struct will have to have a user-defined destructor which 5232 explicitly calls $(REF1 destroy, object) on the correct member of the 5233 union if you want the object in question to be destroyed properly. 5234 5235 See_Also: 5236 $(LREF hasComplexAssignment) 5237 $(LREF hasComplexCopying) 5238 $(REF destroy, object) 5239 $(DDSUBLINK spec/structs, struct-destructor, The language spec for destructors) 5240 $(DDSUBLINK spec/class, destructors, The language spec for class finalizers) 5241 +/ 5242 template hasComplexDestruction(T) 5243 { 5244 import core.internal.traits : hasElaborateDestructor; 5245 alias hasComplexDestruction = hasElaborateDestructor!T; 5246 } 5247 5248 /// 5249 @safe unittest 5250 { 5251 static assert(!hasComplexDestruction!int); 5252 static assert(!hasComplexDestruction!real); 5253 static assert(!hasComplexDestruction!string); 5254 static assert(!hasComplexDestruction!(int[])); 5255 static assert(!hasComplexDestruction!(int[42])); 5256 static assert(!hasComplexDestruction!(int[string])); 5257 static assert(!hasComplexDestruction!Object); 5258 5259 static struct NoDtor 5260 { 5261 int i; 5262 } 5263 static assert(!hasComplexDestruction!NoDtor); 5264 5265 struct HasDtor 5266 { 5267 ~this() {} 5268 } 5269 static assert( hasComplexDestruction!HasDtor); 5270 5271 // The compiler will generate a destructor if a member variable has one. 5272 static struct HasMemberWithDtor 5273 { 5274 HasDtor s; 5275 } 5276 static assert( hasComplexDestruction!HasMemberWithDtor); 5277 5278 // If a struct has @disabled destruction, hasComplexDestruction is still 5279 // true. Code that wants to check whether destruction works can either 5280 // test for whether the __xdtor member is disabled, or it can test whether 5281 // code that will destroy the object compiles. That being said, a disabled 5282 // destructor probably isn't very common in practice, because about all that 5283 // such a type is good for is being allocated on the heap. 5284 static struct DisabledDtor 5285 { 5286 @disable ~this() {} 5287 } 5288 static assert( hasComplexDestruction!DisabledDtor); 5289 static assert( __traits(isDisabled, 5290 __traits(getMember, DisabledDtor, "__xdtor"))); 5291 5292 // A type with a disabled destructor cannot be created on the stack or used 5293 // in any way that would ever trigger a destructor, making it pretty much 5294 // useless outside of providing a way to force a struct to be allocated on 5295 // the heap - though that could be useful in some situations, since it 5296 // it makes it possible to have a type that has to be a reference type but 5297 // which doesn't have the overhead of a class. 5298 static assert(!__traits(compiles, { DisabledDtor d; })); 5299 static assert( __traits(compiles, { auto d = new DisabledDtor; })); 5300 5301 // Static arrays have complex destruction if their elements do. 5302 static assert( hasComplexDestruction!(HasDtor[1])); 5303 5304 // Static arrays with no elements do not have complex destruction, because 5305 // there's nothing to destroy. 5306 static assert(!hasComplexDestruction!(HasDtor[0])); 5307 5308 // Dynamic arrays do not have complex destruction, because their elements 5309 // are contained in the memory that the dynamic array is a slice of and not 5310 // in the dynamic array itself, so there's nothing to destroy when a 5311 // dynamic array leaves scope. 5312 static assert(!hasComplexDestruction!(HasDtor[])); 5313 5314 // Classes and unions do not have complex copying even if they have 5315 // members which do. 5316 class C 5317 { 5318 HasDtor s; 5319 } 5320 static assert(!hasComplexDestruction!C); 5321 5322 union U 5323 { 5324 HasDtor s; 5325 } 5326 static assert(!hasComplexDestruction!U); 5327 5328 // https://issues.dlang.org/show_bug.cgi?id=24833 5329 // This static assertion fails, because the compiler 5330 // currently ignores assignment operators for enum types. 5331 enum E : HasDtor { a = HasDtor.init } 5332 //static assert( hasComplexDestruction!E); 5333 } 5334 5335 @safe unittest 5336 { 5337 import phobos.sys.meta : AliasSeq; 5338 5339 { 5340 struct S1 { int i; } 5341 struct S2 { real r; } 5342 struct S3 { string s; } 5343 struct S4 { int[] arr; } 5344 struct S5 { int[0] arr; } 5345 struct S6 { int[42] arr; } 5346 struct S7 { int[string] aa; } 5347 5348 static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7)) 5349 { 5350 static assert(!hasComplexDestruction!T); 5351 static assert(!hasComplexDestruction!(T[0])); 5352 static assert(!hasComplexDestruction!(T[42])); 5353 static assert(!hasComplexDestruction!(T[])); 5354 } 5355 } 5356 5357 // Basic variations of destructors. 5358 { 5359 static struct S { ~this() {} } 5360 static assert( hasComplexDestruction!S); 5361 5362 static struct S2 { S s; } 5363 static assert( hasComplexDestruction!S2); 5364 } 5365 { 5366 static struct S { ~this() const {} } 5367 static assert( hasComplexDestruction!S); 5368 5369 static struct S2 { S s; } 5370 static assert( hasComplexDestruction!S2); 5371 } 5372 { 5373 static struct S { ~this() @safe {} } 5374 static assert( hasComplexDestruction!S); 5375 5376 static struct S2 { S s; } 5377 static assert( hasComplexDestruction!S2); 5378 } 5379 { 5380 static struct S { ~this() @safe pure nothrow @nogc {} } 5381 static assert( hasComplexDestruction!S); 5382 5383 static struct S2 { S s; } 5384 static assert( hasComplexDestruction!S2); 5385 } 5386 5387 // @disabled destructors. 5388 { 5389 static struct S { @disable ~this() {} } 5390 static assert( __traits(isDisabled, 5391 __traits(getMember, S, "__xdtor"))); 5392 5393 static struct S2 { S s; } 5394 static assert( hasComplexDestruction!S2); 5395 static assert( __traits(isDisabled, 5396 __traits(getMember, S2, "__xdtor"))); 5397 } 5398 5399 // Static arrays 5400 { 5401 static struct S { ~this() {} } 5402 static assert( hasComplexDestruction!S); 5403 5404 static assert(!hasComplexDestruction!(S[0])); 5405 static assert( hasComplexDestruction!(S[12])); 5406 static assert(!hasComplexDestruction!(S[])); 5407 5408 static struct S2 { S[42] s; } 5409 static assert( hasComplexDestruction!S2); 5410 } 5411 } 5412 5413 /++ 5414 Evaluates to $(D true) if the given type is one or more of the following, 5415 or if it's a struct, union, or static array which contains one or more of 5416 the following: 5417 5418 $(OL $(LI A raw pointer) 5419 $(LI A class reference) 5420 $(LI An interface reference) 5421 $(LI A dynamic array) 5422 $(LI An associative array) 5423 $(LI A delegate) 5424 $(LI A struct with a 5425 $(DDSUBLINK spec/traits, isNested, $(D context pointer)).)) 5426 5427 Note that function pointers are not considered to have indirections, because 5428 they do not point to any data (whereas a delegate has a context pointer 5429 and therefore has data that it points to). 5430 5431 Also, while static arrays do not have indirections unless their element 5432 type has indirections, static arrays with an element type of $(D void) are 5433 considered to have indirections by hasIndirections, because it's unknown 5434 what type their elements actually are, so they $(I might) have 5435 indirections, and thus, the conservative approach is to assume that they do 5436 have indirections. 5437 5438 Static arrays with length 0 do not have indirections no matter what their 5439 element type is, since they don't actually have any elements. 5440 +/ 5441 version (StdDdoc) template hasIndirections(T) 5442 { 5443 import core.internal.traits : _hasIndirections = hasIndirections; 5444 alias hasIndirections = _hasIndirections!T; 5445 } 5446 else 5447 { 5448 import core.internal.traits : _hasIndirections = hasIndirections; 5449 alias hasIndirections = _hasIndirections; 5450 } 5451 5452 /// 5453 @safe unittest 5454 { 5455 static class C {} 5456 static interface I {} 5457 5458 static assert( hasIndirections!(int*)); 5459 static assert( hasIndirections!C); 5460 static assert( hasIndirections!I); 5461 static assert( hasIndirections!(int[])); 5462 static assert( hasIndirections!(int[string])); 5463 static assert( hasIndirections!(void delegate())); 5464 static assert( hasIndirections!(string delegate(int))); 5465 5466 static assert(!hasIndirections!(void function())); 5467 static assert(!hasIndirections!int); 5468 5469 static assert(!hasIndirections!(ubyte[9])); 5470 static assert( hasIndirections!(ubyte[9]*)); 5471 static assert( hasIndirections!(ubyte*[9])); 5472 static assert(!hasIndirections!(ubyte*[0])); 5473 static assert( hasIndirections!(ubyte[])); 5474 5475 static assert( hasIndirections!(void[])); 5476 static assert( hasIndirections!(void[42])); 5477 5478 static struct NoContext 5479 { 5480 int i; 5481 } 5482 5483 int local; 5484 5485 struct HasContext 5486 { 5487 int foo() { return local; } 5488 } 5489 5490 struct HasMembersWithIndirections 5491 { 5492 int* ptr; 5493 } 5494 5495 static assert(!hasIndirections!NoContext); 5496 static assert( hasIndirections!HasContext); 5497 static assert( hasIndirections!HasMembersWithIndirections); 5498 5499 union U1 5500 { 5501 int i; 5502 float f; 5503 } 5504 static assert(!hasIndirections!U1); 5505 5506 union U2 5507 { 5508 int i; 5509 int[] arr; 5510 } 5511 static assert( hasIndirections!U2); 5512 } 5513 5514 // hasIndirections with types which aren't aggregate types. 5515 @safe unittest 5516 { 5517 import phobos.sys.meta : AliasSeq; 5518 5519 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 5520 5521 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 5522 float, double, real, char, wchar, dchar, int function(string), void)) 5523 { 5524 mixin testWithQualifiers!(T, false); 5525 mixin testWithQualifiers!(T*, true); 5526 mixin testWithQualifiers!(T[], true); 5527 5528 mixin testWithQualifiers!(T[42], is(T == void)); 5529 mixin testWithQualifiers!(T[0], false); 5530 5531 mixin testWithQualifiers!(T*[42], true); 5532 mixin testWithQualifiers!(T*[0], false); 5533 5534 mixin testWithQualifiers!(T[][42], true); 5535 mixin testWithQualifiers!(T[][0], false); 5536 } 5537 5538 foreach (T; AliasSeq!(int[int], int delegate(string))) 5539 { 5540 mixin testWithQualifiers!(T, true); 5541 mixin testWithQualifiers!(T*, true); 5542 mixin testWithQualifiers!(T[], true); 5543 5544 mixin testWithQualifiers!(T[42], true); 5545 mixin testWithQualifiers!(T[0], false); 5546 5547 mixin testWithQualifiers!(T*[42], true); 5548 mixin testWithQualifiers!(T*[0], false); 5549 5550 mixin testWithQualifiers!(T[][42], true); 5551 mixin testWithQualifiers!(T[][0], false); 5552 } 5553 } 5554 5555 // hasIndirections with structs. 5556 @safe unittest 5557 { 5558 import phobos.sys.meta : AliasSeq; 5559 5560 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 5561 5562 { 5563 struct S {} 5564 mixin testWithQualifiers!(S, false); 5565 } 5566 { 5567 static struct S {} 5568 mixin testWithQualifiers!(S, false); 5569 } 5570 { 5571 struct S { void foo() {} } 5572 mixin testWithQualifiers!(S, true); 5573 } 5574 { 5575 static struct S { void foo() {} } 5576 mixin testWithQualifiers!(S, false); 5577 } 5578 5579 // Structs with members which aren't aggregate types and don't have indirections. 5580 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 5581 float, double, real, char, wchar, dchar, int function(string))) 5582 { 5583 // No indirections. 5584 { 5585 struct S { T member; } 5586 mixin testWithQualifiers!(S, false); 5587 } 5588 { 5589 struct S { const T member; } 5590 mixin testWithQualifiers!(S, false); 5591 } 5592 { 5593 struct S { immutable T member; } 5594 mixin testWithQualifiers!(S, false); 5595 } 5596 { 5597 struct S { shared T member; } 5598 mixin testWithQualifiers!(S, false); 5599 } 5600 5601 { 5602 static struct S { T member; void foo() {} } 5603 mixin testWithQualifiers!(S, false); 5604 } 5605 { 5606 static struct S { const T member; void foo() {} } 5607 mixin testWithQualifiers!(S, false); 5608 } 5609 { 5610 static struct S { immutable T member; void foo() {} } 5611 mixin testWithQualifiers!(S, false); 5612 } 5613 { 5614 static struct S { shared T member; void foo() {} } 5615 mixin testWithQualifiers!(S, false); 5616 } 5617 5618 // Has context pointer. 5619 { 5620 struct S { T member; void foo() {} } 5621 mixin testWithQualifiers!(S, true); 5622 } 5623 { 5624 struct S { const T member; void foo() {} } 5625 mixin testWithQualifiers!(S, true); 5626 } 5627 { 5628 struct S { immutable T member; void foo() {} } 5629 mixin testWithQualifiers!(S, true); 5630 } 5631 { 5632 struct S { shared T member; void foo() {} } 5633 mixin testWithQualifiers!(S, true); 5634 } 5635 5636 { 5637 T local; 5638 struct S { void foo() { auto v = local; } } 5639 mixin testWithQualifiers!(S, true); 5640 } 5641 { 5642 const T local; 5643 struct S { void foo() { auto v = local; } } 5644 mixin testWithQualifiers!(S, true); 5645 } 5646 { 5647 immutable T local; 5648 struct S { void foo() { auto v = local; } } 5649 mixin testWithQualifiers!(S, true); 5650 } 5651 { 5652 shared T local; 5653 struct S { void foo() @trusted { auto v = cast() local; } } 5654 mixin testWithQualifiers!(S, true); 5655 } 5656 5657 // Pointers. 5658 { 5659 struct S { T* member; } 5660 mixin testWithQualifiers!(S, true); 5661 } 5662 { 5663 struct S { const(T)* member; } 5664 mixin testWithQualifiers!(S, true); 5665 } 5666 { 5667 struct S { const T* member; } 5668 mixin testWithQualifiers!(S, true); 5669 } 5670 { 5671 struct S { immutable T* member; } 5672 mixin testWithQualifiers!(S, true); 5673 } 5674 { 5675 struct S { shared T* member; } 5676 mixin testWithQualifiers!(S, true); 5677 } 5678 5679 // Dynamic arrays. 5680 { 5681 struct S { T[] member; } 5682 mixin testWithQualifiers!(S, true); 5683 } 5684 { 5685 struct S { const(T)[] member; } 5686 mixin testWithQualifiers!(S, true); 5687 } 5688 { 5689 struct S { const T[] member; } 5690 mixin testWithQualifiers!(S, true); 5691 } 5692 { 5693 struct S { immutable T[] member; } 5694 mixin testWithQualifiers!(S, true); 5695 } 5696 { 5697 struct S { shared T[] member; } 5698 mixin testWithQualifiers!(S, true); 5699 } 5700 5701 // Static arrays. 5702 { 5703 struct S { T[1] member; } 5704 mixin testWithQualifiers!(S, false); 5705 } 5706 { 5707 struct S { const(T)[1] member; } 5708 mixin testWithQualifiers!(S, false); 5709 } 5710 { 5711 struct S { const T[1] member; } 5712 mixin testWithQualifiers!(S, false); 5713 } 5714 { 5715 struct S { immutable T[1] member; } 5716 mixin testWithQualifiers!(S, false); 5717 } 5718 { 5719 struct S { shared T[1] member; } 5720 mixin testWithQualifiers!(S, false); 5721 } 5722 5723 // Static arrays of pointers. 5724 { 5725 struct S { T*[1] member; } 5726 mixin testWithQualifiers!(S, true); 5727 } 5728 { 5729 struct S { const(T)*[1] member; } 5730 mixin testWithQualifiers!(S, true); 5731 } 5732 { 5733 struct S { const(T*)[1] member; } 5734 mixin testWithQualifiers!(S, true); 5735 } 5736 { 5737 struct S { const T*[1] member; } 5738 mixin testWithQualifiers!(S, true); 5739 } 5740 { 5741 struct S { immutable T*[1] member; } 5742 mixin testWithQualifiers!(S, true); 5743 } 5744 { 5745 struct S { shared T*[1] member; } 5746 mixin testWithQualifiers!(S, true); 5747 } 5748 5749 { 5750 struct S { T*[0] member; } 5751 mixin testWithQualifiers!(S, false); 5752 } 5753 { 5754 struct S { const(T)*[0] member; } 5755 mixin testWithQualifiers!(S, false); 5756 } 5757 { 5758 struct S { const(T*)[0] member; } 5759 mixin testWithQualifiers!(S, false); 5760 } 5761 { 5762 struct S { const T*[0] member; } 5763 mixin testWithQualifiers!(S, false); 5764 } 5765 { 5766 struct S { immutable T*[0] member; } 5767 mixin testWithQualifiers!(S, false); 5768 } 5769 { 5770 struct S { shared T*[0] member; } 5771 mixin testWithQualifiers!(S, false); 5772 } 5773 5774 // Static arrays of dynamic arrays. 5775 { 5776 struct S { T[][1] member; } 5777 mixin testWithQualifiers!(S, true); 5778 } 5779 { 5780 struct S { const(T)[][1] member; } 5781 mixin testWithQualifiers!(S, true); 5782 } 5783 { 5784 struct S { const(T[])[1] member; } 5785 mixin testWithQualifiers!(S, true); 5786 } 5787 { 5788 struct S { const T[][1] member; } 5789 mixin testWithQualifiers!(S, true); 5790 } 5791 { 5792 struct S { immutable T[][1] member; } 5793 mixin testWithQualifiers!(S, true); 5794 } 5795 { 5796 struct S { shared T[][1] member; } 5797 mixin testWithQualifiers!(S, true); 5798 } 5799 5800 { 5801 struct S { T[][0] member; } 5802 mixin testWithQualifiers!(S, false); 5803 } 5804 { 5805 struct S { const(T)[][0] member; } 5806 mixin testWithQualifiers!(S, false); 5807 } 5808 { 5809 struct S { const(T[])[0] member; } 5810 mixin testWithQualifiers!(S, false); 5811 } 5812 { 5813 struct S { const T[][0] member; } 5814 mixin testWithQualifiers!(S, false); 5815 } 5816 { 5817 struct S { immutable T[][0] member; } 5818 mixin testWithQualifiers!(S, false); 5819 } 5820 { 5821 struct S { shared T[][0] member; } 5822 mixin testWithQualifiers!(S, false); 5823 } 5824 } 5825 5826 // Structs with arrays of void. 5827 { 5828 { 5829 static struct S { void[] member; } 5830 mixin testWithQualifiers!(S, true); 5831 } 5832 { 5833 static struct S { void[1] member; } 5834 mixin testWithQualifiers!(S, true); 5835 } 5836 { 5837 static struct S { void[0] member; } 5838 mixin testWithQualifiers!(S, false); 5839 } 5840 } 5841 5842 // Structs with multiple members, testing pointer types. 5843 { 5844 static struct S { int i; bool b; } 5845 mixin testWithQualifiers!(S, false); 5846 } 5847 { 5848 static struct S { int* i; bool b; } 5849 mixin testWithQualifiers!(S, true); 5850 } 5851 { 5852 static struct S { int i; bool* b; } 5853 mixin testWithQualifiers!(S, true); 5854 } 5855 { 5856 static struct S { int* i; bool* b; } 5857 mixin testWithQualifiers!(S, true); 5858 } 5859 5860 // Structs with multiple members, testing dynamic arrays. 5861 { 5862 static struct S { int[] arr; } 5863 mixin testWithQualifiers!(S, true); 5864 } 5865 { 5866 static struct S { int i; int[] arr; } 5867 mixin testWithQualifiers!(S, true); 5868 } 5869 { 5870 static struct S { int[] arr; int i; } 5871 mixin testWithQualifiers!(S, true); 5872 } 5873 5874 // Structs with multiple members, testing static arrays. 5875 { 5876 static struct S { int[1] arr; } 5877 mixin testWithQualifiers!(S, false); 5878 } 5879 { 5880 static struct S { int i; int[1] arr; } 5881 mixin testWithQualifiers!(S, false); 5882 } 5883 { 5884 static struct S { int[1] arr; int i; } 5885 mixin testWithQualifiers!(S, false); 5886 } 5887 5888 { 5889 static struct S { int*[0] arr; } 5890 mixin testWithQualifiers!(S, false); 5891 } 5892 { 5893 static struct S { int i; int*[0] arr; } 5894 mixin testWithQualifiers!(S, false); 5895 } 5896 { 5897 static struct S { int*[0] arr; int i; } 5898 mixin testWithQualifiers!(S, false); 5899 } 5900 5901 { 5902 static struct S { string[42] arr; } 5903 mixin testWithQualifiers!(S, true); 5904 } 5905 { 5906 static struct S { int i; string[42] arr; } 5907 mixin testWithQualifiers!(S, true); 5908 } 5909 { 5910 static struct S { string[42] arr; int i; } 5911 mixin testWithQualifiers!(S, true); 5912 } 5913 5914 // Structs with associative arrays. 5915 { 5916 static struct S { int[string] aa; } 5917 mixin testWithQualifiers!(S, true); 5918 } 5919 { 5920 static struct S { int i; int[string] aa; } 5921 mixin testWithQualifiers!(S, true); 5922 } 5923 { 5924 static struct S { int[string] aa; int i; } 5925 mixin testWithQualifiers!(S, true); 5926 } 5927 5928 { 5929 static struct S { int[42][int] aa; } 5930 mixin testWithQualifiers!(S, true); 5931 } 5932 { 5933 static struct S { int[0][int] aa; } 5934 mixin testWithQualifiers!(S, true); 5935 } 5936 5937 // Structs with classes. 5938 { 5939 class C {} 5940 struct S { C c; } 5941 mixin testWithQualifiers!(S, true); 5942 } 5943 { 5944 interface I {} 5945 struct S { I i; } 5946 mixin testWithQualifiers!(S, true); 5947 } 5948 5949 // Structs with delegates. 5950 { 5951 struct S { void delegate() d; } 5952 mixin testWithQualifiers!(S, true); 5953 } 5954 { 5955 struct S { int delegate(int) d; } 5956 mixin testWithQualifiers!(S, true); 5957 } 5958 5959 // Structs multiple layers deep. 5960 { 5961 struct S1 { int i; } 5962 struct S2 { S1 s; } 5963 struct S3 { S2 s; } 5964 struct S4 { S3 s; } 5965 struct S5 { S4 s; } 5966 struct S6 { S5 s; } 5967 struct S7 { S6[0] s; } 5968 struct S8 { S7 s; } 5969 struct S9 { S8 s; } 5970 struct S10 { S9 s; } 5971 mixin testWithQualifiers!(S1, false); 5972 mixin testWithQualifiers!(S2, false); 5973 mixin testWithQualifiers!(S3, false); 5974 mixin testWithQualifiers!(S4, false); 5975 mixin testWithQualifiers!(S5, false); 5976 mixin testWithQualifiers!(S6, false); 5977 mixin testWithQualifiers!(S7, false); 5978 mixin testWithQualifiers!(S8, false); 5979 mixin testWithQualifiers!(S9, false); 5980 mixin testWithQualifiers!(S10, false); 5981 } 5982 { 5983 struct S1 { int* i; } 5984 struct S2 { S1 s; } 5985 struct S3 { S2 s; } 5986 struct S4 { S3 s; } 5987 struct S5 { S4 s; } 5988 struct S6 { S5 s; } 5989 struct S7 { S6[0] s; } 5990 struct S8 { S7 s; } 5991 struct S9 { S8 s; } 5992 struct S10 { S9 s; } 5993 mixin testWithQualifiers!(S1, true); 5994 mixin testWithQualifiers!(S2, true); 5995 mixin testWithQualifiers!(S3, true); 5996 mixin testWithQualifiers!(S4, true); 5997 mixin testWithQualifiers!(S5, true); 5998 mixin testWithQualifiers!(S6, true); 5999 mixin testWithQualifiers!(S7, false); 6000 mixin testWithQualifiers!(S8, false); 6001 mixin testWithQualifiers!(S9, false); 6002 mixin testWithQualifiers!(S10, false); 6003 } 6004 } 6005 6006 // hasIndirections with unions. 6007 @safe unittest 6008 { 6009 import phobos.sys.meta : AliasSeq; 6010 6011 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 6012 6013 { 6014 union U {} 6015 mixin testWithQualifiers!(U, false); 6016 } 6017 { 6018 static union U {} 6019 mixin testWithQualifiers!(U, false); 6020 } 6021 6022 // Unions with members which aren't aggregate types and don't have indirections. 6023 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 6024 float, double, real, char, wchar, dchar, int function(string))) 6025 { 6026 // No indirections. 6027 { 6028 union U { T member; } 6029 mixin testWithQualifiers!(U, false); 6030 } 6031 { 6032 union U { const T member; } 6033 mixin testWithQualifiers!(U, false); 6034 } 6035 { 6036 union U { immutable T member; } 6037 mixin testWithQualifiers!(U, false); 6038 } 6039 { 6040 union U { shared T member; } 6041 mixin testWithQualifiers!(U, false); 6042 } 6043 6044 // Pointers. 6045 { 6046 union U { T* member; } 6047 mixin testWithQualifiers!(U, true); 6048 } 6049 { 6050 union U { const(T)* member; } 6051 mixin testWithQualifiers!(U, true); 6052 } 6053 { 6054 union U { const T* member; } 6055 mixin testWithQualifiers!(U, true); 6056 } 6057 { 6058 union U { immutable T* member; } 6059 mixin testWithQualifiers!(U, true); 6060 } 6061 { 6062 union U { shared T* member; } 6063 mixin testWithQualifiers!(U, true); 6064 } 6065 6066 // Dynamic arrays. 6067 { 6068 union U { T[] member; } 6069 mixin testWithQualifiers!(U, true); 6070 } 6071 { 6072 union U { const(T)[] member; } 6073 mixin testWithQualifiers!(U, true); 6074 } 6075 { 6076 union U { const T[] member; } 6077 mixin testWithQualifiers!(U, true); 6078 } 6079 { 6080 union U { immutable T[] member; } 6081 mixin testWithQualifiers!(U, true); 6082 } 6083 { 6084 union U { shared T[] member; } 6085 mixin testWithQualifiers!(U, true); 6086 } 6087 6088 // Static arrays. 6089 { 6090 union U { T[1] member; } 6091 mixin testWithQualifiers!(U, false); 6092 } 6093 { 6094 union U { const(T)[1] member; } 6095 mixin testWithQualifiers!(U, false); 6096 } 6097 { 6098 union U { const T[1] member; } 6099 mixin testWithQualifiers!(U, false); 6100 } 6101 { 6102 union U { immutable T[1] member; } 6103 mixin testWithQualifiers!(U, false); 6104 } 6105 { 6106 union U { shared T[1] member; } 6107 mixin testWithQualifiers!(U, false); 6108 } 6109 6110 // Static arrays of pointers. 6111 { 6112 union U { T*[1] member; } 6113 mixin testWithQualifiers!(U, true); 6114 } 6115 { 6116 union U { const(T)*[1] member; } 6117 mixin testWithQualifiers!(U, true); 6118 } 6119 { 6120 union U { const(T*)[1] member; } 6121 mixin testWithQualifiers!(U, true); 6122 } 6123 { 6124 union U { const T*[1] member; } 6125 mixin testWithQualifiers!(U, true); 6126 } 6127 { 6128 union U { immutable T*[1] member; } 6129 mixin testWithQualifiers!(U, true); 6130 } 6131 { 6132 union U { shared T*[1] member; } 6133 mixin testWithQualifiers!(U, true); 6134 } 6135 6136 { 6137 union U { T*[0] member; } 6138 mixin testWithQualifiers!(U, false); 6139 } 6140 { 6141 union U { const(T)*[0] member; } 6142 mixin testWithQualifiers!(U, false); 6143 } 6144 { 6145 union U { const(T*)[0] member; } 6146 mixin testWithQualifiers!(U, false); 6147 } 6148 { 6149 union U { const T*[0] member; } 6150 mixin testWithQualifiers!(U, false); 6151 } 6152 { 6153 union U { immutable T*[0] member; } 6154 mixin testWithQualifiers!(U, false); 6155 } 6156 { 6157 union U { shared T*[0] member; } 6158 mixin testWithQualifiers!(U, false); 6159 } 6160 6161 // Static arrays of dynamic arrays. 6162 { 6163 union U { T[][1] member; } 6164 mixin testWithQualifiers!(U, true); 6165 } 6166 { 6167 union U { const(T)[][1] member; } 6168 mixin testWithQualifiers!(U, true); 6169 } 6170 { 6171 union U { const(T[])[1] member; } 6172 mixin testWithQualifiers!(U, true); 6173 } 6174 { 6175 union U { const T[][1] member; } 6176 mixin testWithQualifiers!(U, true); 6177 } 6178 { 6179 union U { immutable T[][1] member; } 6180 mixin testWithQualifiers!(U, true); 6181 } 6182 { 6183 union U { shared T[][1] member; } 6184 mixin testWithQualifiers!(U, true); 6185 } 6186 6187 { 6188 union U { T[][0] member; } 6189 mixin testWithQualifiers!(U, false); 6190 } 6191 { 6192 union U { const(T)[][0] member; } 6193 mixin testWithQualifiers!(U, false); 6194 } 6195 { 6196 union U { const(T[])[0] member; } 6197 mixin testWithQualifiers!(U, false); 6198 } 6199 { 6200 union U { const T[][0] member; } 6201 mixin testWithQualifiers!(U, false); 6202 } 6203 { 6204 union U { immutable T[][0] member; } 6205 mixin testWithQualifiers!(U, false); 6206 } 6207 { 6208 union U { shared T[][0] member; } 6209 mixin testWithQualifiers!(U, false); 6210 } 6211 } 6212 6213 // Unions with arrays of void. 6214 { 6215 { 6216 static union U { void[] member; } 6217 mixin testWithQualifiers!(U, true); 6218 } 6219 { 6220 static union U { void[1] member; } 6221 mixin testWithQualifiers!(U, true); 6222 } 6223 { 6224 static union U { void[0] member; } 6225 mixin testWithQualifiers!(U, false); 6226 } 6227 } 6228 6229 // Unions with multiple members, testing pointer types. 6230 { 6231 static union U { int i; bool b; } 6232 mixin testWithQualifiers!(U, false); 6233 } 6234 { 6235 static union U { int* i; bool b; } 6236 mixin testWithQualifiers!(U, true); 6237 } 6238 { 6239 static union U { int i; bool* b; } 6240 mixin testWithQualifiers!(U, true); 6241 } 6242 { 6243 static union U { int* i; bool* b; } 6244 mixin testWithQualifiers!(U, true); 6245 } 6246 6247 // Unions with multiple members, testing dynamic arrays. 6248 { 6249 static union U { int[] arr; } 6250 mixin testWithQualifiers!(U, true); 6251 } 6252 { 6253 static union U { int i; int[] arr; } 6254 mixin testWithQualifiers!(U, true); 6255 } 6256 { 6257 static union U { int[] arr; int i; } 6258 mixin testWithQualifiers!(U, true); 6259 } 6260 6261 // Unions with multiple members, testing static arrays. 6262 { 6263 static union U { int[1] arr; } 6264 mixin testWithQualifiers!(U, false); 6265 } 6266 { 6267 static union U { int i; int[1] arr; } 6268 mixin testWithQualifiers!(U, false); 6269 } 6270 { 6271 static union U { int[1] arr; int i; } 6272 mixin testWithQualifiers!(U, false); 6273 } 6274 6275 { 6276 static union U { int*[0] arr; } 6277 mixin testWithQualifiers!(U, false); 6278 } 6279 { 6280 static union U { int i; int*[0] arr; } 6281 mixin testWithQualifiers!(U, false); 6282 } 6283 { 6284 static union U { int*[0] arr; int i; } 6285 mixin testWithQualifiers!(U, false); 6286 } 6287 6288 { 6289 static union U { string[42] arr; } 6290 mixin testWithQualifiers!(U, true); 6291 } 6292 { 6293 static union U { int i; string[42] arr; } 6294 mixin testWithQualifiers!(U, true); 6295 } 6296 { 6297 static union U { string[42] arr; int i; } 6298 mixin testWithQualifiers!(U, true); 6299 } 6300 6301 // Unions with associative arrays. 6302 { 6303 static union U { int[string] aa; } 6304 mixin testWithQualifiers!(U, true); 6305 } 6306 { 6307 static union U { int i; int[string] aa; } 6308 mixin testWithQualifiers!(U, true); 6309 } 6310 { 6311 static union U { int[string] aa; int i; } 6312 mixin testWithQualifiers!(U, true); 6313 } 6314 6315 { 6316 static union U { int[42][int] aa; } 6317 mixin testWithQualifiers!(U, true); 6318 } 6319 { 6320 static union U { int[0][int] aa; } 6321 mixin testWithQualifiers!(U, true); 6322 } 6323 6324 // Unions with classes. 6325 { 6326 class C {} 6327 union U { C c; } 6328 mixin testWithQualifiers!(U, true); 6329 } 6330 { 6331 interface I {} 6332 union U { I i; } 6333 mixin testWithQualifiers!(U, true); 6334 } 6335 6336 // Unions with delegates. 6337 { 6338 union U { void delegate() d; } 6339 mixin testWithQualifiers!(U, true); 6340 } 6341 { 6342 union U { int delegate(int) d; } 6343 mixin testWithQualifiers!(U, true); 6344 } 6345 6346 // Unions multiple layers deep. 6347 { 6348 union U1 { int i; } 6349 union U2 { U1 s; } 6350 union U3 { U2 s; } 6351 union U4 { U3 s; } 6352 union U5 { U4 s; } 6353 union U6 { U5 s; } 6354 union U7 { U6[0] s; } 6355 union U8 { U7 s; } 6356 union U9 { U8 s; } 6357 union U10 { U9 s; } 6358 mixin testWithQualifiers!(U1, false); 6359 mixin testWithQualifiers!(U2, false); 6360 mixin testWithQualifiers!(U3, false); 6361 mixin testWithQualifiers!(U4, false); 6362 mixin testWithQualifiers!(U5, false); 6363 mixin testWithQualifiers!(U6, false); 6364 mixin testWithQualifiers!(U7, false); 6365 mixin testWithQualifiers!(U8, false); 6366 mixin testWithQualifiers!(U9, false); 6367 mixin testWithQualifiers!(U10, false); 6368 } 6369 { 6370 union U1 { int* i; } 6371 union U2 { U1 s; } 6372 union U3 { U2 s; } 6373 union U4 { U3 s; } 6374 union U5 { U4 s; } 6375 union U6 { U5 s; } 6376 union U7 { U6[0] s; } 6377 union U8 { U7 s; } 6378 union U9 { U8 s; } 6379 union U10 { U9 s; } 6380 mixin testWithQualifiers!(U1, true); 6381 mixin testWithQualifiers!(U2, true); 6382 mixin testWithQualifiers!(U3, true); 6383 mixin testWithQualifiers!(U4, true); 6384 mixin testWithQualifiers!(U5, true); 6385 mixin testWithQualifiers!(U6, true); 6386 mixin testWithQualifiers!(U7, false); 6387 mixin testWithQualifiers!(U8, false); 6388 mixin testWithQualifiers!(U9, false); 6389 mixin testWithQualifiers!(U10, false); 6390 } 6391 } 6392 6393 // hasIndirections with classes and interfaces 6394 @safe unittest 6395 { 6396 import phobos.sys.meta : AliasSeq; 6397 6398 alias testWithQualifiers = assertWithQualifiers!hasIndirections; 6399 6400 { 6401 class C {} 6402 mixin testWithQualifiers!(C, true); 6403 } 6404 6405 foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong, 6406 float, double, real, char, wchar, dchar, int function(string), 6407 int[int], string delegate(int))) 6408 { 6409 { 6410 class C { T member; } 6411 mixin testWithQualifiers!(C, true); 6412 } 6413 { 6414 class C { const T member; } 6415 mixin testWithQualifiers!(C, true); 6416 } 6417 { 6418 class C { immutable T member; } 6419 mixin testWithQualifiers!(C, true); 6420 } 6421 { 6422 class C { shared T member; } 6423 mixin testWithQualifiers!(C, true); 6424 } 6425 } 6426 6427 { 6428 interface I {} 6429 mixin testWithQualifiers!(I, true); 6430 } 6431 } 6432 6433 /++ 6434 Takes a type which is an associative array and evaluates to the type of the 6435 keys in that associative array. 6436 6437 See_Also: 6438 $(LREF ValueType) 6439 +/ 6440 alias KeyType(V : V[K], K) = K; 6441 6442 /// 6443 @safe unittest 6444 { 6445 static assert(is(KeyType!(int[string]) == string)); 6446 static assert(is(KeyType!(string[int]) == int)); 6447 6448 static assert(is(KeyType!(string[const int]) == const int)); 6449 static assert(is(KeyType!(const int[string]) == string)); 6450 6451 struct S 6452 { 6453 int i; 6454 } 6455 6456 string[S] aa1; 6457 static assert(is(KeyType!(typeof(aa1)) == S)); 6458 6459 S[string] aa2; 6460 static assert(is(KeyType!(typeof(aa2)) == string)); 6461 6462 KeyType!(typeof(aa1)) key1 = S(42); 6463 KeyType!(typeof(aa2)) key2 = "foo"; 6464 6465 // Key types with indirections have their inner layers treated as const 6466 // by the compiler, because the values of keys can't change, or the hash 6467 // value could change, putting the associative array in an invalid state. 6468 static assert(is(KeyType!(bool[string[]]) == const(string)[])); 6469 static assert(is(KeyType!(bool[int*]) == const(int)*)); 6470 6471 // If the given type is not an AA, then KeyType won't compile. 6472 static assert(!__traits(compiles, KeyType!int)); 6473 static assert(!__traits(compiles, KeyType!(int[]))); 6474 } 6475 6476 /++ 6477 Takes a type which is an associative array and evaluates to the type of the 6478 values in that associative array. 6479 6480 See_Also: 6481 $(LREF KeyType) 6482 +/ 6483 alias ValueType(V : V[K], K) = V; 6484 6485 /// 6486 @safe unittest 6487 { 6488 static assert(is(ValueType!(int[string]) == int)); 6489 static assert(is(ValueType!(string[int]) == string)); 6490 6491 static assert(is(ValueType!(string[const int]) == string)); 6492 static assert(is(ValueType!(const int[string]) == const int)); 6493 6494 struct S 6495 { 6496 int i; 6497 } 6498 6499 string[S] aa1; 6500 static assert(is(ValueType!(typeof(aa1)) == string)); 6501 6502 S[string] aa2; 6503 static assert(is(ValueType!(typeof(aa2)) == S)); 6504 6505 ValueType!(typeof(aa1)) value1 = "foo"; 6506 ValueType!(typeof(aa2)) value2 = S(42); 6507 6508 // If the given type is not an AA, then ValueType won't compile. 6509 static assert(!__traits(compiles, ValueType!int)); 6510 static assert(!__traits(compiles, ValueType!(int[]))); 6511 } 6512 6513 /++ 6514 Evaluates to the original / ultimate base type of an enum type - or for 6515 non-enum types, it evaluates to the type that it's given. 6516 6517 If the base type of the given enum type is not an enum, then the result of 6518 OriginalType is its direct base type. However, if the base type of the 6519 given enum is also an enum, then OriginalType gives the ultimate base type 6520 - that is, it keeps getting the base type for each succesive enum in the 6521 chain until it gets to a base type that isn't an enum, and that's the 6522 result. So, the result will never be an enum type. 6523 6524 If the given type has any qualifiers, the result will have those same 6525 qualifiers. 6526 +/ 6527 version (StdDdoc) template OriginalType(T) 6528 { 6529 import core.internal.traits : CoreOriginalType = OriginalType; 6530 alias OriginalType = CoreOriginalType!T; 6531 } 6532 else 6533 { 6534 import core.internal.traits : CoreOriginalType = OriginalType; 6535 alias OriginalType = CoreOriginalType; 6536 } 6537 6538 /// 6539 @safe unittest 6540 { 6541 enum E { a, b, c } 6542 static assert(is(OriginalType!E == int)); 6543 6544 enum F : E { x = E.a } 6545 static assert(is(OriginalType!F == int)); 6546 6547 enum G : F { y = F.x } 6548 static assert(is(OriginalType!G == int)); 6549 static assert(is(OriginalType!(const G) == const int)); 6550 static assert(is(OriginalType!(immutable G) == immutable int)); 6551 static assert(is(OriginalType!(shared G) == shared int)); 6552 6553 enum C : char { a = 'a', b = 'b' } 6554 static assert(is(OriginalType!C == char)); 6555 6556 enum D : string { d = "dlang" } 6557 static assert(is(OriginalType!D == string)); 6558 6559 static assert(is(OriginalType!int == int)); 6560 static assert(is(OriginalType!(const long) == const long)); 6561 static assert(is(OriginalType!string == string)); 6562 6563 // OriginalType gets the base type of enums and for all other types gives 6564 // the same type back. It does nothing special for other types - like 6565 // classes - where one could talk about the type having a base type. 6566 class Base {} 6567 class Derived : Base {} 6568 static assert(is(OriginalType!Base == Base)); 6569 static assert(is(OriginalType!Derived == Derived)); 6570 } 6571 6572 /++ 6573 PropertyType evaluates to the type of the symbol as an expression (i.e. the 6574 type of the expression when the symbol is used in an expression by itself), 6575 and SymbolType evaluates to the type of the given symbol as a symbol (i.e. 6576 the type of the symbol itself). 6577 6578 Unlike with $(K_TYPEOF), $(K_PROPERTY) has no effect on the result of 6579 either PropertyType or SymbolType. 6580 6581 TLDR, PropertyType should be used when code is going to use a symbol as if 6582 it were a getter property (without caring whether the symbol is a variable 6583 or a function), and the code needs to know the type of that property and 6584 $(I not) the type of the symbol itself (since with functions, they're not 6585 the same thing). So, it's treating the symbol as an expression on its own 6586 and giving the type of that expression rather than giving the type of the 6587 symbol itself. And it's named PropertyType rather than something like 6588 $(D ExpressionType), because it's used in situations where the code is 6589 treating the symbol as a getter property, and it does not operate on 6590 expressions in general. SymbolType should then be used in situations where 6591 the code needs to know the type of the symbol itself. 6592 6593 As for why PropertyType and SymbolType are necessary, and $(K_TYPEOF) is 6594 not sufficient, $(K_TYPEOF) gives both the types of symbols and the types 6595 of expressions. When it's given something that's clearly an expression - 6596 e.g. $(D typeof(foo + bar)) or $(D typeof(foo())), then the result is the 6597 type of that expression. However, when $(K_TYPEOF) is given a symbol, what 6598 $(K_TYPEOF) does depends on the symbol, which can make using it correctly 6599 in generic code difficult. 6600 6601 For symbols that don't have types, naturally, $(K_TYPEOF) doesn't even 6602 compile (e.g. $(D typeof(int)) won't compile, because in D, types don't 6603 themselves have types), so the question is what happens with $(K_TYPEOF) 6604 and symbols which do have types. 6605 6606 For symbols which have types and are not functions, what $(K_TYPEOF) does 6607 is straightforward, because there is no difference between the type of the 6608 symbol and the type of the expression - e.g. if $(D foo) is a variable of 6609 type $(K_INT), then $(D typeof(foo)) would be $(K_INT), because the 6610 variable itself is of type $(K_INT), and if the variable is used as an 6611 expression (e.g. when it's returned from a function or passed to a 6612 function), then that expression is also of type $(K_INT). 6613 6614 However, for functions (particularly functions which don't require 6615 arguments), things aren't as straightforward. Should $(D typeof(foo)) give 6616 the type of the function itself or the type of the expression? If parens 6617 always had to be used when calling a function, then $(D typeof(foo)) would 6618 clearly be the type of the function itself, whereas $(D typeof(foo())) 6619 would be the type of the expression (which would be the return type of the 6620 function so long as $(D foo) could be called with no arguments, and it 6621 wouldn't compile otherwise, because the expression would be invalid). 6622 However, because parens are optional when calling a function that has no 6623 arguments, $(D typeof(foo)) is ambiguous. There's no way to know which the 6624 programmer actually intended, but the compiler has to either make it an 6625 error or choose between giving the type of the symbol or the type of the 6626 expression. 6627 6628 So, the issue here is functions which can be treated as getter properties, 6629 because they can be called without parens and thus syntactically look 6630 exactly like a variable when they're used. Any function which requires 6631 arguments (including when a function is used as a setter property) does not 6632 have this problem, because it isn't a valid expression when used on its own 6633 (it needs to be assigned to or called with parens in order to be a valid 6634 expression). 6635 6636 What the compiler currently does when it encounters this ambiguity depends 6637 on the $(K_PROPERTY) attribute. If the function does not have the 6638 $(K_PROPERTY) attribute, then $(D typeof(foo)) will give the type of the 6639 symbol - e.g. $(D int()) if the signature for $(D foo) were $(D int foo()). 6640 However, if the function $(I does) have the $(K_PROPERTY) attribute, then 6641 $(D typeof(foo)) will give the type of the expression. So, if $(D foo) were 6642 $(D @property int foo()), then $(D typeof(foo)) would give $(K_INT) rather 6643 than $(D int()). The idea behind this is that $(K_PROPERTY) functions are 6644 supposed to act like variables, and using $(K_TYPEOF) on a variable of type 6645 $(K_INT) would give $(K_INT), not $(D int()). So, with this behavior of 6646 $(K_TYPEOF), a $(K_PROPERTY) function is closer to being a drop-in 6647 replacement for a variable. 6648 6649 The problem with this though is two-fold. One, it means that $(K_TYPEOF) 6650 cannot be relied on to give the type of the symbol when given a symbol on 6651 its own, forcing code that needs the actual type of the symbol to work 6652 around $(K_PROPERTY). And two, because parens are optional on functions 6653 which can be called without arguments, whether the function is marked with 6654 $(K_PROPERTY) or not is irrevelant to whether the symbol is going to be 6655 used as if it were a variable, and so it's irrelevant to code that's trying 6656 to get the type of the expression when the symbol is used like a getter 6657 property. If optional parens were removed from the language (as was 6658 originally the intent when $(K_PROPERTY) was introduced), then that would 6659 fix the second problem, but it would still leave the first problem. 6660 6661 So, $(K_PROPERTY) is solving the problem in the wrong place. It's the code 6662 doing the type introspection which needs to decide whether to get the type 6663 of a symbol as if it were a getter property or whether to get the type of 6664 the symbol itself. It's the type introspection code which knows which is 6665 relevant for what it's doing, and a function could be used both in code 6666 which needs to treat it as a getter property and in code which needs to get 6667 the type of the symbol itself (e.g. because it needs to get the attributes 6668 on the function). 6669 6670 All of this means that $(K_TYPEOF) by itself is unreliable when used on a 6671 symbol. In practice, the programmer needs to indicate whether they want the 6672 type of the symbol itself or the type of the symbol as a getter property in 6673 an expression, and leaving it up to $(K_TYPEOF) is simply too error-prone. 6674 So, ideally, $(K_TYPEOF) would be split up into two separate constructs, 6675 but that would involve adding more keywords (and break a lot of existing 6676 code if $(K_TYPEOF) were actually removed). 6677 6678 So, phobos.sys.traits provides SymbolType and PropertyType. They're both 6679 traits that take a symbol and give the type for that symbol. However, 6680 SymbolType gives the type of the symbol itself, whereas PropertyType gives 6681 the type of the symbol as if it were used as a getter property in an 6682 expression. Neither is affected by whether the symbol is marked with 6683 $(K_PROPERTY). So, code that needs to get information about the symbol 6684 itself should use SymbolType rather than $(K_TYPEOF) or PropertyType, 6685 whereas code that needs to get the type of the symbol as a getter property 6686 within an expression should use PropertyType. 6687 6688 The use of $(K_TYPEOF) should then be restricted to situations where code 6689 is getting the type of an expression which isn't a symbol (or code where 6690 it's already known that the symbol isn't a function). Also, since 6691 template alias parameters only accept symbols, any expressions which aren't 6692 symbols won't compile with SymbolType or PropertyType anyway. 6693 6694 SymbolType and PropertyType must be given a symbol which has a type (so, 6695 not something like a type or an uninstantiated template). Symbols 6696 which don't have types will fail the template constraint. 6697 6698 For both SymbolType and PropertyType, if they are given a symbol which has 6699 a type, and that symbol is not a function, the result will be the same as 6700 $(K_TYPEOF) (since in such cases, the type of the symbol and the type of 6701 the expression are the same). The difference comes in with functions. 6702 6703 When SymbolType is given any symbol which is a function, the result will be 6704 the type of the function itself regardless of whether the function is 6705 marked with $(K_PROPERTY). This makes it so that in all situations where 6706 the type of the symbol is needed, SymbolType can be used to get the type of 6707 the symbol without having to worry about whether it's a function marked 6708 with $(K_PROPERTY). 6709 6710 When PropertyType is given any function which can be used as a getter 6711 property, the result will be the type of the symbol as an expression - i.e. 6712 the return type of the function (in effect, this means that it treats all 6713 functions as if they were marked with $(K_PROPERTY)). Whether the function 6714 is actually marked with $(K_PROPERTY) or not is irrelevant. 6715 6716 If PropertyType is given any function which which cannot be used as a 6717 getter property (i.e. it requires arguments or returns $(K_VOID)), the 6718 template constraint will reject it, and PropertyType will fail to compile. 6719 This is equivalent to what $(K_TYPEOF) does when it's given a $(K_PROPERTY) 6720 function which is a setter, since it's not a valid expression on its own. 6721 6722 So, for $(D PropertyType!foo), if $(D foo) is a function, the result is 6723 equivalent to $(D typeof(foo())) (and for non-functions, it's equivalent to 6724 $(D typeof(foo))). 6725 6726 To summarize, SymbolType should be used when code needs to get the type of 6727 the symbol itself; PropertyType should be used when code needs to get the 6728 type of the symbol when it's used in an expression as a getter property 6729 (generally because the code doesn't care whether the symbol is a variable 6730 or a function); and $(K_TYPEOF) should be used when getting the type of an 6731 expression which is not a symbol. 6732 6733 See_Also: 6734 $(DDSUBLINK spec/type, typeof, The language spec for typeof) 6735 +/ 6736 template PropertyType(alias sym) 6737 if (is(typeof(sym)) && (!is(typeof(sym) == return) || 6738 (is(typeof(sym())) && !is(typeof(sym()) == void)))) 6739 { 6740 // This handles functions which don't have a context pointer. 6741 static if (is(typeof(&sym) == T*, T) && is(T == function)) 6742 { 6743 // Note that we can't use is(T R == return) to get the return type, 6744 // because the first overload isn't necessarily the getter function, 6745 // and is(T R == return) will give us the first overload if the function 6746 // doesn't have @property on it (whereas if it does have @property, it 6747 // will give use the getter if there is one). However, we at least know 6748 // that there's a getter function, because the template constraint 6749 // validates that sym() compiles (and returns something) if it's a 6750 // function, function pointer, or delegate. 6751 alias PropertyType = typeof(sym()); 6752 } 6753 // This handles functions which do have a context pointer. 6754 else static if (is(typeof(&sym) T == delegate) && is(T R == return)) 6755 { 6756 // See the comment above for why we can't get the return type the 6757 // normal way. 6758 alias PropertyType = typeof(sym()); 6759 } 6760 // This handles everything which isn't a function. 6761 else 6762 alias PropertyType = typeof(sym); 6763 } 6764 6765 /++ Ditto +/ 6766 template SymbolType(alias sym) 6767 if (!is(sym)) 6768 { 6769 // This handles functions which don't have a context pointer. 6770 static if (is(typeof(&sym) == T*, T) && is(T == function)) 6771 alias SymbolType = T; 6772 // This handles functions which do have a context pointer. 6773 else static if (is(typeof(&sym) T == delegate)) 6774 alias SymbolType = T; 6775 // This handles everything which isn't a function. 6776 else 6777 alias SymbolType = typeof(sym); 6778 } 6779 6780 /// 6781 @safe unittest 6782 { 6783 int i; 6784 static assert( is(SymbolType!i == int)); 6785 static assert( is(PropertyType!i == int)); 6786 static assert( is(typeof(i) == int)); 6787 6788 string str; 6789 static assert( is(SymbolType!str == string)); 6790 static assert( is(PropertyType!str == string)); 6791 static assert( is(typeof(str) == string)); 6792 6793 // ToFunctionType is used here to get around the fact that we don't have a 6794 // way to write out function types in is expressions (whereas we can write 6795 // out the type of a function pointer), which is a consequence of not being 6796 // able to declare variables with a function type (as opposed to a function 6797 // pointer type). That being said, is expressions are pretty much the only 6798 // place where writing out a function type would make sense. 6799 6800 // The function type has more attributes than the function declaration, 6801 // because the attributes are inferred for nested functions. 6802 6803 static string func() { return ""; } 6804 static assert( is(SymbolType!func == 6805 ToFunctionType!(string function() 6806 @safe pure nothrow @nogc))); 6807 static assert( is(PropertyType!func == string)); 6808 static assert( is(typeof(func) == SymbolType!func)); 6809 6810 int function() funcPtr; 6811 static assert( is(SymbolType!funcPtr == int function())); 6812 static assert( is(PropertyType!funcPtr == int function())); 6813 static assert( is(typeof(funcPtr) == int function())); 6814 6815 int delegate() del; 6816 static assert( is(SymbolType!del == int delegate())); 6817 static assert( is(PropertyType!del == int delegate())); 6818 static assert( is(typeof(del) == int delegate())); 6819 6820 @property static int prop() { return 0; } 6821 static assert( is(SymbolType!prop == 6822 ToFunctionType!(int function() 6823 @property @safe pure nothrow @nogc))); 6824 static assert( is(PropertyType!prop == int)); 6825 static assert( is(typeof(prop) == PropertyType!prop)); 6826 6827 // Functions which cannot be used as getter properties (i.e. they require 6828 // arguments and/or return void) do not compile with PropertyType. 6829 static int funcWithArg(int i) { return i; } 6830 static assert( is(SymbolType!funcWithArg == 6831 ToFunctionType!(int function(int) 6832 @safe pure nothrow @nogc))); 6833 static assert(!__traits(compiles, PropertyType!funcWithArg)); 6834 static assert( is(typeof(funcWithArg) == SymbolType!funcWithArg)); 6835 6836 // Setter @property functions also don't work with typeof, because typeof 6837 // gets the type of the expression rather than the type of the symbol when 6838 // the symbol is a function with @property, and a setter property is not a 6839 // valid expression on its own. 6840 @property static void prop2(int) {} 6841 static assert( is(SymbolType!prop2 == 6842 ToFunctionType!(void function(int) 6843 @property @safe pure nothrow @nogc))); 6844 static assert(!__traits(compiles, PropertyType!prop2)); 6845 static assert(!__traits(compiles, typeof(prop2))); 6846 6847 // Expressions which aren't symbols don't work with alias parameters and 6848 // thus don't work with SymbolType or PropertyType. 6849 static assert(!__traits(compiles, PropertyType!(i + 42))); 6850 static assert(!__traits(compiles, SymbolType!(i + 42))); 6851 static assert( is(typeof(i + 42) == int)); 6852 6853 // typeof will work with a function that takes arguments so long as it's 6854 // used in a proper expression. 6855 static assert( is(typeof(funcWithArg(42)) == int)); 6856 static assert( is(typeof(prop2 = 42) == void)); 6857 static assert( is(typeof(prop2(42)) == void)); 6858 } 6859 6860 /++ 6861 With templated types or functions, a specific instantiation should be 6862 passed to SymbolType or PropertyType, not the symbol for the template 6863 itself. If $(K_TYPEOF), SymbolType, or PropertyType is used on a template 6864 (rather than an instantiation of the template), the result will be 6865 $(K_VOID), because the template itself does not have a type. 6866 +/ 6867 @safe unittest 6868 { 6869 static T func(T)() { return T.init; } 6870 6871 static assert(is(SymbolType!func == void)); 6872 static assert(is(PropertyType!func == void)); 6873 static assert(is(typeof(func) == void)); 6874 6875 static assert(is(SymbolType!(func!int) == 6876 ToFunctionType!(int function() 6877 @safe pure nothrow @nogc))); 6878 static assert(is(PropertyType!(func!int) == int)); 6879 static assert(is(typeof(func!int) == SymbolType!(func!int))); 6880 6881 static assert(is(SymbolType!(func!string) == 6882 ToFunctionType!(string function() 6883 @safe pure nothrow @nogc))); 6884 static assert(is(PropertyType!(func!string) == string)); 6885 static assert(is(typeof(func!string) == SymbolType!(func!string))); 6886 } 6887 6888 /++ 6889 If a function is overloaded, then when using it as a symbol to pass to 6890 $(K_TYPEOF), the compiler typically selects the first overload. However, if 6891 the functions are marked with $(K_PROPERTY), and one of the overloads is a 6892 getter property, then $(K_TYPEOF) will select the getter property (or fail 6893 to compile if they're all setter properties). This is because it's getting 6894 the type of the function as an expression rather than doing introspection 6895 on the function itself. 6896 6897 SymbolType always gives the type of the first overload (effectively ignoring 6898 $(K_PROPERTY)), and PropertyType always gives the getter ovrerload 6899 (effectively treating all functions as if they had $(K_PROPERTY)). 6900 6901 If code needs to get the symbol for a specific overload, then 6902 $(DDSUBLINK spec/traits, getOverloads, $(D __traits(getOverloads, ...)) 6903 must be used. 6904 6905 In general, $(D getOverloads) should be used when using SymbolType, since 6906 there's no guarantee that the first one is the correct one (and often, code 6907 will need to check all of the overloads), whereas with PropertyType, it 6908 doesn't usually make sense to get specific overloads, because there can 6909 only ever be one overload which works as a getter property, and using 6910 PropertyType on the symbol for the function will give that overload if it's 6911 present, regardless of which overload is first (and it will fail to compile 6912 if there is no overload which can be called as a getter). 6913 +/ 6914 @safe unittest 6915 { 6916 static struct S 6917 { 6918 string foo(); 6919 void foo(string); 6920 bool foo(string, int); 6921 6922 @property void bar(int); 6923 @property int bar(); 6924 } 6925 6926 { 6927 static assert( is(SymbolType!(S.foo) == 6928 ToFunctionType!(string function()))); 6929 static assert( is(PropertyType!(S.foo) == string)); 6930 static assert( is(typeof(S.foo) == SymbolType!(S.foo))); 6931 6932 alias overloads = __traits(getOverloads, S, "foo"); 6933 6934 // string foo(); 6935 static assert( is(SymbolType!(overloads[0]) == function)); 6936 static assert( is(PropertyType!(overloads[0]) == string)); 6937 static assert( is(typeof(overloads[0]) == function)); 6938 6939 static assert( is(SymbolType!(overloads[0]) == 6940 ToFunctionType!(string function()))); 6941 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 6942 6943 // void foo(string); 6944 static assert( is(SymbolType!(overloads[1]) == function)); 6945 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 6946 static assert( is(typeof(overloads[1]) == function)); 6947 6948 static assert( is(SymbolType!(overloads[1]) == 6949 ToFunctionType!(void function(string)))); 6950 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 6951 6952 // void foo(string, int); 6953 static assert( is(SymbolType!(overloads[2]) == function)); 6954 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 6955 static assert( is(typeof(overloads[2]) == function)); 6956 6957 static assert( is(SymbolType!(overloads[2]) == 6958 ToFunctionType!(bool function(string, int)))); 6959 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 6960 } 6961 { 6962 static assert( is(SymbolType!(S.bar) == 6963 ToFunctionType!(void function(int) @property))); 6964 static assert( is(PropertyType!(S.bar) == int)); 6965 static assert( is(typeof(S.bar) == PropertyType!(S.bar))); 6966 6967 alias overloads = __traits(getOverloads, S, "bar"); 6968 6969 // @property void bar(int); 6970 static assert( is(SymbolType!(overloads[0]) == function)); 6971 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 6972 static assert(!__traits(compiles, typeof(overloads[0]))); 6973 6974 static assert( is(SymbolType!(overloads[0]) == 6975 ToFunctionType!(void function(int) @property))); 6976 6977 // @property int bar(); 6978 static assert( is(SymbolType!(overloads[1]) == function)); 6979 static assert( is(PropertyType!(overloads[1]) == int)); 6980 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 6981 6982 static assert( is(SymbolType!(overloads[1]) == 6983 ToFunctionType!(int function() @property))); 6984 } 6985 } 6986 6987 @safe unittest 6988 { 6989 { 6990 string str; 6991 int i; 6992 6993 static assert(!__traits(compiles, SymbolType!int)); 6994 static assert(!__traits(compiles, SymbolType!(str ~ "more str"))); 6995 static assert(!__traits(compiles, SymbolType!(i + 42))); 6996 static assert(!__traits(compiles, SymbolType!(&i))); 6997 6998 static assert(!__traits(compiles, PropertyType!int)); 6999 static assert(!__traits(compiles, PropertyType!(str ~ "more str"))); 7000 static assert(!__traits(compiles, PropertyType!(i + 42))); 7001 static assert(!__traits(compiles, PropertyType!(&i))); 7002 } 7003 7004 static assert( is(SymbolType!42 == int)); 7005 static assert( is(SymbolType!"dlang" == string)); 7006 7007 int var; 7008 7009 int funcWithContext() { return var; } 7010 static assert( is(SymbolType!funcWithContext == 7011 ToFunctionType!(int function() 7012 @safe pure nothrow @nogc))); 7013 static assert( is(PropertyType!funcWithContext == int)); 7014 static assert( is(typeof(funcWithContext) == SymbolType!funcWithContext)); 7015 7016 @property int propWithContext() { return var; } 7017 static assert( is(SymbolType!propWithContext == function)); 7018 static assert( is(SymbolType!propWithContext == 7019 ToFunctionType!(int function() @property @safe pure nothrow @nogc))); 7020 static assert( is(PropertyType!propWithContext == int)); 7021 static assert( is(typeof(propWithContext) == PropertyType!propWithContext)); 7022 7023 // For those who might be confused by this sort of declaration, this is a 7024 // property function which returns a function pointer that takes no 7025 // arguments and returns int, which gets an even uglier signature when 7026 // writing out the type for a pointer to such a property function. 7027 static int function() propFuncPtr() @property { return null; } 7028 static assert( is(SymbolType!propFuncPtr == function)); 7029 static assert( is(SymbolType!propFuncPtr == 7030 ToFunctionType!(int function() function() @property @safe pure nothrow @nogc))); 7031 static assert( is(PropertyType!propFuncPtr == int function())); 7032 static assert( is(typeof(propFuncPtr) == PropertyType!propFuncPtr)); 7033 7034 static int delegate() propDel() @property { return null; } 7035 static assert( is(SymbolType!propDel == function)); 7036 static assert( is(SymbolType!propDel == 7037 ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc))); 7038 static assert( is(PropertyType!propDel == int delegate())); 7039 static assert( is(typeof(propDel) == PropertyType!propDel)); 7040 7041 int function() propFuncPtrWithContext() @property { ++var; return null; } 7042 static assert( is(SymbolType!propFuncPtrWithContext == function)); 7043 static assert( is(SymbolType!propFuncPtrWithContext == 7044 ToFunctionType!(int function() function() @property @safe pure nothrow @nogc))); 7045 static assert( is(PropertyType!propFuncPtrWithContext == int function())); 7046 static assert( is(typeof(propFuncPtrWithContext) == PropertyType!propFuncPtrWithContext)); 7047 7048 int delegate() propDelWithContext() @property { ++var; return null; } 7049 static assert( is(SymbolType!propDelWithContext == function)); 7050 static assert( is(SymbolType!propDelWithContext == 7051 ToFunctionType!(int delegate() function() @property @safe pure nothrow @nogc))); 7052 static assert( is(PropertyType!propDelWithContext == int delegate())); 7053 static assert( is(typeof(propDelWithContext) == PropertyType!propDelWithContext)); 7054 7055 const int ci; 7056 static assert( is(SymbolType!ci == const int)); 7057 static assert( is(PropertyType!ci == const int)); 7058 static assert( is(typeof(ci) == PropertyType!ci)); 7059 7060 shared int si; 7061 static assert( is(SymbolType!si == shared int)); 7062 static assert( is(PropertyType!si == shared int)); 7063 static assert( is(typeof(si) == PropertyType!si)); 7064 7065 static struct S 7066 { 7067 int i; 7068 @disable this(this); 7069 } 7070 static assert(!__traits(isCopyable, S)); 7071 7072 S s; 7073 static assert( is(SymbolType!s == S)); 7074 static assert( is(PropertyType!s == S)); 7075 static assert( is(typeof(s) == SymbolType!s)); 7076 7077 static ref S foo(); 7078 static void bar(ref S); 7079 7080 static @property ref S bob(); 7081 static @property void sally(ref S); 7082 7083 // The aliases are due to https://github.com/dlang/dmd/issues/17505 7084 // Apparently, aliases are special-cased to work with function pointer 7085 // signatures which return by ref, and we can't do it elsewhere. 7086 alias FooPtr = ref S function(); 7087 static assert( is(SymbolType!foo == ToFunctionType!FooPtr)); 7088 static assert( is(PropertyType!foo == S)); 7089 static assert( is(typeof(foo) == SymbolType!foo)); 7090 7091 static assert( is(SymbolType!bar == ToFunctionType!(void function(ref S)))); 7092 static assert(!__traits(compiles, PropertyType!bar)); 7093 static assert( is(typeof(bar) == SymbolType!bar)); 7094 7095 alias BobPtr = ref S function() @property; 7096 static assert( is(SymbolType!bob == ToFunctionType!BobPtr)); 7097 static assert( is(PropertyType!bob == S)); 7098 static assert( is(typeof(bob) == S)); 7099 static assert( is(typeof(bob) == PropertyType!bob)); 7100 7101 static assert( is(SymbolType!sally == ToFunctionType!(void function(ref S) @property))); 7102 static assert(!__traits(compiles, PropertyType!sally)); 7103 static assert(!__traits(compiles, typeof(sally))); 7104 7105 string defaultArgs1(int i = 0); 7106 void defaultArgs2(string, int i = 0); 7107 7108 static assert( is(SymbolType!defaultArgs1 == ToFunctionType!(string function(int)))); 7109 static assert( is(PropertyType!defaultArgs1 == string)); 7110 static assert( is(typeof(defaultArgs1) == SymbolType!defaultArgs1)); 7111 7112 static assert( is(SymbolType!defaultArgs2 == ToFunctionType!(void function(string, int)))); 7113 static assert(!__traits(compiles, PropertyType!defaultArgs2)); 7114 static assert( is(typeof(defaultArgs2) == SymbolType!defaultArgs2)); 7115 7116 @property string defaultArgsProp1(int i = 0); 7117 @property void defaultArgsProp2(string, int i = 0); 7118 7119 static assert( is(SymbolType!defaultArgsProp1 == ToFunctionType!(string function(int) @property))); 7120 static assert( is(PropertyType!defaultArgsProp1 == string)); 7121 static assert( is(typeof(defaultArgsProp1) == PropertyType!defaultArgsProp1)); 7122 7123 static assert( is(SymbolType!defaultArgsProp2 == ToFunctionType!(void function(string, int) @property))); 7124 static assert(!__traits(compiles, PropertyType!defaultArgsProp2)); 7125 static assert(!__traits(compiles, typeof(defaultArgsProp2))); 7126 7127 int returningSetter(string); 7128 @property int returningSetterProp(string); 7129 7130 static assert( is(SymbolType!returningSetter == ToFunctionType!(int function(string)))); 7131 static assert(!__traits(compiles, PropertyType!returningSetter)); 7132 static assert( is(typeof(returningSetter) == SymbolType!returningSetter)); 7133 7134 static assert( is(SymbolType!returningSetterProp == ToFunctionType!(int function(string) @property))); 7135 static assert(!__traits(compiles, PropertyType!returningSetterProp)); 7136 static assert(!__traits(compiles, typeof(returningSetterProp))); 7137 } 7138 7139 // These are for the next unittest block to test overloaded free functions (in 7140 // addition to the overloaded member functions and static functions that it 7141 // tests). That way, if there are any differences in how free functions and 7142 // member functions are handled, we'll catch those bugs (be they compiler bugs 7143 // or bugs in phobos.sys.traits). 7144 version (PhobosUnittest) 7145 { 7146 private void modFunc1(); 7147 private void modFunc1(string); 7148 private int modFunc1(string, int); 7149 7150 private int modFunc2(); 7151 private int modFunc2(string); 7152 private string modFunc2(string, int); 7153 7154 private void modFunc3(int*); 7155 private void modFunc3(float); 7156 private string modFunc3(int a = 0); 7157 7158 private int modGetterFirst(); 7159 private void modGetterFirst(int); 7160 7161 private void modSetterFirst(int); 7162 private int modSetterFirst(); 7163 7164 private void modSetterOnly(string); 7165 private void modSetterOnly(int); 7166 7167 private @property int modPropGetterFirst(); 7168 private @property void modPropGetterFirst(int); 7169 7170 private @property void modPropSetterFirst(int); 7171 private @property int modPropSetterFirst(); 7172 7173 private @property void modPropSetterOnly(string); 7174 private @property void modPropSetterOnly(int); 7175 7176 private int function() @property modGetterFirstFuncPtr(); 7177 private void modGetterFirstFuncPtr(int function() @property); 7178 7179 private void modSetterFirstFuncPtr(int function() @property); 7180 private int function() @property modSetterFirstFuncPtr(); 7181 7182 private int function() @property modPropGetterFirstFuncPtr() @property; 7183 private void modPropGetterFirstFuncPtr(int function() @property) @property; 7184 7185 private void modPropSetterFirstFuncPtr(int function() @property) @property; 7186 private int function() @property modPropSetterFirstFuncPtr() @property; 7187 } 7188 7189 @safe unittest 7190 { 7191 // Note that with overloads without @property, typeof gives the first 7192 // overload, whereas with overloads with @property, typeof gives the return 7193 // type of the getter overload no matter where it is in the order. 7194 // PropertyType needs to always give the getter overload whether @property 7195 // is used or not, since that's the type of the symbol when used as a 7196 // getter property in an expression. 7197 { 7198 alias module_ = __traits(parent, __traits(parent, {})); 7199 7200 // void modFunc1(); 7201 // void modFunc1(string); 7202 // int modFunc1(string, int); 7203 { 7204 static assert( is(SymbolType!modFunc1 == ToFunctionType!(void function()))); 7205 static assert(!__traits(compiles, PropertyType!modFunc1)); 7206 static assert( is(typeof(modFunc1) == SymbolType!modFunc1)); 7207 7208 alias overloads = __traits(getOverloads, module_, "modFunc1"); 7209 static assert(overloads.length == 3); 7210 7211 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function()))); 7212 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7213 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7214 7215 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string)))); 7216 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7217 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7218 7219 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int function(string, int)))); 7220 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7221 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7222 } 7223 7224 // int modFunc2(); 7225 // int modFunc2(string); 7226 // string modFunc2(string, int); 7227 { 7228 static assert( is(SymbolType!modFunc2 == ToFunctionType!(int function()))); 7229 static assert( is(PropertyType!modFunc2 == int)); 7230 static assert( is(typeof(modFunc2) == SymbolType!modFunc2)); 7231 7232 alias overloads = __traits(getOverloads, module_, "modFunc2"); 7233 static assert(overloads.length == 3); 7234 7235 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 7236 static assert( is(PropertyType!(overloads[0]) == int)); 7237 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7238 7239 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 7240 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7241 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7242 7243 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(string, int)))); 7244 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7245 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7246 } 7247 7248 // void modFunc3(int*); 7249 // void modFunc3(float); 7250 // string modFunc3(int a = 0); 7251 { 7252 static assert( is(SymbolType!modFunc3 == ToFunctionType!(void function(int*)))); 7253 static assert( is(PropertyType!modFunc3 == string)); 7254 static assert( is(typeof(modFunc3) == SymbolType!modFunc3)); 7255 7256 alias overloads = __traits(getOverloads, module_, "modFunc3"); 7257 static assert(overloads.length == 3); 7258 7259 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int*)))); 7260 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7261 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7262 7263 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(float)))); 7264 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7265 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7266 7267 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(string function(int)))); 7268 static assert( is(PropertyType!(overloads[2]) == string)); 7269 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7270 } 7271 7272 // int modGetterFirst(); 7273 // void modGetterFirst(int); 7274 { 7275 static assert( is(SymbolType!modGetterFirst == ToFunctionType!(int function()))); 7276 static assert( is(PropertyType!modGetterFirst == int)); 7277 static assert( is(typeof(modGetterFirst) == SymbolType!modGetterFirst)); 7278 7279 alias overloads = __traits(getOverloads, module_, "modGetterFirst"); 7280 static assert(overloads.length == 2); 7281 7282 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 7283 static assert( is(PropertyType!(overloads[0]) == int)); 7284 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7285 7286 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 7287 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7288 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7289 } 7290 7291 // void modSetterFirst(int); 7292 // int modSetterFirst(); 7293 { 7294 static assert( is(SymbolType!modSetterFirst == ToFunctionType!(void function(int)))); 7295 static assert( is(PropertyType!modSetterFirst == int)); 7296 static assert( is(typeof(modSetterFirst) == SymbolType!modSetterFirst)); 7297 7298 alias overloads = __traits(getOverloads, module_, "modSetterFirst"); 7299 static assert(overloads.length == 2); 7300 7301 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 7302 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7303 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7304 7305 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 7306 static assert( is(PropertyType!(overloads[1]) == int)); 7307 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7308 } 7309 7310 // void modSetterOnly(string); 7311 // void modSetterOnly(int); 7312 { 7313 static assert( is(SymbolType!modSetterOnly == ToFunctionType!(void function(string)))); 7314 static assert(!__traits(compiles, PropertyType!modSetterOnly)); 7315 static assert( is(typeof(modSetterOnly) == SymbolType!modSetterOnly)); 7316 7317 alias overloads = __traits(getOverloads, module_, "modSetterOnly"); 7318 static assert(overloads.length == 2); 7319 7320 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string)))); 7321 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7322 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7323 7324 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 7325 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7326 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7327 } 7328 7329 // @property int modPropGetterFirst(); 7330 // @property void modPropGetterFirst(int); 7331 { 7332 static assert( is(SymbolType!modPropGetterFirst == ToFunctionType!(int function() @property))); 7333 static assert( is(PropertyType!modPropGetterFirst == int)); 7334 static assert( is(typeof(modPropGetterFirst) == PropertyType!modPropGetterFirst)); 7335 7336 alias overloads = __traits(getOverloads, module_, "modPropGetterFirst"); 7337 static assert(overloads.length == 2); 7338 7339 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property))); 7340 static assert( is(PropertyType!(overloads[0]) == int)); 7341 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 7342 7343 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 7344 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7345 static assert(!__traits(compiles, typeof((overloads[1])))); 7346 } 7347 7348 // @property void modPropSetterFirst(int); 7349 // @property int modPropSetterFirst(); 7350 { 7351 static assert( is(SymbolType!modPropSetterFirst == ToFunctionType!(void function(int) @property))); 7352 static assert( is(PropertyType!modPropSetterFirst == int)); 7353 static assert( is(typeof(modPropSetterFirst) == PropertyType!modPropSetterFirst)); 7354 7355 alias overloads = __traits(getOverloads, module_, "modPropSetterFirst"); 7356 static assert(overloads.length == 2); 7357 7358 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 7359 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7360 static assert(!__traits(compiles, typeof(overloads[0]))); 7361 7362 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 7363 static assert( is(PropertyType!(overloads[1]) == int)); 7364 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 7365 } 7366 7367 // @property void modPropSetterOnly(string); 7368 // @property void modPropSetterOnly(int); 7369 { 7370 static assert( is(SymbolType!modPropSetterOnly == ToFunctionType!(void function(string) @property))); 7371 static assert(!__traits(compiles, PropertyType!modPropSetterOnly)); 7372 static assert(!__traits(compiles, typeof(modPropSetterOnly))); 7373 7374 alias overloads = __traits(getOverloads, module_, "modPropSetterOnly"); 7375 static assert(overloads.length == 2); 7376 7377 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property))); 7378 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7379 static assert(!__traits(compiles, typeof(overloads[0]))); 7380 7381 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 7382 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7383 static assert(!__traits(compiles, typeof(overloads[1]))); 7384 } 7385 7386 // int function() @property modGetterFirstFuncPtr(); 7387 // void modGetterFirstFuncPtr(int function() @property); 7388 { 7389 static assert( is(SymbolType!modGetterFirstFuncPtr == 7390 ToFunctionType!(int function() @property function()))); 7391 static assert( is(PropertyType!modGetterFirstFuncPtr == int function() @property)); 7392 static assert( is(typeof(modGetterFirstFuncPtr) == SymbolType!modGetterFirstFuncPtr)); 7393 7394 alias overloads = __traits(getOverloads, module_, "modGetterFirstFuncPtr"); 7395 static assert(overloads.length == 2); 7396 7397 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property function()))); 7398 static assert( is(PropertyType!(overloads[0]) == int function() @property)); 7399 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7400 7401 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int function() @property)))); 7402 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7403 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7404 } 7405 7406 // void modSetterFirstFuncPtr(int function() @property); 7407 // int function() @property modSetterFirstFuncPtr(); 7408 { 7409 static assert( is(SymbolType!modSetterFirstFuncPtr == 7410 ToFunctionType!(void function(int function() @property)))); 7411 static assert( is(PropertyType!modSetterFirstFuncPtr == int function() @property)); 7412 static assert( is(typeof(modSetterFirstFuncPtr) == SymbolType!modSetterFirstFuncPtr)); 7413 7414 alias overloads = __traits(getOverloads, module_, "modSetterFirstFuncPtr"); 7415 static assert(overloads.length == 2); 7416 7417 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int function() @property)))); 7418 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7419 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7420 7421 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property function()))); 7422 static assert( is(PropertyType!(overloads[1]) == int function() @property)); 7423 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7424 } 7425 7426 // int function() @property modPropGetterFirstFuncPtr() @property; 7427 // void modPropGetterFirstFuncPtr(int function() @property) @property; 7428 { 7429 static assert( is(SymbolType!modPropGetterFirstFuncPtr == 7430 ToFunctionType!(int function() @property function() @property))); 7431 static assert( is(PropertyType!modPropGetterFirstFuncPtr == int function() @property)); 7432 static assert( is(typeof(modPropGetterFirstFuncPtr) == PropertyType!modPropGetterFirstFuncPtr)); 7433 7434 alias overloads = __traits(getOverloads, module_, "modPropGetterFirstFuncPtr"); 7435 static assert(overloads.length == 2); 7436 7437 static assert( is(SymbolType!(overloads[0]) == 7438 ToFunctionType!(int function() @property function() @property))); 7439 static assert( is(PropertyType!(overloads[0]) == int function() @property)); 7440 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 7441 7442 static assert( is(SymbolType!(overloads[1]) == 7443 ToFunctionType!(void function(int function() @property) @property))); 7444 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7445 static assert(!__traits(compiles, typeof((overloads[1])))); 7446 } 7447 7448 // void modPropSetterFirstFuncPtr(int function() @property) @property; 7449 // int function() @property modPropSetterFirstFuncPtr() @property; 7450 { 7451 static assert( is(SymbolType!modPropSetterFirstFuncPtr == 7452 ToFunctionType!(void function(int function() @property) @property))); 7453 static assert( is(PropertyType!modPropSetterFirstFuncPtr == int function() @property)); 7454 static assert( is(typeof(modPropSetterFirstFuncPtr) == PropertyType!modPropSetterFirstFuncPtr)); 7455 7456 alias overloads = __traits(getOverloads, module_, "modPropSetterFirstFuncPtr"); 7457 static assert(overloads.length == 2); 7458 7459 static assert( is(SymbolType!(overloads[0]) == 7460 ToFunctionType!(void function(int function() @property) @property))); 7461 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7462 static assert(!__traits(compiles, typeof(overloads[0]))); 7463 7464 static assert( is(SymbolType!(overloads[1]) == 7465 ToFunctionType!(int function() @property function() @property))); 7466 static assert( is(PropertyType!(overloads[1]) == int function() @property)); 7467 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 7468 } 7469 } 7470 7471 { 7472 static struct S 7473 { 7474 int[] arr1; 7475 immutable bool[] arr2; 7476 7477 void foo(); 7478 static void bar(); 7479 7480 long bob(); 7481 void sally(long); 7482 7483 @property long propGetter(); 7484 @property void propSetter(int[]); 7485 7486 static @property long staticPropGetter(); 7487 static @property void staticPropSetter(int[]); 7488 7489 void func1(); 7490 void func1(int[]); 7491 long func1(int[], long); 7492 7493 long func2(); 7494 long func2(int[]); 7495 int[] func2(int[], long); 7496 7497 void func3(long*); 7498 void func3(real); 7499 int[] func3(long a = 0); 7500 7501 long getterFirst(); 7502 void getterFirst(long); 7503 7504 void setterFirst(long); 7505 long setterFirst(); 7506 7507 void setterOnly(int[]); 7508 void setterOnly(long); 7509 7510 static long staticGetterFirst(); 7511 static void staticGetterFirst(long); 7512 7513 static void staticSetterFirst(long); 7514 static long staticSetterFirst(); 7515 7516 static void staticSetterOnly(int[]); 7517 static void staticSetterOnly(long); 7518 7519 @property long propGetterFirst(); 7520 @property void propGetterFirst(long); 7521 7522 @property void propSetterFirst(long); 7523 @property long propSetterFirst(); 7524 7525 @property void propSetterOnly(int[]); 7526 @property void propSetterOnly(long); 7527 7528 static @property long staticPropGetterFirst(); 7529 static @property void staticPropGetterFirst(long); 7530 7531 static @property void staticPropSetterFirst(long); 7532 static @property long staticPropSetterFirst(); 7533 7534 static @property void staticPropSetterOnly(int[]); 7535 static @property void staticPropSetterOnly(long); 7536 7537 long function() @property getterFirstFuncPtr(); 7538 void getterFirstFuncPtr(long function() @property); 7539 7540 void setterFirstFuncPtr(long function() @property); 7541 long function() @property setterFirstFuncPtr(); 7542 7543 long function() @property propGetterFirstFuncPtr() @property; 7544 void propGetterFirstFuncPtr(long function() @property) @property; 7545 7546 void propSetterFirstFuncPtr(long function() @property) @property; 7547 long function() @property propSetterFirstFuncPtr() @property; 7548 7549 static long delegate() @property staticGetterFirstDel(); 7550 static void staticGetterFirstDel(long delegate() @property); 7551 7552 static void staticSetterFirstDel(long delegate() @property); 7553 static long delegate() @property staticSetterFirstDel(); 7554 7555 static long delegate() @property staticPropGetterFirstDel() @property; 7556 static void staticPropGetterFirstDel(long delegate() @property) @property; 7557 7558 static void staticPropSetterFirstDel(long delegate() @property) @property; 7559 static long delegate() @property staticPropSetterFirstDel() @property; 7560 } 7561 7562 // int[] arr1; 7563 // immutable bool[] arr2; 7564 static assert( is(SymbolType!(S.arr1) == int[])); 7565 static assert( is(PropertyType!(S.arr1) == int[])); 7566 static assert( is(typeof(S.arr1) == int[])); 7567 7568 static assert( is(SymbolType!(S.arr2) == immutable bool[])); 7569 static assert( is(PropertyType!(S.arr2) == immutable bool[])); 7570 static assert( is(typeof(S.arr2) == immutable bool[])); 7571 7572 // void foo(); 7573 static assert( is(SymbolType!(S.foo) == function)); 7574 static assert( is(SymbolType!(S.foo) == ToFunctionType!(void function()))); 7575 static assert(!__traits(compiles, PropertyType!(S.foo))); 7576 static assert( is(typeof(S.foo) == SymbolType!(S.foo))); 7577 7578 //static void bar(); 7579 static assert( is(SymbolType!(S.bar) == function)); 7580 static assert( is(SymbolType!(S.bar) == ToFunctionType!(void function()))); 7581 static assert(!__traits(compiles, PropertyType!(S.bar))); 7582 static assert( is(typeof(S.bar) == SymbolType!(S.bar))); 7583 7584 // long bob(); 7585 static assert( is(SymbolType!(S.bob) == function)); 7586 static assert( is(SymbolType!(S.bob) == ToFunctionType!(long function()))); 7587 static assert( is(PropertyType!(S.bob) == long)); 7588 static assert( is(typeof(S.bob) == SymbolType!(S.bob))); 7589 7590 // void sally(long); 7591 static assert( is(SymbolType!(S.sally) == function)); 7592 static assert( is(SymbolType!(S.sally) == ToFunctionType!(void function(long)))); 7593 static assert(!__traits(compiles, PropertyType!(S.sally))); 7594 static assert( is(typeof(S.sally) == SymbolType!(S.sally))); 7595 7596 // @property long propGetter(); 7597 static assert( is(SymbolType!(S.propGetter) == function)); 7598 static assert( is(SymbolType!(S.propGetter) == ToFunctionType!(long function() @property))); 7599 static assert( is(PropertyType!(S.propGetter) == long)); 7600 static assert( is(typeof(S.propGetter) == PropertyType!(S.propGetter))); 7601 7602 // @property void propSetter(int[]); 7603 static assert( is(SymbolType!(S.propSetter) == function)); 7604 static assert( is(SymbolType!(S.propSetter) == ToFunctionType!(void function(int[]) @property))); 7605 static assert(!__traits(compiles, PropertyType!(S.propSetter))); 7606 static assert(!__traits(compiles, typeof(S.propSetter))); 7607 7608 // static @property long staticPropGetter(); 7609 static assert( is(SymbolType!(S.staticPropGetter) == function)); 7610 static assert( is(SymbolType!(S.staticPropGetter) == ToFunctionType!(long function() @property))); 7611 static assert( is(PropertyType!(S.staticPropGetter) == long)); 7612 static assert( is(typeof(S.staticPropGetter) == PropertyType!(S.staticPropGetter))); 7613 7614 // static @property void staticPropSetter(int[]); 7615 static assert( is(SymbolType!(S.staticPropSetter) == function)); 7616 static assert( is(SymbolType!(S.staticPropSetter) == ToFunctionType!(void function(int[]) @property))); 7617 static assert(!__traits(compiles, PropertyType!(S.staticPropSetter))); 7618 static assert(!__traits(compiles, typeof(S.staticPropSetter))); 7619 7620 // void func1(); 7621 // void func1(int[]); 7622 // long func1(int[], long); 7623 { 7624 static assert( is(SymbolType!(S.func1) == ToFunctionType!(void function()))); 7625 static assert(!__traits(compiles, PropertyType!(S.func1))); 7626 static assert( is(typeof((S.func1)) == SymbolType!(S.func1))); 7627 7628 alias overloads = __traits(getOverloads, S, "func1"); 7629 static assert(overloads.length == 3); 7630 7631 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function()))); 7632 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7633 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7634 7635 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int[])))); 7636 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7637 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7638 7639 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(long function(int[], long)))); 7640 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7641 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7642 } 7643 7644 // long func2(); 7645 // long func2(int[]); 7646 // int[] func2(int[], long); 7647 { 7648 static assert( is(SymbolType!(S.func2) == ToFunctionType!(long function()))); 7649 static assert( is(PropertyType!(S.func2) == long)); 7650 static assert( is(typeof((S.func2)) == SymbolType!(S.func2))); 7651 7652 alias overloads = __traits(getOverloads, S, "func2"); 7653 static assert(overloads.length == 3); 7654 7655 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function()))); 7656 static assert( is(PropertyType!(overloads[0]) == long)); 7657 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7658 7659 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function(int[])))); 7660 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7661 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7662 7663 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(int[], long)))); 7664 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 7665 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7666 } 7667 7668 // void func3(long*); 7669 // void func3(real); 7670 // int[] func3(long a = 0); 7671 { 7672 static assert( is(SymbolType!(S.func3) == ToFunctionType!(void function(long*)))); 7673 static assert( is(PropertyType!(S.func3) == int[])); 7674 static assert( is(typeof((S.func3)) == SymbolType!(S.func3))); 7675 7676 alias overloads = __traits(getOverloads, S, "func3"); 7677 static assert(overloads.length == 3); 7678 7679 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long*)))); 7680 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7681 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7682 7683 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real)))); 7684 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7685 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7686 7687 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(int[] function(long)))); 7688 static assert( is(PropertyType!(overloads[2]) == int[])); 7689 static assert( is(typeof(overloads[2]) == SymbolType!(overloads[2]))); 7690 } 7691 7692 // long getterFirst(); 7693 // void getterFirst(long); 7694 { 7695 static assert( is(SymbolType!(S.getterFirst) == ToFunctionType!(long function()))); 7696 static assert( is(PropertyType!(S.getterFirst) == long)); 7697 static assert( is(typeof((S.getterFirst)) == SymbolType!(S.getterFirst))); 7698 7699 alias overloads = __traits(getOverloads, S, "getterFirst"); 7700 static assert(overloads.length == 2); 7701 7702 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function()))); 7703 static assert( is(PropertyType!(overloads[0]) == long)); 7704 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7705 7706 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 7707 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7708 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7709 } 7710 7711 // void setterFirst(long); 7712 // long setterFirst(); 7713 { 7714 static assert( is(SymbolType!(S.setterFirst) == ToFunctionType!(void function(long)))); 7715 static assert( is(PropertyType!(S.setterFirst) == long)); 7716 static assert( is(typeof((S.setterFirst)) == SymbolType!(S.setterFirst))); 7717 7718 alias overloads = __traits(getOverloads, S, "setterFirst"); 7719 static assert(overloads.length == 2); 7720 7721 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long)))); 7722 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7723 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7724 7725 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function()))); 7726 static assert( is(PropertyType!(overloads[1]) == long)); 7727 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7728 } 7729 7730 // void setterOnly(int[]); 7731 // void setterOnly(long); 7732 { 7733 static assert( is(SymbolType!(S.setterOnly) == ToFunctionType!(void function(int[])))); 7734 static assert(!__traits(compiles, PropertyType!(S.setterOnly))); 7735 static assert( is(typeof((S.setterOnly)) == SymbolType!(S.setterOnly))); 7736 7737 alias overloads = __traits(getOverloads, S, "setterOnly"); 7738 static assert(overloads.length == 2); 7739 7740 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[])))); 7741 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7742 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7743 7744 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 7745 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7746 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7747 } 7748 7749 // long staticGetterFirst(); 7750 // void staticGetterFirst(long); 7751 { 7752 static assert( is(SymbolType!(S.staticGetterFirst) == ToFunctionType!(long function()))); 7753 static assert( is(PropertyType!(S.staticGetterFirst) == long)); 7754 static assert( is(typeof((S.staticGetterFirst)) == SymbolType!(S.staticGetterFirst))); 7755 7756 alias overloads = __traits(getOverloads, S, "staticGetterFirst"); 7757 static assert(overloads.length == 2); 7758 7759 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function()))); 7760 static assert( is(PropertyType!(overloads[0]) == long)); 7761 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7762 7763 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 7764 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7765 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7766 } 7767 7768 // void staticSetterFirst(long); 7769 // long staticSetterFirst(); 7770 { 7771 static assert( is(SymbolType!(S.staticSetterFirst) == ToFunctionType!(void function(long)))); 7772 static assert( is(PropertyType!(S.staticSetterFirst) == long)); 7773 static assert( is(typeof((S.staticSetterFirst)) == SymbolType!(S.staticSetterFirst))); 7774 7775 alias overloads = __traits(getOverloads, S, "staticSetterFirst"); 7776 static assert(overloads.length == 2); 7777 7778 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long)))); 7779 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7780 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7781 7782 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function()))); 7783 static assert( is(PropertyType!(overloads[1]) == long)); 7784 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7785 } 7786 7787 // void staticSetterOnly(int[]); 7788 // void staticSetterOnly(long); 7789 { 7790 static assert( is(SymbolType!(S.staticSetterOnly) == ToFunctionType!(void function(int[])))); 7791 static assert(!__traits(compiles, PropertyType!(S.staticSetterOnly))); 7792 static assert( is(typeof((S.staticSetterOnly)) == SymbolType!(S.staticSetterOnly))); 7793 7794 alias overloads = __traits(getOverloads, S, "staticSetterOnly"); 7795 static assert(overloads.length == 2); 7796 7797 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[])))); 7798 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7799 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7800 7801 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long)))); 7802 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7803 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7804 } 7805 7806 // @property long propGetterFirst(); 7807 // @property void propGetterFirst(long); 7808 { 7809 static assert( is(SymbolType!(S.propGetterFirst) == ToFunctionType!(long function() @property))); 7810 static assert( is(PropertyType!(S.propGetterFirst) == long)); 7811 static assert( is(typeof((S.propGetterFirst)) == PropertyType!(S.propGetterFirst))); 7812 7813 alias overloads = __traits(getOverloads, S, "propGetterFirst"); 7814 static assert(overloads.length == 2); 7815 7816 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 7817 static assert( is(PropertyType!(overloads[0]) == long)); 7818 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 7819 7820 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 7821 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7822 static assert(!__traits(compiles, typeof((overloads[1])))); 7823 } 7824 7825 // @property void propSetterFirst(long); 7826 // @property long propSetterFirst(); 7827 { 7828 static assert( is(SymbolType!(S.propSetterFirst) == ToFunctionType!(void function(long) @property))); 7829 static assert( is(PropertyType!(S.propSetterFirst) == long)); 7830 static assert( is(typeof((S.propSetterFirst)) == PropertyType!(S.propSetterFirst))); 7831 7832 alias overloads = __traits(getOverloads, S, "propSetterFirst"); 7833 static assert(overloads.length == 2); 7834 7835 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property))); 7836 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7837 static assert(!__traits(compiles, typeof(overloads[0]))); 7838 7839 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property))); 7840 static assert( is(PropertyType!(overloads[1]) == long)); 7841 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 7842 } 7843 7844 // @property void propSetterOnly(int[]); 7845 // @property void propSetterOnly(long); 7846 { 7847 static assert( is(SymbolType!(S.propSetterOnly) == ToFunctionType!(void function(int[]) @property))); 7848 static assert(!__traits(compiles, PropertyType!(S.propSetterOnly))); 7849 static assert(!__traits(compiles, typeof((S.propSetterOnly)))); 7850 7851 alias overloads = __traits(getOverloads, S, "propSetterOnly"); 7852 static assert(overloads.length == 2); 7853 7854 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property))); 7855 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7856 static assert(!__traits(compiles, typeof(overloads[0]))); 7857 7858 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 7859 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7860 static assert(!__traits(compiles, typeof(overloads[1]))); 7861 } 7862 7863 // @property long staticPropGetterFirst(); 7864 // @property void staticPropGetterFirst(long); 7865 { 7866 static assert( is(SymbolType!(S.staticPropGetterFirst) == ToFunctionType!(long function() @property))); 7867 static assert( is(PropertyType!(S.staticPropGetterFirst) == long)); 7868 static assert( is(typeof((S.staticPropGetterFirst)) == PropertyType!(S.staticPropGetterFirst))); 7869 7870 alias overloads = __traits(getOverloads, S, "staticPropGetterFirst"); 7871 static assert(overloads.length == 2); 7872 7873 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 7874 static assert( is(PropertyType!(overloads[0]) == long)); 7875 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 7876 7877 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 7878 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7879 static assert(!__traits(compiles, typeof((overloads[1])))); 7880 } 7881 7882 // @property void staticPropSetterFirst(long); 7883 // @property long staticPropSetterFirst(); 7884 { 7885 static assert( is(SymbolType!(S.staticPropSetterFirst) == ToFunctionType!(void function(long) @property))); 7886 static assert( is(PropertyType!(S.staticPropSetterFirst) == long)); 7887 static assert( is(typeof((S.staticPropSetterFirst)) == PropertyType!(S.staticPropSetterFirst))); 7888 7889 alias overloads = __traits(getOverloads, S, "staticPropSetterFirst"); 7890 static assert(overloads.length == 2); 7891 7892 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long) @property))); 7893 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7894 static assert(!__traits(compiles, typeof(overloads[0]))); 7895 7896 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property))); 7897 static assert( is(PropertyType!(overloads[1]) == long)); 7898 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 7899 } 7900 7901 // @property void staticPropSetterOnly(int[]); 7902 // @property void staticPropSetterOnly(long); 7903 { 7904 static assert( is(SymbolType!(S.staticPropSetterOnly) == ToFunctionType!(void function(int[]) @property))); 7905 static assert(!__traits(compiles, PropertyType!(S.staticPropSetterOnly))); 7906 static assert(!__traits(compiles, typeof((S.staticPropSetterOnly)))); 7907 7908 alias overloads = __traits(getOverloads, S, "staticPropSetterOnly"); 7909 static assert(overloads.length == 2); 7910 7911 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int[]) @property))); 7912 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7913 static assert(!__traits(compiles, typeof(overloads[0]))); 7914 7915 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long) @property))); 7916 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7917 static assert(!__traits(compiles, typeof(overloads[1]))); 7918 } 7919 7920 // long function() @property getterFirstFuncPtr(); 7921 // void getterFirstFuncPtr(long function() @property); 7922 { 7923 static assert( is(SymbolType!(S.getterFirstFuncPtr) == 7924 ToFunctionType!(long function() @property function()))); 7925 static assert( is(PropertyType!(S.getterFirstFuncPtr) == long function() @property)); 7926 static assert( is(typeof((S.getterFirstFuncPtr)) == SymbolType!(S.getterFirstFuncPtr))); 7927 7928 alias overloads = __traits(getOverloads, S, "getterFirstFuncPtr"); 7929 static assert(overloads.length == 2); 7930 7931 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property function()))); 7932 static assert( is(PropertyType!(overloads[0]) == long function() @property)); 7933 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7934 7935 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long function() @property)))); 7936 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7937 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7938 } 7939 7940 // void setterFirstFuncPtr(long function() @property); 7941 // long function() @property setterFirstFuncPtr(); 7942 { 7943 static assert( is(SymbolType!(S.setterFirstFuncPtr) == 7944 ToFunctionType!(void function(long function() @property)))); 7945 static assert( is(PropertyType!(S.setterFirstFuncPtr) == long function() @property)); 7946 static assert( is(typeof((S.setterFirstFuncPtr)) == SymbolType!(S.setterFirstFuncPtr))); 7947 7948 alias overloads = __traits(getOverloads, S, "setterFirstFuncPtr"); 7949 static assert(overloads.length == 2); 7950 7951 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long function() @property)))); 7952 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7953 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 7954 7955 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long function() @property function()))); 7956 static assert( is(PropertyType!(overloads[1]) == long function() @property)); 7957 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 7958 } 7959 7960 // long function() @property propGetterFirstFuncPtr() @property; 7961 // void propGetterFirstFuncPtr(long function() @property) @property; 7962 { 7963 static assert( is(SymbolType!(S.propGetterFirstFuncPtr) == 7964 ToFunctionType!(long function() @property function() @property))); 7965 static assert( is(PropertyType!(S.propGetterFirstFuncPtr) == long function() @property)); 7966 static assert( is(typeof((S.propGetterFirstFuncPtr)) == PropertyType!(S.propGetterFirstFuncPtr))); 7967 7968 alias overloads = __traits(getOverloads, S, "propGetterFirstFuncPtr"); 7969 static assert(overloads.length == 2); 7970 7971 static assert( is(SymbolType!(overloads[0]) == 7972 ToFunctionType!(long function() @property function() @property))); 7973 static assert( is(PropertyType!(overloads[0]) == long function() @property)); 7974 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 7975 7976 static assert( is(SymbolType!(overloads[1]) == 7977 ToFunctionType!(void function(long function() @property) @property))); 7978 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 7979 static assert(!__traits(compiles, typeof((overloads[1])))); 7980 } 7981 7982 // void propSetterFirstFuncPtr(long function() @property) @property; 7983 // long function() @property propSetterFirstFuncPtr() @property; 7984 { 7985 static assert( is(SymbolType!(S.propSetterFirstFuncPtr) == 7986 ToFunctionType!(void function(long function() @property) @property))); 7987 static assert( is(PropertyType!(S.propSetterFirstFuncPtr) == long function() @property)); 7988 static assert( is(typeof((S.propSetterFirstFuncPtr)) == PropertyType!(S.propSetterFirstFuncPtr))); 7989 7990 alias overloads = __traits(getOverloads, S, "propSetterFirstFuncPtr"); 7991 static assert(overloads.length == 2); 7992 7993 static assert( is(SymbolType!(overloads[0]) == 7994 ToFunctionType!(void function(long function() @property) @property))); 7995 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 7996 static assert(!__traits(compiles, typeof(overloads[0]))); 7997 7998 static assert( is(SymbolType!(overloads[1]) == 7999 ToFunctionType!(long function() @property function() @property))); 8000 static assert( is(PropertyType!(overloads[1]) == long function() @property)); 8001 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8002 } 8003 8004 // long function() @property staticGetterFirstDel(); 8005 // void staticGetterFirstDel(long function() @property); 8006 { 8007 static assert( is(SymbolType!(S.staticGetterFirstDel) == 8008 ToFunctionType!(long delegate() @property function()))); 8009 static assert( is(PropertyType!(S.staticGetterFirstDel) == long delegate() @property)); 8010 static assert( is(typeof((S.staticGetterFirstDel)) == SymbolType!(S.staticGetterFirstDel))); 8011 8012 alias overloads = __traits(getOverloads, S, "staticGetterFirstDel"); 8013 static assert(overloads.length == 2); 8014 8015 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long delegate() @property function()))); 8016 static assert( is(PropertyType!(overloads[0]) == long delegate() @property)); 8017 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8018 8019 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(long delegate() @property)))); 8020 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8021 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8022 } 8023 8024 // void setterFirstDel(long function() @property); 8025 // long function() @property setterFirstDel(); 8026 { 8027 static assert( is(SymbolType!(S.staticSetterFirstDel) == 8028 ToFunctionType!(void function(long delegate() @property)))); 8029 static assert( is(PropertyType!(S.staticSetterFirstDel) == long delegate() @property)); 8030 static assert( is(typeof((S.staticSetterFirstDel)) == SymbolType!(S.staticSetterFirstDel))); 8031 8032 alias overloads = __traits(getOverloads, S, "staticSetterFirstDel"); 8033 static assert(overloads.length == 2); 8034 8035 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(long delegate() @property)))); 8036 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8037 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8038 8039 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(long delegate() @property function()))); 8040 static assert( is(PropertyType!(overloads[1]) == long delegate() @property)); 8041 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8042 } 8043 8044 // long function() @property staticPropGetterFirstDel() @property; 8045 // void staticPropGetterFirstDel(long function() @property) @property; 8046 { 8047 static assert( is(SymbolType!(S.staticPropGetterFirstDel) == 8048 ToFunctionType!(long delegate() @property function() @property))); 8049 static assert( is(PropertyType!(S.staticPropGetterFirstDel) == long delegate() @property)); 8050 static assert( is(typeof((S.staticPropGetterFirstDel)) == PropertyType!(S.staticPropGetterFirstDel))); 8051 8052 alias overloads = __traits(getOverloads, S, "staticPropGetterFirstDel"); 8053 static assert(overloads.length == 2); 8054 8055 static assert( is(SymbolType!(overloads[0]) == 8056 ToFunctionType!(long delegate() @property function() @property))); 8057 static assert( is(PropertyType!(overloads[0]) == long delegate() @property)); 8058 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8059 8060 static assert( is(SymbolType!(overloads[1]) == 8061 ToFunctionType!(void function(long delegate() @property) @property))); 8062 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8063 static assert(!__traits(compiles, typeof((overloads[1])))); 8064 } 8065 8066 // void propSetterFirstDel(long function() @property) @property; 8067 // long function() @property propSetterFirstDel() @property; 8068 { 8069 static assert( is(SymbolType!(S.staticPropSetterFirstDel) == 8070 ToFunctionType!(void function(long delegate() @property) @property))); 8071 static assert( is(PropertyType!(S.staticPropSetterFirstDel) == long delegate() @property)); 8072 static assert( is(typeof((S.staticPropSetterFirstDel)) == PropertyType!(S.staticPropSetterFirstDel))); 8073 8074 alias overloads = __traits(getOverloads, S, "staticPropSetterFirstDel"); 8075 static assert(overloads.length == 2); 8076 8077 static assert( is(SymbolType!(overloads[0]) == 8078 ToFunctionType!(void function(long delegate() @property) @property))); 8079 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8080 static assert(!__traits(compiles, typeof(overloads[0]))); 8081 8082 static assert( is(SymbolType!(overloads[1]) == 8083 ToFunctionType!(long delegate() @property function() @property))); 8084 static assert( is(PropertyType!(overloads[1]) == long delegate() @property)); 8085 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8086 } 8087 } 8088 { 8089 static interface I 8090 { 8091 void foo(); 8092 static void bar(); 8093 8094 int func1(); 8095 void func1(int); 8096 8097 void func2(int); 8098 int func2(); 8099 8100 @property void prop1(int); 8101 @property int prop1(); 8102 8103 @property int prop2(); 8104 @property void prop2(int); 8105 8106 static @property string staticProp(); 8107 static @property void staticProp(real); 8108 8109 @property void extraProp(string); 8110 8111 int defaultArg1(string str = "foo"); 8112 void defaultArg1(int, string str = "foo"); 8113 8114 void defaultArg2(int, string str = "foo"); 8115 int defaultArg2(string str = "foo"); 8116 8117 @property int defaultArgProp1(string str = "foo"); 8118 @property void defaultArgProp1(int, string str = "foo"); 8119 8120 @property void defaultArgProp2(int, string str = "foo"); 8121 @property int defaultArgProp2(string str = "foo"); 8122 8123 string defaultArgInDerived1(int); 8124 void defaultArgInDerived1(string, int); 8125 8126 void defaultArgInDerived2(string, int); 8127 string defaultArgInDerived2(int); 8128 8129 @property string defaultArgInDerivedProp1(int); 8130 @property void defaultArgInDerivedProp1(string, int); 8131 8132 @property void defaultArgInDerivedProp2(string, int); 8133 @property string defaultArgInDerivedProp2(int); 8134 } 8135 8136 { 8137 // void foo() 8138 static assert( is(SymbolType!(I.foo) == ToFunctionType!(void function()))); 8139 static assert(!__traits(compiles, PropertyType!(I.foo))); 8140 static assert( is(typeof(I.foo) == SymbolType!(I.foo))); 8141 8142 // static void bar() 8143 static assert( is(SymbolType!(I.bar) == ToFunctionType!(void function()))); 8144 static assert(!__traits(compiles, PropertyType!(I.bar))); 8145 static assert( is(typeof(I.bar) == SymbolType!(I.bar))); 8146 8147 // int func1(); 8148 // void func1(int); 8149 { 8150 static assert( is(SymbolType!(I.func1) == ToFunctionType!(int function()))); 8151 static assert( is(PropertyType!(I.func1) == int)); 8152 static assert( is(typeof(I.func1) == SymbolType!(I.func1))); 8153 8154 alias overloads = __traits(getOverloads, I, "func1"); 8155 static assert(overloads.length == 2); 8156 8157 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 8158 static assert( is(PropertyType!(overloads[0]) == int)); 8159 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8160 8161 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 8162 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8163 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8164 } 8165 8166 // void func2(int); 8167 // int func2(); 8168 { 8169 static assert( is(SymbolType!(I.func2) == ToFunctionType!(void function(int)))); 8170 static assert( is(PropertyType!(I.func2) == int)); 8171 static assert( is(typeof(I.func2) == SymbolType!(I.func2))); 8172 8173 alias overloads = __traits(getOverloads, I, "func2"); 8174 static assert(overloads.length == 2); 8175 8176 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 8177 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8178 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8179 8180 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 8181 static assert( is(PropertyType!(overloads[1]) == int)); 8182 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8183 } 8184 8185 // @property void prop1(int); 8186 // @property int prop1(); 8187 { 8188 static assert( is(SymbolType!(I.prop1) == ToFunctionType!(void function(int) @property))); 8189 static assert( is(PropertyType!(I.prop1) == int)); 8190 static assert( is(typeof(I.prop1) == PropertyType!(I.prop1))); 8191 8192 alias overloads = __traits(getOverloads, I, "prop1"); 8193 static assert(overloads.length == 2); 8194 8195 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 8196 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8197 static assert(!__traits(compiles, typeof(overloads[0]))); 8198 8199 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 8200 static assert( is(PropertyType!(overloads[1]) == int)); 8201 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8202 } 8203 8204 // @property int prop2(); 8205 // @property void prop2(int); 8206 { 8207 static assert( is(SymbolType!(I.prop2) == ToFunctionType!(int function() @property))); 8208 static assert( is(PropertyType!(I.prop2) == int)); 8209 static assert( is(typeof(I.prop2) == PropertyType!(I.prop2))); 8210 8211 alias overloads = __traits(getOverloads, I, "prop2"); 8212 static assert(overloads.length == 2); 8213 8214 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property))); 8215 static assert( is(PropertyType!(overloads[0]) == int)); 8216 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8217 8218 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 8219 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8220 static assert(!__traits(compiles, typeof(overloads[1]))); 8221 } 8222 8223 // static @property string staticProp(); 8224 // static @property void staticProp(real); 8225 { 8226 static assert( is(SymbolType!(I.staticProp) == ToFunctionType!(string function() @property))); 8227 static assert( is(PropertyType!(I.staticProp) == string)); 8228 static assert( is(typeof(I.staticProp) == PropertyType!(I.staticProp))); 8229 8230 alias overloads = __traits(getOverloads, I, "staticProp"); 8231 static assert(overloads.length == 2); 8232 8233 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 8234 static assert( is(PropertyType!(overloads[0]) == string)); 8235 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8236 8237 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 8238 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8239 static assert(!__traits(compiles, typeof(overloads[1]))); 8240 } 8241 8242 // @property void extraProp(string); 8243 { 8244 static assert( is(SymbolType!(I.extraProp) == ToFunctionType!(void function(string) @property))); 8245 static assert(!__traits(compiles, PropertyType!(I.extraProp))); 8246 static assert(!__traits(compiles, typeof(I.extraProp))); 8247 8248 alias overloads = __traits(getOverloads, I, "extraProp"); 8249 static assert(overloads.length == 1); 8250 8251 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property))); 8252 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8253 static assert(!__traits(compiles, typeof(overloads[0]))); 8254 } 8255 8256 // int defaultArg1(string str = "foo"); 8257 // void defaultArg1(int, string str = "foo"); 8258 { 8259 static assert( is(SymbolType!(I.defaultArg1) == ToFunctionType!(int function(string)))); 8260 static assert( is(PropertyType!(I.defaultArg1) == int)); 8261 static assert( is(typeof(I.defaultArg1) == SymbolType!(I.defaultArg1))); 8262 8263 alias overloads = __traits(getOverloads, I, "defaultArg1"); 8264 static assert(overloads.length == 2); 8265 8266 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string)))); 8267 static assert( is(PropertyType!(overloads[0]) == int)); 8268 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8269 8270 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string)))); 8271 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8272 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8273 } 8274 8275 // void defaultArg2(int, string str = "foo"); 8276 // int defaultArg2(string str = "foo"); 8277 { 8278 static assert( is(SymbolType!(I.defaultArg2) == ToFunctionType!(void function(int, string)))); 8279 static assert( is(PropertyType!(I.defaultArg2) == int)); 8280 static assert( is(typeof(I.defaultArg2) == SymbolType!(I.defaultArg2))); 8281 8282 alias overloads = __traits(getOverloads, I, "defaultArg2"); 8283 static assert(overloads.length == 2); 8284 8285 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 8286 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8287 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8288 8289 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 8290 static assert( is(PropertyType!(overloads[1]) == int)); 8291 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8292 } 8293 8294 // @property int defaultArgProp1(string str = "foo"); 8295 // @property void defaultArgProp1(int, string str = "foo"); 8296 { 8297 static assert( is(SymbolType!(I.defaultArgProp1) == ToFunctionType!(int function(string) @property))); 8298 static assert( is(PropertyType!(I.defaultArgProp1) == int)); 8299 static assert( is(typeof(I.defaultArgProp1) == PropertyType!(I.defaultArgProp1))); 8300 8301 alias overloads = __traits(getOverloads, I, "defaultArgProp1"); 8302 static assert(overloads.length == 2); 8303 8304 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 8305 static assert( is(PropertyType!(overloads[0]) == int)); 8306 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8307 8308 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 8309 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8310 static assert(!__traits(compiles, typeof(overloads[1]))); 8311 } 8312 8313 // @property void defaultArgProp2(int, string str = "foo"); 8314 // @property int defaultArgProp2(string str = "foo"); 8315 { 8316 static assert( is(SymbolType!(I.defaultArgProp2) == 8317 ToFunctionType!(void function(int, string) @property))); 8318 static assert( is(PropertyType!(I.defaultArgProp2) == int)); 8319 static assert( is(typeof(I.defaultArgProp2) == PropertyType!(I.defaultArgProp2))); 8320 8321 alias overloads = __traits(getOverloads, I, "defaultArgProp2"); 8322 static assert(overloads.length == 2); 8323 8324 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 8325 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8326 static assert(!__traits(compiles, typeof(overloads[0]))); 8327 8328 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 8329 static assert( is(PropertyType!(overloads[1]) == int)); 8330 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8331 } 8332 8333 // string defaultArgInDerived1(int); 8334 // void defaultArgInDerived1(string, int); 8335 { 8336 static assert( is(SymbolType!(I.defaultArgInDerived1) == ToFunctionType!(string function(int)))); 8337 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived1))); 8338 static assert( is(typeof(I.defaultArgInDerived1) == SymbolType!(I.defaultArgInDerived1))); 8339 8340 alias overloads = __traits(getOverloads, I, "defaultArgInDerived1"); 8341 static assert(overloads.length == 2); 8342 8343 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 8344 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8345 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8346 8347 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 8348 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8349 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8350 } 8351 8352 // void defaultArgInDerived2(string, int); 8353 // string defaultArgInDerived2(int); 8354 { 8355 static assert( is(SymbolType!(I.defaultArgInDerived2) == ToFunctionType!(void function(string, int)))); 8356 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerived2))); 8357 static assert( is(typeof(I.defaultArgInDerived2) == SymbolType!(I.defaultArgInDerived2))); 8358 8359 alias overloads = __traits(getOverloads, I, "defaultArgInDerived2"); 8360 static assert(overloads.length == 2); 8361 8362 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 8363 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8364 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8365 8366 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 8367 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8368 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8369 } 8370 8371 // @property string defaultArgInDerivedProp1(int); 8372 // @property void defaultArgInDerivedProp1(string, int); 8373 { 8374 static assert( is(SymbolType!(I.defaultArgInDerivedProp1) == 8375 ToFunctionType!(string function(int) @property))); 8376 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp1))); 8377 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp1))); 8378 8379 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp1"); 8380 static assert(overloads.length == 2); 8381 8382 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 8383 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8384 static assert(!__traits(compiles, typeof(overloads[0]))); 8385 8386 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 8387 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8388 static assert(!__traits(compiles, typeof(overloads[0]))); 8389 } 8390 8391 // @property void defaultArgInDerivedProp2(string, int); 8392 // @property string defaultArgInDerivedProp2(int); 8393 { 8394 static assert( is(SymbolType!(I.defaultArgInDerivedProp2) == 8395 ToFunctionType!(void function(string, int) @property))); 8396 static assert(!__traits(compiles, PropertyType!(I.defaultArgInDerivedProp2))); 8397 static assert(!__traits(compiles, typeof(I.defaultArgInDerivedProp2))); 8398 8399 alias overloads = __traits(getOverloads, I, "defaultArgInDerivedProp2"); 8400 static assert(overloads.length == 2); 8401 8402 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, 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!(string function(int) @property))); 8407 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8408 static assert(!__traits(compiles, typeof(overloads[1]))); 8409 } 8410 } 8411 8412 // For whatever reason, the virtual functions have to have bodies, or 8413 // the linker complains, even though the functions aren't actually 8414 // called anywhere, but having them implement the functions which are in 8415 // the interface at least gets rid of the attribute inference. 8416 static class C1 : I 8417 { 8418 shared int i; 8419 string s; 8420 8421 override void foo() {} 8422 8423 // This shadows the one in the interface, and it has a different 8424 // signature, so it makes sure that we're getting the right one. 8425 static int bar(); 8426 8427 final void baz(); 8428 8429 override int func1() { return 0; } 8430 override void func1(int) {} 8431 8432 override void func2(int) {} 8433 override int func2() { return 0; } 8434 8435 override @property void prop1(int) {} 8436 override @property int prop1() { return 0; } 8437 8438 override @property int prop2() { return 0; } 8439 override @property void prop2(int) {} 8440 8441 override @property void extraProp(string) {} 8442 @property bool extraProp() { return true; } 8443 8444 override int defaultArg1(string str = "foo") { return 42; } 8445 override void defaultArg1(int, string str = "foo") {} 8446 8447 // This tests the case where the derived type doesn't provide 8448 // default arguments even though the interface does. 8449 override void defaultArg2(int, string str) {} 8450 override int defaultArg2(string str) { return 42; } 8451 8452 override @property int defaultArgProp1(string str = "foo") { return 42; } 8453 override @property void defaultArgProp1(int, string str = "foo") {} 8454 8455 // This tests the case where the derived type doesn't provide 8456 // default arguments even though the interface does. 8457 override @property void defaultArgProp2(int, string str) {} 8458 override @property int defaultArgProp2(string str) { return 42; } 8459 8460 override string defaultArgInDerived1(int i = 0) { return ""; } 8461 override void defaultArgInDerived1(string, int i = 0) {} 8462 8463 override void defaultArgInDerived2(string, int i = 0) {} 8464 override string defaultArgInDerived2(int i = 0) { return ""; } 8465 8466 @property string defaultArgInDerivedProp1(int i = 0) { return ""; } 8467 @property void defaultArgInDerivedProp1(string, int i = 0) {} 8468 8469 @property void defaultArgInDerivedProp2(string, int i = 0) {} 8470 @property string defaultArgInDerivedProp2(int i = 0) { return ""; } 8471 } 8472 8473 { 8474 // shared int i; 8475 // string s; 8476 static assert( is(SymbolType!(C1.i) == shared int)); 8477 static assert( is(PropertyType!(C1.i) == shared int)); 8478 static assert( is(typeof(C1.i) == shared int)); 8479 8480 static assert( is(SymbolType!(C1.s) == string)); 8481 static assert( is(PropertyType!(C1.s) == string)); 8482 static assert( is(typeof(C1.s) == string)); 8483 8484 // override void foo() 8485 static assert( is(SymbolType!(C1.foo) == ToFunctionType!(void function()))); 8486 static assert(!__traits(compiles, PropertyType!(C1.foo))); 8487 static assert( is(typeof(C1.foo) == SymbolType!(C1.foo))); 8488 8489 // static int bar() 8490 static assert( is(SymbolType!(C1.bar) == ToFunctionType!(int function()))); 8491 static assert( is(PropertyType!(C1.bar) == int)); 8492 static assert( is(typeof(C1.bar) == SymbolType!(C1.bar))); 8493 8494 // void baz() 8495 static assert( is(SymbolType!(C1.baz) == ToFunctionType!(void function()))); 8496 static assert(!__traits(compiles, PropertyType!(C1.baz))); 8497 static assert( is(typeof(C1.baz) == SymbolType!(C1.baz))); 8498 8499 // override int func1(); 8500 // override void func1(int); 8501 { 8502 static assert( is(SymbolType!(C1.func1) == ToFunctionType!(int function()))); 8503 static assert( is(PropertyType!(C1.func1) == int)); 8504 static assert( is(typeof(C1.func1) == SymbolType!(C1.func1))); 8505 8506 alias overloads = __traits(getOverloads, C1, "func1"); 8507 static assert(overloads.length == 2); 8508 8509 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 8510 static assert( is(PropertyType!(overloads[0]) == int)); 8511 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8512 8513 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 8514 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8515 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8516 } 8517 8518 // override void func2(int); 8519 // override int func2(); 8520 { 8521 static assert( is(SymbolType!(C1.func2) == ToFunctionType!(void function(int)))); 8522 static assert( is(PropertyType!(C1.func2) == int)); 8523 static assert( is(typeof(C1.func2) == SymbolType!(C1.func2))); 8524 8525 alias overloads = __traits(getOverloads, C1, "func2"); 8526 static assert(overloads.length == 2); 8527 8528 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 8529 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8530 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8531 8532 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 8533 static assert( is(PropertyType!(overloads[1]) == int)); 8534 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8535 } 8536 8537 // override @property void prop1(int); 8538 // override @property int prop1(); 8539 { 8540 static assert( is(SymbolType!(C1.prop1) == ToFunctionType!(void function(int) @property))); 8541 static assert( is(PropertyType!(C1.prop1) == int)); 8542 static assert( is(typeof(C1.prop1) == PropertyType!(C1.prop1))); 8543 8544 alias overloads = __traits(getOverloads, C1, "prop1"); 8545 static assert(overloads.length == 2); 8546 8547 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 8548 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8549 static assert(!__traits(compiles, typeof(overloads[0]))); 8550 8551 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 8552 static assert( is(PropertyType!(overloads[1]) == int)); 8553 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 8554 } 8555 8556 // override @property int prop2(); 8557 // override @property void prop2(int); 8558 { 8559 static assert( is(SymbolType!(C1.prop2) == ToFunctionType!(int function() @property))); 8560 static assert( is(PropertyType!(C1.prop2) == int)); 8561 static assert( is(typeof(C1.prop2) == PropertyType!(C1.prop2))); 8562 8563 alias overloads = __traits(getOverloads, C1, "prop2"); 8564 static assert(overloads.length == 2); 8565 8566 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function() @property))); 8567 static assert( is(PropertyType!(overloads[0]) == int)); 8568 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8569 8570 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int) @property))); 8571 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8572 static assert(!__traits(compiles, typeof(overloads[1]))); 8573 } 8574 8575 // Actually on I, not C1. 8576 // static @property string staticProp(); 8577 // static @property void staticProp(real); 8578 { 8579 static assert( is(SymbolType!(C1.staticProp) == ToFunctionType!(string function() @property))); 8580 static assert( is(PropertyType!(C1.staticProp) == string)); 8581 static assert( is(typeof(C1.staticProp) == PropertyType!(C1.staticProp))); 8582 8583 alias overloads = __traits(getOverloads, C1, "staticProp"); 8584 static assert(overloads.length == 2); 8585 8586 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 8587 static assert( is(PropertyType!(overloads[0]) == string)); 8588 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8589 8590 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 8591 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8592 static assert(!__traits(compiles, typeof(overloads[1]))); 8593 } 8594 8595 // override @property void extraProp(string); 8596 // @property bool extraProp() { return true; } 8597 { 8598 static assert( is(SymbolType!(C1.extraProp) == ToFunctionType!(void function(string) @property))); 8599 static assert( is(PropertyType!(C1.extraProp) == bool)); 8600 static assert( is(typeof(C1.extraProp) == bool)); 8601 8602 alias overloads = __traits(getOverloads, C1, "extraProp"); 8603 static assert(overloads.length == 2); 8604 8605 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string) @property))); 8606 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8607 static assert(!__traits(compiles, typeof(overloads[0]))); 8608 8609 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(bool function() @property))); 8610 static assert( is(PropertyType!(overloads[1]) == bool)); 8611 static assert( is(typeof(overloads[1]) == bool)); 8612 } 8613 8614 // override int defaultArg1(string str = "foo"); 8615 // override void defaultArg1(int, string str = "foo"); 8616 { 8617 static assert( is(SymbolType!(C1.defaultArg1) == ToFunctionType!(int function(string)))); 8618 static assert( is(PropertyType!(C1.defaultArg1) == int)); 8619 static assert( is(typeof(C1.defaultArg1) == SymbolType!(C1.defaultArg1))); 8620 8621 alias overloads = __traits(getOverloads, C1, "defaultArg1"); 8622 static assert(overloads.length == 2); 8623 8624 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string)))); 8625 static assert( is(PropertyType!(overloads[0]) == int)); 8626 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8627 8628 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string)))); 8629 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8630 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8631 } 8632 8633 // I provides default arguments, but C1 does not. 8634 // override void defaultArg2(int, string); 8635 // override int defaultArg2(string); 8636 { 8637 static assert( is(SymbolType!(C1.defaultArg2) == ToFunctionType!(void function(int, string)))); 8638 static assert(!__traits(compiles, PropertyType!(C1.defaultArg2))); 8639 static assert( is(typeof(C1.defaultArg2) == SymbolType!(C1.defaultArg2))); 8640 8641 alias overloads = __traits(getOverloads, C1, "defaultArg2"); 8642 static assert(overloads.length == 2); 8643 8644 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 8645 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8646 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8647 8648 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 8649 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8650 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8651 } 8652 8653 // override @property int defaultArgProp1(string str = "foo"); 8654 // override @property void defaultArgProp1(int, string str = "foo"); 8655 { 8656 static assert( is(SymbolType!(C1.defaultArgProp1) == ToFunctionType!(int function(string) @property))); 8657 static assert( is(PropertyType!(C1.defaultArgProp1) == int)); 8658 static assert( is(typeof(C1.defaultArgProp1) == PropertyType!(C1.defaultArgProp1))); 8659 8660 alias overloads = __traits(getOverloads, C1, "defaultArgProp1"); 8661 static assert(overloads.length == 2); 8662 8663 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 8664 static assert( is(PropertyType!(overloads[0]) == int)); 8665 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8666 8667 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 8668 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8669 static assert(!__traits(compiles, typeof(overloads[1]))); 8670 } 8671 8672 // I provides default arguments, but C1 does not. 8673 // override @property void defaultArgProp2(int, string str); 8674 // override @property int defaultArgProp2(string str); 8675 { 8676 static assert( is(SymbolType!(C1.defaultArgProp2) == 8677 ToFunctionType!(void function(int, string) @property))); 8678 static assert(!__traits(compiles, PropertyType!(C1.defaultArgProp2))); 8679 static assert(!__traits(compiles, typeof(C1.defaultArgProp2))); 8680 8681 alias overloads = __traits(getOverloads, C1, "defaultArgProp2"); 8682 static assert(overloads.length == 2); 8683 8684 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 8685 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8686 static assert(!__traits(compiles, typeof(overloads[0]))); 8687 8688 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 8689 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8690 static assert(!__traits(compiles, typeof(overloads[1]))); 8691 } 8692 8693 // I does not provide default arguments, but C1 does. 8694 // override string defaultArgInDerived1(int i = 0); 8695 // override void defaultArgInDerived1(string, int i = 0); 8696 { 8697 static assert( is(SymbolType!(C1.defaultArgInDerived1) == ToFunctionType!(string function(int)))); 8698 static assert( is(PropertyType!(C1.defaultArgInDerived1) == string)); 8699 static assert( is(typeof(C1.defaultArgInDerived1) == SymbolType!(C1.defaultArgInDerived1))); 8700 8701 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived1"); 8702 static assert(overloads.length == 2); 8703 8704 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 8705 static assert( is(PropertyType!(overloads[0]) == string)); 8706 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8707 8708 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 8709 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8710 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8711 } 8712 8713 // I does not provide default arguments, but C1 does. 8714 // override void defaultArgInDerived2(string, int i = 0); 8715 // override string defaultArgInDerived2(int i = 0); 8716 { 8717 static assert( is(SymbolType!(C1.defaultArgInDerived2) == ToFunctionType!(void function(string, int)))); 8718 static assert( is(PropertyType!(C1.defaultArgInDerived2) == string)); 8719 static assert( is(typeof(C1.defaultArgInDerived2) == SymbolType!(C1.defaultArgInDerived2))); 8720 8721 alias overloads = __traits(getOverloads, C1, "defaultArgInDerived2"); 8722 static assert(overloads.length == 2); 8723 8724 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 8725 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8726 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8727 8728 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 8729 static assert( is(PropertyType!(overloads[1]) == string)); 8730 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8731 } 8732 8733 // I does not provide default arguments, but C1 does. 8734 // override @property string defaultArgInDerivedProp1(int i = 0); 8735 // override @property void defaultArgInDerivedProp1(string, int i = 0); 8736 { 8737 static assert( is(SymbolType!(C1.defaultArgInDerivedProp1) == 8738 ToFunctionType!(string function(int) @property))); 8739 static assert( is(PropertyType!(C1.defaultArgInDerivedProp1) == string)); 8740 static assert( is(typeof(C1.defaultArgInDerivedProp1) == string)); 8741 8742 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp1"); 8743 static assert(overloads.length == 2); 8744 8745 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 8746 static assert( is(PropertyType!(overloads[0]) == string)); 8747 static assert( is(typeof(overloads[0]) == string)); 8748 8749 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 8750 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8751 static assert(!__traits(compiles, typeof(overloads[1]))); 8752 } 8753 8754 // I does not provide default arguments, but C1 does. 8755 // override @property void defaultArgInDerivedProp2(string, int i = 0); 8756 // override @property string defaultArgInDerivedProp2(int i = 0); 8757 { 8758 static assert( is(SymbolType!(C1.defaultArgInDerivedProp2) == 8759 ToFunctionType!(void function(string, int) @property))); 8760 static assert( is(PropertyType!(C1.defaultArgInDerivedProp2) == string)); 8761 static assert( is(typeof(C1.defaultArgInDerivedProp2) == string)); 8762 8763 alias overloads = __traits(getOverloads, C1, "defaultArgInDerivedProp2"); 8764 static assert(overloads.length == 2); 8765 8766 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property))); 8767 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8768 static assert(!__traits(compiles, typeof(overloads[0]))); 8769 8770 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property))); 8771 static assert( is(PropertyType!(overloads[1]) == string)); 8772 static assert( is(typeof(overloads[1]) == string)); 8773 } 8774 } 8775 8776 // Changes the function order (and has different extraProps). 8777 // It also provides default arguments when C1 does not. 8778 static class C2 : I 8779 { 8780 real r; 8781 bool b; 8782 int* ptr; 8783 8784 @property long extraProp() { return 42; } 8785 override @property void extraProp(string) {} 8786 @property void extraProp(int) {} 8787 8788 override void foo() {} 8789 8790 @property string defaultArgInDerivedProp2(int i = 0) { return "dlang"; } 8791 @property void defaultArgInDerivedProp2(string, int i = 0) {} 8792 8793 string defaultArgInDerived2(int i = 0) { return "dlang"; } 8794 void defaultArgInDerived2(string, int i = 0) {} 8795 8796 void defaultArgInDerived1(string, int i = 0) {} 8797 string defaultArgInDerived1(int i = 0) { return "dlang"; } 8798 8799 @property void defaultArgInDerivedProp1(string, int i = 0) {} 8800 @property string defaultArgInDerivedProp1(int i = 0) { return "dlang"; } 8801 8802 override void defaultArg2(int, string str = "bar") {} 8803 override int defaultArg2(string str = "bar") { return 0; } 8804 8805 override @property int defaultArgProp2(string str = "bar") { return 0; } 8806 override @property void defaultArgProp2(int, string str = "bar") {} 8807 8808 override @property void defaultArgProp1(int, string str = "bar") {} 8809 override @property int defaultArgProp1(string str = "bar") { return 0; } 8810 8811 override void defaultArg1(int, string str = "bar") {} 8812 override int defaultArg1(string str = "bar") { return 0; } 8813 8814 override @property void prop2(int) {} 8815 override @property int prop2() { return 0; } 8816 8817 override @property void prop1(int) {} 8818 override @property int prop1() { return 0; } 8819 8820 override void func2(int) {} 8821 override int func2() { return 0; } 8822 8823 override int func1() { return 0; } 8824 override void func1(int) {} 8825 } 8826 8827 { 8828 // real r; 8829 // bool b; 8830 // int* ptr; 8831 8832 static assert( is(SymbolType!(C2.r) == real)); 8833 static assert( is(PropertyType!(C2.r) == real)); 8834 static assert( is(typeof(C2.r) == real)); 8835 8836 static assert( is(SymbolType!(C2.b) == bool)); 8837 static assert( is(PropertyType!(C2.b) == bool)); 8838 static assert( is(typeof(C2.b) == bool)); 8839 8840 static assert( is(SymbolType!(C2.ptr) == int*)); 8841 static assert( is(PropertyType!(C2.ptr) == int*)); 8842 static assert( is(typeof(C2.ptr) == int*)); 8843 8844 // Actually on I, not C2. 8845 // static @property string staticProp(); 8846 // static @property void staticProp(real); 8847 { 8848 static assert( is(SymbolType!(C2.staticProp) == ToFunctionType!(string function() @property))); 8849 static assert( is(PropertyType!(C2.staticProp) == string)); 8850 static assert( is(typeof(C2.staticProp) == PropertyType!(C2.staticProp))); 8851 8852 alias overloads = __traits(getOverloads, C2, "staticProp"); 8853 static assert(overloads.length == 2); 8854 8855 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 8856 static assert( is(PropertyType!(overloads[0]) == string)); 8857 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 8858 8859 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 8860 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8861 static assert(!__traits(compiles, typeof(overloads[1]))); 8862 } 8863 8864 // @property long extraProp() { return 42; } 8865 // override @property void extraProp(string) {} 8866 // @property void extraProp(int) {} 8867 { 8868 static assert( is(SymbolType!(C2.extraProp) == ToFunctionType!(long function() @property))); 8869 static assert( is(PropertyType!(C2.extraProp) == long)); 8870 static assert( is(typeof(C2.extraProp) == long)); 8871 8872 alias overloads = __traits(getOverloads, C2, "extraProp"); 8873 static assert(overloads.length == 3); 8874 8875 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 8876 static assert( is(PropertyType!(overloads[0]) == long)); 8877 static assert( is(typeof(overloads[0]) == long)); 8878 8879 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property))); 8880 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8881 static assert(!__traits(compiles, typeof(overloads[1]))); 8882 8883 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property))); 8884 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 8885 static assert(!__traits(compiles, typeof(overloads[2]))); 8886 } 8887 8888 // override void foo() 8889 static assert( is(SymbolType!(C2.foo) == ToFunctionType!(void function()))); 8890 static assert(!__traits(compiles, PropertyType!(C2.foo))); 8891 static assert( is(typeof(C2.foo) == SymbolType!(C2.foo))); 8892 8893 // I does not provide default arguments, but C2 does. 8894 // @property string defaultArgInDerivedProp2(int i = 0); 8895 // @property void defaultArgInDerivedProp2(string, int i = 0); 8896 { 8897 static assert( is(SymbolType!(C2.defaultArgInDerivedProp2) == 8898 ToFunctionType!(string function(int) @property))); 8899 static assert( is(PropertyType!(C2.defaultArgInDerivedProp2) == string)); 8900 static assert( is(typeof(C2.defaultArgInDerivedProp2) == string)); 8901 8902 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp2"); 8903 static assert(overloads.length == 2); 8904 8905 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 8906 static assert( is(PropertyType!(overloads[0]) == string)); 8907 static assert( is(typeof(overloads[0]) == string)); 8908 8909 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 8910 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8911 static assert(!__traits(compiles, typeof(overloads[1]))); 8912 } 8913 8914 // I does not provide default arguments, but C2 does. 8915 // string defaultArgInDerived2(int i = 0); 8916 // void defaultArgInDerived2(string, int i = 0); 8917 { 8918 static assert( is(SymbolType!(C2.defaultArgInDerived2) == ToFunctionType!(string function(int)))); 8919 static assert( is(PropertyType!(C2.defaultArgInDerived2) == string)); 8920 static assert( is(typeof(C2.defaultArgInDerived2) == SymbolType!(C2.defaultArgInDerived2))); 8921 8922 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived2"); 8923 static assert(overloads.length == 2); 8924 8925 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 8926 static assert( is(PropertyType!(overloads[0]) == string)); 8927 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8928 8929 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 8930 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 8931 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8932 } 8933 8934 // I does not provide default arguments, but C2 does. 8935 // void defaultArgInDerived1(string, int i = 0); 8936 // string defaultArgInDerived1(int i = 0); 8937 { 8938 static assert( is(SymbolType!(C2.defaultArgInDerived1) == ToFunctionType!(void function(string, int)))); 8939 static assert( is(PropertyType!(C2.defaultArgInDerived1) == string)); 8940 static assert( is(typeof(C2.defaultArgInDerived1) == SymbolType!(C2.defaultArgInDerived1))); 8941 8942 alias overloads = __traits(getOverloads, C2, "defaultArgInDerived1"); 8943 static assert(overloads.length == 2); 8944 8945 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 8946 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8947 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8948 8949 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 8950 static assert( is(PropertyType!(overloads[1]) == string)); 8951 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8952 } 8953 8954 // I does not provide default arguments, but C2 does. 8955 // @property void defaultArgInDerivedProp1(string, int i = 0); 8956 // @property string defaultArgInDerivedProp1(int i = 0); 8957 { 8958 static assert( is(SymbolType!(C2.defaultArgInDerivedProp1) == 8959 ToFunctionType!(void function(string, int) @property))); 8960 static assert( is(PropertyType!(C2.defaultArgInDerivedProp1) == string)); 8961 static assert( is(typeof(C2.defaultArgInDerivedProp1) == string)); 8962 8963 alias overloads = __traits(getOverloads, C2, "defaultArgInDerivedProp1"); 8964 static assert(overloads.length == 2); 8965 8966 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property))); 8967 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8968 static assert(!__traits(compiles, typeof(overloads[0]))); 8969 8970 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property))); 8971 static assert( is(PropertyType!(overloads[1]) == string)); 8972 static assert( is(typeof(overloads[1]) == string)); 8973 } 8974 8975 // override void defaultArg2(int, string str = "bar"); 8976 // override int defaultArg2(string str = "bar"); 8977 { 8978 static assert( is(SymbolType!(C2.defaultArg2) == ToFunctionType!(void function(int, string)))); 8979 static assert( is(PropertyType!(C2.defaultArg2) == int)); 8980 static assert( is(typeof(C2.defaultArg2) == SymbolType!(C2.defaultArg2))); 8981 8982 alias overloads = __traits(getOverloads, C2, "defaultArg2"); 8983 static assert(overloads.length == 2); 8984 8985 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 8986 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 8987 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 8988 8989 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 8990 static assert( is(PropertyType!(overloads[1]) == int)); 8991 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 8992 } 8993 8994 // override @property int defaultArgProp2(string str = "bar"); 8995 // override @property void defaultArgProp2(int, string str = "bar"); 8996 { 8997 static assert( is(SymbolType!(C2.defaultArgProp2) == 8998 ToFunctionType!(int function(string) @property))); 8999 static assert( is(PropertyType!(C2.defaultArgProp2) == int)); 9000 static assert( is(typeof(C2.defaultArgProp2) == PropertyType!(C2.defaultArgProp2))); 9001 9002 alias overloads = __traits(getOverloads, C2, "defaultArgProp2"); 9003 static assert(overloads.length == 2); 9004 9005 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 9006 static assert( is(PropertyType!(overloads[0]) == int)); 9007 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 9008 9009 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 9010 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9011 static assert(!__traits(compiles, typeof(overloads[1]))); 9012 } 9013 9014 // override @property void defaultArgProp1(int, string str = "bar"); 9015 // override @property int defaultArgProp1(string str = "bar"); 9016 { 9017 9018 static assert( is(SymbolType!(C2.defaultArgProp1) == 9019 ToFunctionType!(void function(int, string) @property))); 9020 static assert( is(PropertyType!(C2.defaultArgProp1) == int)); 9021 static assert( is(typeof(C2.defaultArgProp1) == PropertyType!(C2.defaultArgProp1))); 9022 9023 alias overloads = __traits(getOverloads, C2, "defaultArgProp1"); 9024 static assert(overloads.length == 2); 9025 9026 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 9027 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9028 static assert(!__traits(compiles, typeof(overloads[0]))); 9029 9030 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 9031 static assert( is(PropertyType!(overloads[1]) == int)); 9032 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9033 } 9034 9035 // override void defaultArg1(int, string str = "bar"); 9036 // override int defaultArg1(string str = "bar"); 9037 { 9038 static assert( is(SymbolType!(C2.defaultArg1) == ToFunctionType!(void function(int, string)))); 9039 static assert( is(PropertyType!(C2.defaultArg1) == int)); 9040 static assert( is(typeof(C2.defaultArg1) == SymbolType!(C2.defaultArg1))); 9041 9042 alias overloads = __traits(getOverloads, C2, "defaultArg1"); 9043 static assert(overloads.length == 2); 9044 9045 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 9046 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9047 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9048 9049 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 9050 static assert( is(PropertyType!(overloads[1]) == int)); 9051 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9052 } 9053 9054 // override @property void prop2(int); 9055 // override @property int prop2(); 9056 { 9057 static assert( is(SymbolType!(C2.prop2) == ToFunctionType!(void function(int) @property))); 9058 static assert( is(PropertyType!(C2.prop2) == int)); 9059 static assert( is(typeof(C2.prop2) == PropertyType!(C2.prop2))); 9060 9061 alias overloads = __traits(getOverloads, C2, "prop2"); 9062 static assert(overloads.length == 2); 9063 9064 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9065 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9066 static assert(!__traits(compiles, typeof(overloads[0]))); 9067 9068 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9069 static assert( is(PropertyType!(overloads[1]) == int)); 9070 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9071 } 9072 9073 // override @property void prop1(int); 9074 // override @property int prop1(); 9075 { 9076 static assert( is(SymbolType!(C2.prop1) == ToFunctionType!(void function(int) @property))); 9077 static assert( is(PropertyType!(C2.prop1) == int)); 9078 static assert( is(typeof(C2.prop1) == PropertyType!(C2.prop1))); 9079 9080 alias overloads = __traits(getOverloads, C2, "prop1"); 9081 static assert(overloads.length == 2); 9082 9083 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9084 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9085 static assert(!__traits(compiles, typeof(overloads[0]))); 9086 9087 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9088 static assert( is(PropertyType!(overloads[1]) == int)); 9089 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9090 } 9091 9092 // override void func2(int); 9093 // override int func2(); 9094 { 9095 static assert( is(SymbolType!(C2.func2) == ToFunctionType!(void function(int)))); 9096 static assert( is(PropertyType!(C2.func2) == int)); 9097 static assert( is(typeof(C2.func2) == SymbolType!(C2.func2))); 9098 9099 alias overloads = __traits(getOverloads, C2, "func2"); 9100 static assert(overloads.length == 2); 9101 9102 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 9103 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9104 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9105 9106 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 9107 static assert( is(PropertyType!(overloads[1]) == int)); 9108 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9109 } 9110 9111 // override int func1(); 9112 // override void func1(int); 9113 { 9114 static assert( is(SymbolType!(C2.func1) == ToFunctionType!(int function()))); 9115 static assert( is(PropertyType!(C2.func1) == int)); 9116 static assert( is(typeof(C2.func1) == SymbolType!(C2.func1))); 9117 9118 alias overloads = __traits(getOverloads, C2, "func1"); 9119 static assert(overloads.length == 2); 9120 9121 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 9122 static assert( is(PropertyType!(overloads[0]) == int)); 9123 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9124 9125 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 9126 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9127 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9128 } 9129 } 9130 9131 static class C3 : C2 9132 { 9133 const(short)* ptr; 9134 } 9135 9136 { 9137 // real r; (from C2) 9138 // bool b; (from C2) 9139 // const(short)* ptr; (shadows C2.ptr) 9140 static assert( is(SymbolType!(C3.r) == real)); 9141 static assert( is(PropertyType!(C3.r) == real)); 9142 static assert( is(typeof(C3.r) == real)); 9143 9144 static assert( is(SymbolType!(C3.b) == bool)); 9145 static assert( is(PropertyType!(C3.b) == bool)); 9146 static assert( is(typeof(C3.b) == bool)); 9147 9148 static assert( is(SymbolType!(C3.ptr) == const(short)*)); 9149 static assert( is(PropertyType!(C3.ptr) == const(short)*)); 9150 static assert( is(typeof(C3.ptr) == const(short)*)); 9151 9152 // Actually on I, not C3. 9153 // static @property string staticProp(); 9154 // static @property void staticProp(real); 9155 { 9156 static assert( is(SymbolType!(C3.staticProp) == ToFunctionType!(string function() @property))); 9157 static assert( is(PropertyType!(C3.staticProp) == string)); 9158 static assert( is(typeof(C3.staticProp) == PropertyType!(C3.staticProp))); 9159 9160 alias overloads = __traits(getOverloads, C3, "staticProp"); 9161 static assert(overloads.length == 2); 9162 9163 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function() @property))); 9164 static assert( is(PropertyType!(overloads[0]) == string)); 9165 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 9166 9167 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(real) @property))); 9168 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9169 static assert(!__traits(compiles, typeof(overloads[1]))); 9170 } 9171 9172 // @property long extraProp() { return 42; } 9173 // override @property void extraProp(string) {} 9174 // @property void extraProp(int) {} 9175 { 9176 static assert( is(SymbolType!(C3.extraProp) == ToFunctionType!(long function() @property))); 9177 static assert( is(PropertyType!(C3.extraProp) == long)); 9178 static assert( is(typeof(C3.extraProp) == long)); 9179 9180 alias overloads = __traits(getOverloads, C3, "extraProp"); 9181 static assert(overloads.length == 3); 9182 9183 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(long function() @property))); 9184 static assert( is(PropertyType!(overloads[0]) == long)); 9185 static assert( is(typeof(overloads[0]) == long)); 9186 9187 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string) @property))); 9188 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9189 static assert(!__traits(compiles, typeof(overloads[1]))); 9190 9191 static assert( is(SymbolType!(overloads[2]) == ToFunctionType!(void function(int) @property))); 9192 static assert(!__traits(compiles, PropertyType!(overloads[2]))); 9193 static assert(!__traits(compiles, typeof(overloads[2]))); 9194 } 9195 9196 // override void foo() 9197 static assert( is(SymbolType!(C3.foo) == ToFunctionType!(void function()))); 9198 static assert(!__traits(compiles, PropertyType!(C3.foo))); 9199 static assert( is(typeof(C3.foo) == SymbolType!(C3.foo))); 9200 9201 // I does not provide default arguments, but C2 does. 9202 // @property string defaultArgInDerivedProp2(int i = 0); 9203 // @property void defaultArgInDerivedProp2(string, int i = 0); 9204 { 9205 static assert( is(SymbolType!(C3.defaultArgInDerivedProp2) == 9206 ToFunctionType!(string function(int) @property))); 9207 static assert( is(PropertyType!(C3.defaultArgInDerivedProp2) == string)); 9208 static assert( is(typeof(C3.defaultArgInDerivedProp2) == string)); 9209 9210 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp2"); 9211 static assert(overloads.length == 2); 9212 9213 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int) @property))); 9214 static assert( is(PropertyType!(overloads[0]) == string)); 9215 static assert( is(typeof(overloads[0]) == string)); 9216 9217 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int) @property))); 9218 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9219 static assert(!__traits(compiles, typeof(overloads[1]))); 9220 } 9221 9222 // I does not provide default arguments, but C2 does. 9223 // string defaultArgInDerived2(int i = 0); 9224 // void defaultArgInDerived2(string, int i = 0); 9225 { 9226 static assert( is(SymbolType!(C3.defaultArgInDerived2) == ToFunctionType!(string function(int)))); 9227 static assert( is(PropertyType!(C3.defaultArgInDerived2) == string)); 9228 static assert( is(typeof(C3.defaultArgInDerived2) == SymbolType!(C3.defaultArgInDerived2))); 9229 9230 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived2"); 9231 static assert(overloads.length == 2); 9232 9233 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(string function(int)))); 9234 static assert( is(PropertyType!(overloads[0]) == string)); 9235 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9236 9237 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(string, int)))); 9238 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9239 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9240 } 9241 9242 // I does not provide default arguments, but C2 does. 9243 // void defaultArgInDerived1(string, int i = 0); 9244 // string defaultArgInDerived1(int i = 0); 9245 { 9246 static assert( is(SymbolType!(C3.defaultArgInDerived1) == ToFunctionType!(void function(string, int)))); 9247 static assert( is(PropertyType!(C3.defaultArgInDerived1) == string)); 9248 static assert( is(typeof(C3.defaultArgInDerived1) == SymbolType!(C3.defaultArgInDerived1))); 9249 9250 alias overloads = __traits(getOverloads, C3, "defaultArgInDerived1"); 9251 static assert(overloads.length == 2); 9252 9253 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int)))); 9254 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9255 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9256 9257 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int)))); 9258 static assert( is(PropertyType!(overloads[1]) == string)); 9259 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9260 } 9261 9262 // I does not provide default arguments, but C2 does. 9263 // @property void defaultArgInDerivedProp1(string, int i = 0); 9264 // @property string defaultArgInDerivedProp1(int i = 0); 9265 { 9266 static assert( is(SymbolType!(C3.defaultArgInDerivedProp1) == 9267 ToFunctionType!(void function(string, int) @property))); 9268 static assert( is(PropertyType!(C3.defaultArgInDerivedProp1) == string)); 9269 static assert( is(typeof(C3.defaultArgInDerivedProp1) == string)); 9270 9271 alias overloads = __traits(getOverloads, C3, "defaultArgInDerivedProp1"); 9272 static assert(overloads.length == 2); 9273 9274 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(string, int) @property))); 9275 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9276 static assert(!__traits(compiles, typeof(overloads[0]))); 9277 9278 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(string function(int) @property))); 9279 static assert( is(PropertyType!(overloads[1]) == string)); 9280 static assert( is(typeof(overloads[1]) == string)); 9281 } 9282 9283 // override void defaultArg2(int, string str = "bar"); 9284 // override int defaultArg2(string str = "bar"); 9285 { 9286 static assert( is(SymbolType!(C3.defaultArg2) == ToFunctionType!(void function(int, string)))); 9287 static assert( is(PropertyType!(C3.defaultArg2) == int)); 9288 static assert( is(typeof(C3.defaultArg2) == SymbolType!(C3.defaultArg2))); 9289 9290 alias overloads = __traits(getOverloads, C3, "defaultArg2"); 9291 static assert(overloads.length == 2); 9292 9293 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 9294 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9295 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9296 9297 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 9298 static assert( is(PropertyType!(overloads[1]) == int)); 9299 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9300 } 9301 9302 // override @property int defaultArgProp2(string str = "bar"); 9303 // override @property void defaultArgProp2(int, string str = "bar"); 9304 { 9305 static assert( is(SymbolType!(C3.defaultArgProp2) == 9306 ToFunctionType!(int function(string) @property))); 9307 static assert( is(PropertyType!(C3.defaultArgProp2) == int)); 9308 static assert( is(typeof(C3.defaultArgProp2) == PropertyType!(C3.defaultArgProp2))); 9309 9310 alias overloads = __traits(getOverloads, C3, "defaultArgProp2"); 9311 static assert(overloads.length == 2); 9312 9313 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function(string) @property))); 9314 static assert( is(PropertyType!(overloads[0]) == int)); 9315 static assert( is(typeof(overloads[0]) == PropertyType!(overloads[0]))); 9316 9317 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int, string) @property))); 9318 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9319 static assert(!__traits(compiles, typeof(overloads[1]))); 9320 } 9321 9322 // override @property void defaultArgProp1(int, string str = "bar"); 9323 // override @property int defaultArgProp1(string str = "bar"); 9324 { 9325 9326 static assert( is(SymbolType!(C3.defaultArgProp1) == 9327 ToFunctionType!(void function(int, string) @property))); 9328 static assert( is(PropertyType!(C3.defaultArgProp1) == int)); 9329 static assert( is(typeof(C3.defaultArgProp1) == PropertyType!(C3.defaultArgProp1))); 9330 9331 alias overloads = __traits(getOverloads, C3, "defaultArgProp1"); 9332 static assert(overloads.length == 2); 9333 9334 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string) @property))); 9335 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9336 static assert(!__traits(compiles, typeof(overloads[0]))); 9337 9338 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string) @property))); 9339 static assert( is(PropertyType!(overloads[1]) == int)); 9340 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9341 } 9342 9343 // override void defaultArg1(int, string str = "bar"); 9344 // override int defaultArg1(string str = "bar"); 9345 { 9346 static assert( is(SymbolType!(C3.defaultArg1) == ToFunctionType!(void function(int, string)))); 9347 static assert( is(PropertyType!(C3.defaultArg1) == int)); 9348 static assert( is(typeof(C3.defaultArg1) == SymbolType!(C3.defaultArg1))); 9349 9350 alias overloads = __traits(getOverloads, C3, "defaultArg1"); 9351 static assert(overloads.length == 2); 9352 9353 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int, string)))); 9354 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9355 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9356 9357 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function(string)))); 9358 static assert( is(PropertyType!(overloads[1]) == int)); 9359 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9360 } 9361 9362 // override @property void prop2(int); 9363 // override @property int prop2(); 9364 { 9365 static assert( is(SymbolType!(C3.prop2) == ToFunctionType!(void function(int) @property))); 9366 static assert( is(PropertyType!(C3.prop2) == int)); 9367 static assert( is(typeof(C3.prop2) == PropertyType!(C3.prop2))); 9368 9369 alias overloads = __traits(getOverloads, C3, "prop2"); 9370 static assert(overloads.length == 2); 9371 9372 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9373 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9374 static assert(!__traits(compiles, typeof(overloads[0]))); 9375 9376 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9377 static assert( is(PropertyType!(overloads[1]) == int)); 9378 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9379 } 9380 9381 // override @property void prop1(int); 9382 // override @property int prop1(); 9383 { 9384 static assert( is(SymbolType!(C3.prop1) == ToFunctionType!(void function(int) @property))); 9385 static assert( is(PropertyType!(C3.prop1) == int)); 9386 static assert( is(typeof(C3.prop1) == PropertyType!(C3.prop1))); 9387 9388 alias overloads = __traits(getOverloads, C3, "prop1"); 9389 static assert(overloads.length == 2); 9390 9391 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int) @property))); 9392 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9393 static assert(!__traits(compiles, typeof(overloads[0]))); 9394 9395 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function() @property))); 9396 static assert( is(PropertyType!(overloads[1]) == int)); 9397 static assert( is(typeof(overloads[1]) == PropertyType!(overloads[1]))); 9398 } 9399 9400 // override void func2(int); 9401 // override int func2(); 9402 { 9403 static assert( is(SymbolType!(C3.func2) == ToFunctionType!(void function(int)))); 9404 static assert( is(PropertyType!(C3.func2) == int)); 9405 static assert( is(typeof(C3.func2) == SymbolType!(C3.func2))); 9406 9407 alias overloads = __traits(getOverloads, C3, "func2"); 9408 static assert(overloads.length == 2); 9409 9410 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(void function(int)))); 9411 static assert(!__traits(compiles, PropertyType!(overloads[0]))); 9412 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9413 9414 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(int function()))); 9415 static assert( is(PropertyType!(overloads[1]) == int)); 9416 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9417 } 9418 9419 // override int func1(); 9420 // override void func1(int); 9421 { 9422 static assert( is(SymbolType!(C3.func1) == ToFunctionType!(int function()))); 9423 static assert( is(PropertyType!(C3.func1) == int)); 9424 static assert( is(typeof(C3.func1) == SymbolType!(C3.func1))); 9425 9426 alias overloads = __traits(getOverloads, C3, "func1"); 9427 static assert(overloads.length == 2); 9428 9429 static assert( is(SymbolType!(overloads[0]) == ToFunctionType!(int function()))); 9430 static assert( is(PropertyType!(overloads[0]) == int)); 9431 static assert( is(typeof(overloads[0]) == SymbolType!(overloads[0]))); 9432 9433 static assert( is(SymbolType!(overloads[1]) == ToFunctionType!(void function(int)))); 9434 static assert(!__traits(compiles, PropertyType!(overloads[1]))); 9435 static assert( is(typeof(overloads[1]) == SymbolType!(overloads[1]))); 9436 } 9437 } 9438 } 9439 } 9440 9441 // This is probably overkill, since it's arguably testing the compiler more 9442 // than it's testing SymbolType or ToFunctionType, but with various tests 9443 // either using inference for all attributes or not providing a body to avoid 9444 // it entirely, it seemed prudent to add some tests where the attributes being 9445 // inferred were better controlled, and it does help ensure that SymbolType 9446 // and ToFunctionType behave as expected in each case. 9447 @safe unittest 9448 { 9449 static int var; 9450 9451 // Since these are actually called below (even if those functions aren't 9452 // called) we can't play the trick of not providing a body to set all of 9453 // the attributes, because we get linker errors when the functions below 9454 // call these functions. 9455 static void useGC() @safe pure nothrow { new int; } 9456 static void throws() @safe pure @nogc { Exception e; throw e; } 9457 static void impure() @safe nothrow @nogc { ++var; } 9458 static void unsafe() @system pure nothrow @nogc { int i; int* ptr = &i; } 9459 9460 { 9461 static void func() { useGC(); } 9462 static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure nothrow))); 9463 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure nothrow))); 9464 } 9465 { 9466 static void func() { throws(); } 9467 static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure @nogc))); 9468 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure @nogc))); 9469 } 9470 { 9471 static void func() { impure(); } 9472 static assert( is(typeof(func) == ToFunctionType!(void function() @safe nothrow @nogc))); 9473 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe nothrow @nogc))); 9474 } 9475 { 9476 static void func() { unsafe(); } 9477 static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow @nogc))); 9478 9479 // Doubling the test shouldn't be necessary, but since the order of the 9480 // attributes isn't supposed to matter, it seemed prudent to have at 9481 // least one test that used a different order. 9482 static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow @nogc))); 9483 static assert( is(SymbolType!func == ToFunctionType!(void function() @nogc nothrow pure @system))); 9484 } 9485 { 9486 static void func() { useGC(); throws(); } 9487 static assert( is(typeof(func) == ToFunctionType!(void function() @safe pure))); 9488 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe pure))); 9489 } 9490 { 9491 static void func() { throws(); impure(); } 9492 static assert( is(typeof(func) == ToFunctionType!(void function() @safe @nogc))); 9493 static assert( is(SymbolType!func == ToFunctionType!(void function() @safe @nogc))); 9494 } 9495 { 9496 static void func() { impure(); unsafe(); } 9497 static assert( is(typeof(func) == ToFunctionType!(void function() @system nothrow @nogc))); 9498 static assert( is(SymbolType!func == ToFunctionType!(void function() @system nothrow @nogc))); 9499 } 9500 { 9501 static void func() { useGC(); unsafe(); } 9502 static assert( is(typeof(func) == ToFunctionType!(void function() @system pure nothrow))); 9503 static assert( is(SymbolType!func == ToFunctionType!(void function() @system pure nothrow))); 9504 } 9505 { 9506 static void func() { useGC(); throws(); impure(); unsafe(); } 9507 static assert( is(typeof(func) == ToFunctionType!(void function() @system))); 9508 static assert( is(SymbolType!func == ToFunctionType!(void function() @system))); 9509 } 9510 { 9511 static void func() @trusted { useGC(); throws(); impure(); unsafe(); } 9512 static assert( is(typeof(func) == ToFunctionType!(void function() @trusted))); 9513 static assert( is(SymbolType!func == ToFunctionType!(void function() @trusted))); 9514 } 9515 } 9516 9517 /++ 9518 Removes the outer layer of $(D const), $(D inout), or $(D immutable) 9519 from type $(D T). 9520 9521 If none of those qualifiers have been applied to the outer layer of 9522 type $(D T), then the result is $(D T). 9523 9524 For the built-in scalar types (that is $(D bool), the character types, and 9525 the numeric types), they only have one layer, so $(D const U) simply becomes 9526 $(D U). 9527 9528 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 9529 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 9530 goes from being fully $(D const) to being a mutable pointer to $(D const), 9531 and a dynamic array goes from being fully $(D const) to being a mutable 9532 dynamic array of $(D const) elements. And if there are multiple layers of 9533 pointers or arrays, it's just that outer layer which is affected - e.g. 9534 $(D const(U**)) would become $(D const(U*)*). 9535 9536 For user-defined types, the effect is that $(D const U) becomes $(D U), and 9537 how that affects member variables depends on the type of the member 9538 variable. If a member variable is explicitly marked with any mutability 9539 qualifiers, then it will continue to have those qualifiers even after 9540 Unconst has stripped all mutability qualifiers from the containing type. 9541 However, if a mutability qualifier was on the member variable only because 9542 the containing type had that qualifier, then when Unconst removes the 9543 qualifier from the containing type, it is removed from the member variable 9544 as well. 9545 9546 Also, Unconst has no effect on what a templated type is instantiated 9547 with, so if a templated type is instantiated with a template argument which 9548 has a mutability qualifier, the template instantiation will not change. 9549 +/ 9550 version (StdDdoc) template Unconst(T) 9551 { 9552 import core.internal.traits : CoreUnconst = Unconst; 9553 alias Unconst = CoreUnconst!T; 9554 } 9555 else 9556 { 9557 import core.internal.traits : CoreUnconst = Unconst; 9558 alias Unconst = CoreUnconst; 9559 } 9560 9561 /// 9562 @safe unittest 9563 { 9564 static assert(is(Unconst!( int) == int)); 9565 static assert(is(Unconst!( const int) == int)); 9566 static assert(is(Unconst!( inout int) == int)); 9567 static assert(is(Unconst!( inout const int) == int)); 9568 static assert(is(Unconst!(shared int) == shared int)); 9569 static assert(is(Unconst!(shared const int) == shared int)); 9570 static assert(is(Unconst!(shared inout int) == shared int)); 9571 static assert(is(Unconst!(shared inout const int) == shared int)); 9572 static assert(is(Unconst!( immutable int) == int)); 9573 9574 // Only the outer layer of immutable is removed. 9575 // immutable(int[]) -> immutable(int)[] 9576 alias ImmIntArr = immutable(int[]); 9577 static assert(is(Unconst!ImmIntArr == immutable(int)[])); 9578 9579 // Only the outer layer of const is removed. 9580 // immutable(int*) -> immutable(int)* 9581 alias ConstIntPtr = const(int*); 9582 static assert(is(Unconst!ConstIntPtr == const(int)*)); 9583 9584 // const(int)* -> const(int)* 9585 alias PtrToConstInt = const(int)*; 9586 static assert(is(Unconst!PtrToConstInt == const(int)*)); 9587 9588 static struct S 9589 { 9590 int* ptr; 9591 const int* cPtr; 9592 shared int* sPtr; 9593 } 9594 9595 const S s; 9596 static assert(is(typeof(s) == const S)); 9597 static assert(is(typeof(typeof(s).ptr) == const int*)); 9598 static assert(is(typeof(typeof(s).cPtr) == const int*)); 9599 static assert(is(typeof(typeof(s).sPtr) == const shared int*)); 9600 9601 // For user-defined types, all mutability qualifiers that are applied to 9602 // member variables only because the containing type has them are removed, 9603 // but the ones that are directly on those member variables remain. 9604 9605 // const S -> S 9606 static assert(is(Unconst!(typeof(s)) == S)); 9607 static assert(is(typeof(Unconst!(typeof(s)).ptr) == int*)); 9608 static assert(is(typeof(Unconst!(typeof(s)).cPtr) == const int*)); 9609 static assert(is(typeof(Unconst!(typeof(s)).sPtr) == shared int*)); 9610 9611 static struct Foo(T) 9612 { 9613 T* ptr; 9614 } 9615 9616 // The qualifier on the type is removed, but the qualifier on the template 9617 // argument is not. 9618 static assert(is(Unconst!(const(Foo!(const int))) == Foo!(const int))); 9619 static assert(is(Unconst!(Foo!(const int)) == Foo!(const int))); 9620 static assert(is(Unconst!(const(Foo!int)) == Foo!int)); 9621 } 9622 9623 /++ 9624 Removes the outer layer of $(D shared) from type $(D T). 9625 9626 If $(D shared) has not been applied to the outer layer of type $(D T), then 9627 the result is $(D T). 9628 9629 Note that while $(D immutable) is implicitly $(D shared), it is unaffected 9630 by Unshared. Only explicit $(D shared) is removed. 9631 9632 For the built-in scalar types (that is $(D bool), the character types, and 9633 the numeric types), they only have one layer, so $(D shared U) simply 9634 becomes $(D U). 9635 9636 Where the layers come in is pointers and arrays. $(D shared(U*)) becomes 9637 $(D shared(U)*), and $(D shared(U[])), becomes $(D shared(U)[]). So, a 9638 pointer goes from being fully $(D shared) to being a mutable pointer to 9639 $(D shared), and a dynamic array goes from being fully $(D shared) to being 9640 a mutable dynamic array of $(D shared) elements. And if there are multiple 9641 layers of pointers or arrays, it's just that outer layer which is affected 9642 - e.g. $(D shared(U**)) would become $(D shared(U*)*). 9643 9644 For user-defined types, the effect is that $(D shared U) becomes $(D U), 9645 and how that affects member variables depends on the type of the member 9646 variable. If a member variable is explicitly marked with $(D shared), then 9647 it will continue to be $(D shared) even after Unshared has stripped 9648 $(D shared) from the containing type. However, if $(D shared) was on the 9649 member variable only because the containing type was $(D shared), then when 9650 Unshared removes the qualifier from the containing type, it is removed from 9651 the member variable as well. 9652 9653 Also, Unshared has no effect on what a templated type is instantiated 9654 with, so if a templated type is instantiated with a template argument which 9655 has a type qualifier, the template instantiation will not change. 9656 +/ 9657 template Unshared(T) 9658 { 9659 static if (is(T == shared U, U)) 9660 alias Unshared = U; 9661 else 9662 alias Unshared = T; 9663 } 9664 9665 /// 9666 @safe unittest 9667 { 9668 static assert(is(Unshared!( int) == int)); 9669 static assert(is(Unshared!( const int) == const int)); 9670 static assert(is(Unshared!( inout int) == inout int)); 9671 static assert(is(Unshared!( inout const int) == inout const int)); 9672 static assert(is(Unshared!(shared int) == int)); 9673 static assert(is(Unshared!(shared const int) == const int)); 9674 static assert(is(Unshared!(shared inout int) == inout int)); 9675 static assert(is(Unshared!(shared inout const int) == inout const int)); 9676 static assert(is(Unshared!( immutable int) == immutable int)); 9677 9678 // Only the outer layer of shared is removed. 9679 // shared(int[]) -> shared(int)[] 9680 alias SharedIntArr = shared(int[]); 9681 static assert(is(Unshared!SharedIntArr == shared(int)[])); 9682 9683 // Only the outer layer of shared is removed. 9684 // shared(int*) -> shared(int)* 9685 alias SharedIntPtr = shared(int*); 9686 static assert(is(Unshared!SharedIntPtr == shared(int)*)); 9687 9688 // shared(int)* -> shared(int)* 9689 alias PtrToSharedInt = shared(int)*; 9690 static assert(is(Unshared!PtrToSharedInt == shared(int)*)); 9691 9692 // immutable is unaffected 9693 alias ImmutableArr = immutable(int[]); 9694 static assert(is(Unshared!ImmutableArr == immutable(int[]))); 9695 9696 static struct S 9697 { 9698 int* ptr; 9699 const int* cPtr; 9700 shared int* sPtr; 9701 } 9702 9703 shared S s; 9704 static assert(is(typeof(s) == shared S)); 9705 static assert(is(typeof(typeof(s).ptr) == shared int*)); 9706 static assert(is(typeof(typeof(s).cPtr) == const shared int*)); 9707 static assert(is(typeof(typeof(s).sPtr) == shared int*)); 9708 9709 // For user-defined types, if shared is applied to a member variable only 9710 // because the containing type is shared, then shared is removed from that 9711 // member variable, but if the member variable is directly marked as shared, 9712 // then it continues to be shared. 9713 9714 // shared S -> S 9715 static assert(is(Unshared!(typeof(s)) == S)); 9716 static assert(is(typeof(Unshared!(typeof(s)).ptr) == int*)); 9717 static assert(is(typeof(Unshared!(typeof(s)).cPtr) == const int*)); 9718 static assert(is(typeof(Unshared!(typeof(s)).sPtr) == shared int*)); 9719 9720 static struct Foo(T) 9721 { 9722 T* ptr; 9723 } 9724 9725 // The qualifier on the type is removed, but the qualifier on the template 9726 // argument is not. 9727 static assert(is(Unshared!(shared(Foo!(shared int))) == Foo!(shared int))); 9728 static assert(is(Unshared!(Foo!(shared int)) == Foo!(shared int))); 9729 static assert(is(Unshared!(shared(Foo!int)) == Foo!int)); 9730 } 9731 9732 /++ 9733 Removes the outer layer of all type qualifiers from type $(D T) - this 9734 includes $(D shared). 9735 9736 If no type qualifiers have been applied to the outer layer of type $(D T), 9737 then the result is $(D T). 9738 9739 For the built-in scalar types (that is $(D bool), the character types, and 9740 the numeric types), they only have one layer, so $(D const U) simply becomes 9741 $(D U). 9742 9743 Where the layers come in is pointers and arrays. $(D const(U*)) becomes 9744 $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer 9745 goes from being fully $(D const) to being a mutable pointer to $(D const), 9746 and a dynamic array goes from being fully $(D const) to being a mutable 9747 dynamic array of $(D const) elements. And if there are multiple layers of 9748 pointers or arrays, it's just that outer layer which is affected - e.g. 9749 $(D shared(U**)) would become $(D shared(U*)*). 9750 9751 For user-defined types, the effect is that $(D const U) becomes $(D U), and 9752 how that affects member variables depends on the type of the member 9753 variable. If a member variable is explicitly marked with any qualifiers, 9754 then it will continue to have those qualifiers even after Unqualified has 9755 stripped all qualifiers from the containing type. However, if a qualifier 9756 was on the member variable only because the containing type had that 9757 qualifier, then when Unqualified removes the qualifier from the containing 9758 type, it is removed from the member variable as well. 9759 9760 Also, Unqualified has no effect on what a templated type is instantiated 9761 with, so if a templated type is instantiated with a template argument which 9762 has a type qualifier, the template instantiation will not change. 9763 9764 Note that in most cases, $(LREF Unconst) or $(LREF Unshared) should be used 9765 rather than Unqualified, because in most cases, code is not designed to 9766 work with $(D shared) and thus doing type checks which remove $(D shared) 9767 will allow $(D shared) types to pass template constraints when they won't 9768 actually work with the code. And when code is designed to work with 9769 $(D shared), it's often the case that the type checks need to take 9770 $(D const) into account in order to avoid accidentally mutating $(D const) 9771 data and violating the type system. 9772 9773 In particular, historically, a lot of D code has used 9774 $(REF Unqual, std, traits) (which is equivalent to phobos.sys.traits' 9775 Unqualified) when the programmer's intent was to remove $(D const), and 9776 $(D shared) wasn't actually considered at all. And in such cases, the code 9777 really should use $(LREF Unconst) instead. 9778 9779 But of course, if a template constraint or $(D static if) really needs to 9780 strip off both the mutability qualifiers and $(D shared) for what it's 9781 testing for, then that's what Unqualified is for. It's just that it's best 9782 practice to use $(LREF Unconst) when it's not clear that $(D shared) should 9783 be removed as well. 9784 9785 Also, note that $(D is(immutable T == immutable U))) is equivalent to 9786 $(D is(Unqualified!T == Unqualified!U)) (using $(D immutable) converts 9787 $(D const), $(D inout), and $(D shared) to $(D immutable), whereas using 9788 Unqualified strips off all type qualifiers, but the resulting comparison is 9789 the same as long as $(D immutable) is used on both sides or Unqualified is 9790 used on both sides)). So, in cases where code needs to compare two types to 9791 see whether they're the same while ignoring all qualifiers, it's generally 9792 better to use $(D immutable) on both types rather than using Unqualfied on 9793 both types, since that avoids needing to instantiate a template, and those 9794 instantiations can really add up when a project has a lot of templates 9795 with template constraints, $(D static if)s, and other forms of conditional 9796 compilation that need to compare types. 9797 +/ 9798 template Unqualified(T) 9799 { 9800 import core.internal.traits : CoreUnqualified = Unqual; 9801 alias Unqualified = CoreUnqualified!(T); 9802 } 9803 9804 /// 9805 @safe unittest 9806 { 9807 static assert(is(Unqualified!( int) == int)); 9808 static assert(is(Unqualified!( const int) == int)); 9809 static assert(is(Unqualified!( inout int) == int)); 9810 static assert(is(Unqualified!( inout const int) == int)); 9811 static assert(is(Unqualified!(shared int) == int)); 9812 static assert(is(Unqualified!(shared const int) == int)); 9813 static assert(is(Unqualified!(shared inout int) == int)); 9814 static assert(is(Unqualified!(shared inout const int) == int)); 9815 static assert(is(Unqualified!( immutable int) == int)); 9816 9817 // Only the outer layer of immutable is removed. 9818 // immutable(int[]) -> immutable(int)[] 9819 alias ImmIntArr = immutable(int[]); 9820 static assert(is(Unqualified!ImmIntArr == immutable(int)[])); 9821 9822 // Only the outer layer of const is removed. 9823 // const(int*) -> const(int)* 9824 alias ConstIntPtr = const(int*); 9825 static assert(is(Unqualified!ConstIntPtr == const(int)*)); 9826 9827 // const(int)* -> const(int)* 9828 alias PtrToConstInt = const(int)*; 9829 static assert(is(Unqualified!PtrToConstInt == const(int)*)); 9830 9831 // Only the outer layer of shared is removed. 9832 // shared(int*) -> shared(int)* 9833 alias SharedIntPtr = shared(int*); 9834 static assert(is(Unqualified!SharedIntPtr == shared(int)*)); 9835 9836 // shared(int)* -> shared(int)* 9837 alias PtrToSharedInt = shared(int)*; 9838 static assert(is(Unqualified!PtrToSharedInt == shared(int)*)); 9839 9840 // Both const and shared are removed from the outer layer. 9841 // shared const int[] -> shared(const(int))[] 9842 alias SharedConstIntArr = shared const(int[]); 9843 static assert(is(Unqualified!SharedConstIntArr == shared(const(int))[])); 9844 9845 static struct S 9846 { 9847 int* ptr; 9848 const int* cPtr; 9849 shared int* sPtr; 9850 } 9851 9852 shared const S s; 9853 static assert(is(typeof(s) == shared const S)); 9854 static assert(is(typeof(typeof(s).ptr) == shared const int*)); 9855 static assert(is(typeof(typeof(s).cPtr) == shared const int*)); 9856 static assert(is(typeof(typeof(s).sPtr) == shared const int*)); 9857 9858 // For user-defined types, all qualifiers that are applied to member 9859 // variables only because the containing type has them are removed, but the 9860 // ones that are directly on those member variables remain. 9861 9862 // shared const S -> S 9863 static assert(is(Unqualified!(typeof(s)) == S)); 9864 static assert(is(typeof(Unqualified!(typeof(s)).ptr) == int*)); 9865 static assert(is(typeof(Unqualified!(typeof(s)).cPtr) == const int*)); 9866 static assert(is(typeof(Unqualified!(typeof(s)).sPtr) == shared int*)); 9867 9868 static struct Foo(T) 9869 { 9870 T* ptr; 9871 } 9872 9873 // The qualifiers on the type are removed, but the qualifiers on the 9874 // template argument are not. 9875 static assert(is(Unqualified!(const(Foo!(const int))) == Foo!(const int))); 9876 static assert(is(Unqualified!(Foo!(const int)) == Foo!(const int))); 9877 static assert(is(Unqualified!(const(Foo!int)) == Foo!int)); 9878 } 9879 9880 /++ 9881 Applies $(D const) to the given type. 9882 9883 This is primarily useful in conjunction with templates that take a template 9884 predicate (such as many of the templates in phobos.sys.meta), since while in 9885 most cases, you can simply do $(D const T) or $(D const(T)) to make $(D T) 9886 $(D const), with something like $(REF Map, phobos, sys, meta), you need to 9887 pass a template to be applied. 9888 9889 See_Also: 9890 $(LREF ImmutableOf) 9891 $(LREF InoutOf) 9892 $(LREF SharedOf) 9893 +/ 9894 alias ConstOf(T) = const T; 9895 9896 /// 9897 @safe unittest 9898 { 9899 static assert(is(ConstOf!int == const int)); 9900 static assert(is(ConstOf!(const int) == const int)); 9901 static assert(is(ConstOf!(inout int) == inout const int)); 9902 static assert(is(ConstOf!(shared int) == const shared int)); 9903 9904 // Note that const has no effect on immutable. 9905 static assert(is(ConstOf!(immutable int) == immutable int)); 9906 9907 import phobos.sys.meta : AliasSeq, Map; 9908 9909 alias Types = AliasSeq!(int, long, 9910 bool*, ubyte[], 9911 string, immutable(string)); 9912 alias WithConst = Map!(ConstOf, Types); 9913 static assert(is(WithConst == 9914 AliasSeq!(const int, const long, 9915 const(bool*), const(ubyte[]), 9916 const(string), immutable(string)))); 9917 } 9918 9919 /++ 9920 Applies $(D immutable) to the given type. 9921 9922 This is primarily useful in conjunction with templates that take a template 9923 predicate (such as many of the templates in phobos.sys.meta), since while in 9924 most cases, you can simply do $(D immutable T) or $(D immutable(T)) to make 9925 $(D T) $(D immutable), with something like $(REF Map, phobos, sys, meta), 9926 you need to pass a template to be applied. 9927 9928 See_Also: 9929 $(LREF ConstOf) 9930 $(LREF InoutOf) 9931 $(LREF SharedOf) 9932 +/ 9933 alias ImmutableOf(T) = immutable T; 9934 9935 /// 9936 @safe unittest 9937 { 9938 static assert(is(ImmutableOf!int == immutable int)); 9939 9940 // Note that immutable overrides const and inout. 9941 static assert(is(ImmutableOf!(const int) == immutable int)); 9942 static assert(is(ImmutableOf!(inout int) == immutable int)); 9943 9944 // Note that immutable overrides shared, since immutable is implicitly 9945 // shared. 9946 static assert(is(ImmutableOf!(shared int) == immutable int)); 9947 9948 static assert(is(ImmutableOf!(immutable int) == immutable int)); 9949 9950 import phobos.sys.meta : AliasSeq, Map; 9951 9952 alias Types = AliasSeq!(int, long, 9953 bool*, ubyte[], 9954 string, immutable(string)); 9955 alias WithImmutable = Map!(ImmutableOf, Types); 9956 static assert(is(WithImmutable == 9957 AliasSeq!(immutable int, immutable long, 9958 immutable(bool*), immutable(ubyte[]), 9959 immutable(string), immutable(string)))); 9960 } 9961 9962 /++ 9963 Applies $(D inout) to the given type. 9964 9965 This is primarily useful in conjunction with templates that take a template 9966 predicate (such as many of the templates in phobos.sys.meta), since while in 9967 most cases, you can simply do $(D inout T) or $(D inout(T)) to make $(D T) 9968 $(D inout), with something like $(REF Map, phobos, sys, meta), you need to 9969 pass a template to be applied. 9970 9971 See_Also: 9972 $(LREF ConstOf) 9973 $(LREF ImmutableOf) 9974 $(LREF SharedOf) 9975 +/ 9976 alias InoutOf(T) = inout T; 9977 9978 /// 9979 @safe unittest 9980 { 9981 static assert(is(InoutOf!int == inout int)); 9982 static assert(is(InoutOf!(const int) == inout const int)); 9983 static assert(is(InoutOf!(inout int) == inout int)); 9984 static assert(is(InoutOf!(shared int) == inout shared int)); 9985 9986 // Note that inout has no effect on immutable. 9987 static assert(is(InoutOf!(immutable int) == immutable int)); 9988 9989 import phobos.sys.meta : AliasSeq, Map; 9990 9991 alias Types = AliasSeq!(int, long, 9992 bool*, ubyte[], 9993 string, immutable(string)); 9994 alias WithInout = Map!(InoutOf, Types); 9995 static assert(is(WithInout == 9996 AliasSeq!(inout int, inout long, 9997 inout(bool*), inout(ubyte[]), 9998 inout(string), immutable(string)))); 9999 } 10000 10001 /++ 10002 Applies $(D shared) to the given type. 10003 10004 This is primarily useful in conjunction with templates that take a template 10005 predicate (such as many of the templates in phobos.sys.meta), since while in 10006 most cases, you can simply do $(D shared T) or $(D shared(T)) to make $(D T) 10007 $(D shared), with something like $(REF Map, phobos, sys, meta), you need to 10008 pass a template to be applied. 10009 10010 See_Also: 10011 $(LREF ConstOf) 10012 $(LREF ImmutableOf) 10013 $(LREF InoutOf) 10014 +/ 10015 alias SharedOf(T) = shared T; 10016 10017 /// 10018 @safe unittest 10019 { 10020 static assert(is(SharedOf!int == shared int)); 10021 static assert(is(SharedOf!(const int) == const shared int)); 10022 static assert(is(SharedOf!(inout int) == inout shared int)); 10023 static assert(is(SharedOf!(shared int) == shared int)); 10024 10025 // Note that shared has no effect on immutable, since immutable is 10026 // implicitly shared. 10027 static assert(is(SharedOf!(immutable int) == immutable int)); 10028 10029 import phobos.sys.meta : AliasSeq, Map; 10030 10031 alias Types = AliasSeq!(int, long, 10032 bool*, ubyte[], 10033 string, immutable(string)); 10034 alias WithShared = Map!(SharedOf, Types); 10035 static assert(is(WithShared == 10036 AliasSeq!(shared int, shared long, 10037 shared(bool*), shared(ubyte[]), 10038 shared(string), immutable(string)))); 10039 } 10040 10041 // Needed for rvalueOf/lvalueOf because 10042 // "inout on return means inout must be on a parameter as well" 10043 private struct __InoutWorkaroundStruct {} 10044 10045 /++ 10046 Creates an lvalue or rvalue of type T to be used in conjunction with 10047 $(D is(typeof(...))) or 10048 $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))). 10049 10050 The idea is that some traits or other forms of conditional compilation need 10051 to verify that a particular piece of code compiles with an rvalue or an 10052 lvalue of a specific type, and these $(D @property) functions allow you to 10053 get an rvalue or lvalue of a specific type to use within an expression that 10054 is then tested to see whether it compiles. 10055 10056 They're $(D @property) functions so that using $(D typeof) on them gives 10057 the return type rather than the type of the function. 10058 10059 Note that these functions are $(I not) defined, so if they're actually used 10060 outside of type introspection, they'll result in linker errors. They're 10061 entirely for testing that a particular piece of code compiles with an rvalue 10062 or lvalue of the given type. 10063 10064 The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that 10065 these work when the given type has the $(D inout) qualifier, since the 10066 language requires that a function that returns an $(D inout) type also have 10067 an $(D inout) type as a parameter. It should just be ignored. 10068 +/ 10069 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 10070 10071 /++ Ditto +/ 10072 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 10073 10074 /// 10075 @safe unittest 10076 { 10077 static int foo(int); 10078 static assert(is(typeof(foo(lvalueOf!int)) == int)); 10079 static assert(is(typeof(foo(rvalueOf!int)) == int)); 10080 10081 static bool bar(ref int); 10082 static assert(is(typeof(bar(lvalueOf!int)) == bool)); 10083 static assert(!is(typeof(bar(rvalueOf!int)))); 10084 10085 static assert( is(typeof({ lvalueOf!int = 42; }))); 10086 static assert(!is(typeof({ rvalueOf!int = 42; }))); 10087 10088 static struct S {} 10089 static assert( is(typeof({ lvalueOf!S = S.init; }))); 10090 static assert(!is(typeof({ rvalueOf!S = S.init; }))); 10091 10092 static struct NoAssign 10093 { 10094 @disable void opAssign(ref NoAssign); 10095 } 10096 static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; }))); 10097 static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; }))); 10098 } 10099 10100 @system unittest 10101 { 10102 import phobos.sys.meta : AliasSeq; 10103 10104 void needLvalue(T)(ref T); 10105 static struct S {} 10106 int i; 10107 struct Nested { void f() { ++i; } } 10108 10109 static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object)) 10110 { 10111 static assert(!__traits(compiles, needLvalue(rvalueOf!T))); 10112 static assert( __traits(compiles, needLvalue(lvalueOf!T))); 10113 static assert(is(typeof(rvalueOf!T) == T)); 10114 static assert(is(typeof(lvalueOf!T) == T)); 10115 } 10116 10117 static assert(!__traits(compiles, rvalueOf!int = 1)); 10118 static assert( __traits(compiles, lvalueOf!byte = 127)); 10119 static assert(!__traits(compiles, lvalueOf!byte = 128)); 10120 } 10121 10122 // We may want to add this as some sort of public test helper in the future in 10123 // whatever module would be appropriate for that. 10124 private template assertWithQualifiers(alias Pred, T, bool expected) 10125 { 10126 static assert(Pred!T == expected); 10127 static assert(Pred!(const T) == expected); 10128 static assert(Pred!(inout T) == expected); 10129 static assert(Pred!(immutable T) == expected); 10130 static assert(Pred!(shared T) == expected); 10131 10132 static if (is(T == U*, U)) 10133 { 10134 static assert(Pred!(const(U)*) == expected); 10135 static assert(Pred!(inout(U)*) == expected); 10136 static assert(Pred!(immutable(U)*) == expected); 10137 static assert(Pred!(shared(U)*) == expected); 10138 } 10139 else static if (is(T == U[], U)) 10140 { 10141 static assert(Pred!(const(U)[]) == expected); 10142 static assert(Pred!(inout(U)[]) == expected); 10143 static assert(Pred!(immutable(U)[]) == expected); 10144 static assert(Pred!(shared(U)[]) == expected); 10145 } 10146 else static if (is(T == U[n], U, size_t n)) 10147 { 10148 static assert(Pred!(const(U)[n]) == expected); 10149 static assert(Pred!(inout(U)[n]) == expected); 10150 static assert(Pred!(immutable(U)[n]) == expected); 10151 static assert(Pred!(shared(U)[n]) == expected); 10152 } 10153 } 10154 10155 private template assertWithQualifiers(alias Pred) 10156 { 10157 alias assertWithQualifiers(T, bool expected) = .assertWithQualifiers!(Pred, T, expected); 10158 } 10159 10160 @safe unittest 10161 { 10162 mixin assertWithQualifiers!(isPointer, int*, true); 10163 mixin assertWithQualifiers!(isPointer, int, false); 10164 10165 alias test = assertWithQualifiers!isPointer; 10166 mixin test!(int*, true); 10167 mixin test!(int, false); 10168 }