1 // Written in the D programming language. 2 3 /** 4 * Templates which extract information about types and symbols at compile time. 5 * 6 * $(SCRIPT inhibitQuickIndex = 1;) 7 * 8 * $(DIVC quickindex, 9 * $(BOOKTABLE , 10 * $(TR $(TH Category) $(TH Templates)) 11 * $(TR $(TD Symbol Name traits) $(TD 12 * $(LREF fullyQualifiedName) 13 * $(LREF moduleName) 14 * $(LREF packageName) 15 * )) 16 * $(TR $(TD Function traits) $(TD 17 * $(LREF isFunction) 18 * $(LREF arity) 19 * $(LREF functionAttributes) 20 * $(LREF hasFunctionAttributes) 21 * $(LREF functionLinkage) 22 * $(LREF FunctionTypeOf) 23 * $(LREF isSafe) 24 * $(LREF isUnsafe) 25 * $(LREF isFinal) 26 * $(LREF ParameterDefaults) 27 * $(LREF ParameterIdentifierTuple) 28 * $(LREF ParameterStorageClassTuple) 29 * $(LREF Parameters) 30 * $(LREF ReturnType) 31 * $(LREF SetFunctionAttributes) 32 * $(LREF variadicFunctionStyle) 33 * )) 34 * $(TR $(TD Aggregate Type traits) $(TD 35 * $(LREF BaseClassesTuple) 36 * $(LREF BaseTypeTuple) 37 * $(LREF classInstanceAlignment) 38 * $(LREF EnumMembers) 39 * $(LREF FieldNameTuple) 40 * $(LREF Fields) 41 * $(LREF hasAliasing) 42 * $(LREF hasElaborateAssign) 43 * $(LREF hasElaborateCopyConstructor) 44 * $(LREF hasElaborateDestructor) 45 * $(LREF hasElaborateMove) 46 * $(LREF hasIndirections) 47 * $(LREF hasMember) 48 * $(LREF hasStaticMember) 49 * $(LREF hasNested) 50 * $(LREF hasUnsharedAliasing) 51 * $(LREF InterfacesTuple) 52 * $(LREF isInnerClass) 53 * $(LREF isNested) 54 * $(LREF MemberFunctionsTuple) 55 * $(LREF RepresentationTypeTuple) 56 * $(LREF TemplateArgsOf) 57 * $(LREF TemplateOf) 58 * $(LREF TransitiveBaseTypeTuple) 59 * )) 60 * $(TR $(TD Type Conversion) $(TD 61 * $(LREF CommonType) 62 * $(LREF ImplicitConversionTargets) 63 * $(LREF CopyTypeQualifiers) 64 * $(LREF CopyConstness) 65 * $(LREF isAssignable) 66 * $(LREF isCovariantWith) 67 * $(LREF isImplicitlyConvertible) 68 * )) 69 * $(TR $(TD SomethingTypeOf) $(TD 70 * $(LREF rvalueOf) 71 * $(LREF lvalueOf) 72 * $(LREF InoutOf) 73 * $(LREF ConstOf) 74 * $(LREF SharedOf) 75 * $(LREF SharedInoutOf) 76 * $(LREF SharedConstOf) 77 * $(LREF ImmutableOf) 78 * $(LREF QualifierOf) 79 * )) 80 * $(TR $(TD Categories of types) $(TD 81 * $(LREF allSameType) 82 * $(LREF ifTestable) 83 * $(LREF isType) 84 * $(LREF isAggregateType) 85 * $(LREF isArray) 86 * $(LREF isAssociativeArray) 87 * $(LREF isAutodecodableString) 88 * $(LREF isBasicType) 89 * $(LREF isBoolean) 90 * $(LREF isBuiltinType) 91 * $(LREF isCopyable) 92 * $(LREF isDynamicArray) 93 * $(LREF isEqualityComparable) 94 * $(LREF isFloatingPoint) 95 * $(LREF isIntegral) 96 * $(LREF isNarrowString) 97 * $(LREF isConvertibleToString) 98 * $(LREF isNumeric) 99 * $(LREF isOrderingComparable) 100 * $(LREF isPointer) 101 * $(LREF isScalarType) 102 * $(LREF isSigned) 103 * $(LREF isSIMDVector) 104 * $(LREF isSomeChar) 105 * $(LREF isSomeString) 106 * $(LREF isStaticArray) 107 * $(LREF isUnsigned) 108 * )) 109 * $(TR $(TD Type behaviours) $(TD 110 * $(LREF isAbstractClass) 111 * $(LREF isAbstractFunction) 112 * $(LREF isCallable) 113 * $(LREF isDelegate) 114 * $(LREF isExpressions) 115 * $(LREF isFinalClass) 116 * $(LREF isFinalFunction) 117 * $(LREF isFunctionPointer) 118 * $(LREF isInstanceOf) 119 * $(LREF isIterable) 120 * $(LREF isMutable) 121 * $(LREF isSomeFunction) 122 * $(LREF isTypeTuple) 123 * )) 124 * $(TR $(TD General Types) $(TD 125 * $(LREF ForeachType) 126 * $(LREF KeyType) 127 * $(LREF Largest) 128 * $(LREF mostNegative) 129 * $(LREF OriginalType) 130 * $(LREF PointerTarget) 131 * $(LREF Signed) 132 * $(LREF Unconst) 133 * $(LREF Unqual) 134 * $(LREF Unsigned) 135 * $(LREF ValueType) 136 * $(LREF Promoted) 137 * )) 138 * $(TR $(TD Misc) $(TD 139 * $(LREF mangledName) 140 * $(LREF Select) 141 * $(LREF select) 142 * )) 143 * $(TR $(TD User-Defined Attributes) $(TD 144 * $(LREF hasUDA) 145 * $(LREF getUDAs) 146 * $(LREF getSymbolsByUDA) 147 * )) 148 * ) 149 * ) 150 * 151 * Copyright: Copyright The D Language Foundation 2005 - 2009. 152 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 153 * Authors: $(HTTP digitalmars.com, Walter Bright), 154 * Tomasz Stachowiak (`isExpressions`), 155 * $(HTTP erdani.org, Andrei Alexandrescu), 156 * Shin Fujishiro, 157 * $(HTTP octarineparrot.com, Robert Clipsham), 158 * $(HTTP klickverbot.at, David Nadlinger), 159 * Kenji Hara, 160 * Shoichi Kato 161 * Source: $(PHOBOSSRC std/traits.d) 162 */ 163 /* Copyright The D Language Foundation 2005 - 2009. 164 * Distributed under the Boost Software License, Version 1.0. 165 * (See accompanying file LICENSE_1_0.txt or copy at 166 * http://www.boost.org/LICENSE_1_0.txt) 167 */ 168 module std.traits; 169 170 import std.meta : AliasSeq, allSatisfy, anySatisfy, ApplyLeft; 171 import std.functional : unaryFun; 172 173 // Legacy inheritance from std.typetuple 174 // See also: https://github.com/dlang/phobos/pull/5484#discussion_r122602797 175 import std.meta : staticMapMeta = staticMap; 176 // TODO: find a way to trigger deprecation warnings 177 //deprecated("staticMap is part of std.meta: Please import std.meta") 178 alias staticMap = staticMapMeta; 179 180 /////////////////////////////////////////////////////////////////////////////// 181 // Functions 182 /////////////////////////////////////////////////////////////////////////////// 183 184 // Petit demangler 185 // (this or similar thing will eventually go to std.demangle if necessary 186 // ctfe stuffs are available) 187 private 188 { 189 struct Demangle(T) 190 { 191 T value; // extracted information 192 string rest; 193 } 194 195 /* Demangles mstr as the storage class part of Argument. */ 196 Demangle!uint demangleParameterStorageClass(string mstr) 197 { 198 uint pstc = 0; // parameter storage class 199 200 // Argument --> Argument2 | M Argument2 201 if (mstr.length > 0 && mstr[0] == 'M') 202 { 203 pstc |= ParameterStorageClass.scope_; 204 mstr = mstr[1 .. $]; 205 } 206 207 // Argument2 --> Type | J Type | K Type | L Type 208 ParameterStorageClass stc2; 209 210 switch (mstr.length ? mstr[0] : char.init) 211 { 212 case 'J': stc2 = ParameterStorageClass.out_; break; 213 case 'K': stc2 = ParameterStorageClass.ref_; break; 214 case 'L': stc2 = ParameterStorageClass.lazy_; break; 215 case 'N': if (mstr.length >= 2 && mstr[1] == 'k') 216 stc2 = ParameterStorageClass.return_; 217 break; 218 default : break; 219 } 220 if (stc2 != ParameterStorageClass.init) 221 { 222 pstc |= stc2; 223 mstr = mstr[1 .. $]; 224 if (stc2 & ParameterStorageClass.return_) 225 mstr = mstr[1 .. $]; 226 } 227 228 return Demangle!uint(pstc, mstr); 229 } 230 231 /* Demangles mstr as FuncAttrs. */ 232 Demangle!uint demangleFunctionAttributes(string mstr) 233 { 234 immutable LOOKUP_ATTRIBUTE = 235 [ 236 'a': FunctionAttribute.pure_, 237 'b': FunctionAttribute.nothrow_, 238 'c': FunctionAttribute.ref_, 239 'd': FunctionAttribute.property, 240 'e': FunctionAttribute.trusted, 241 'f': FunctionAttribute.safe, 242 'i': FunctionAttribute.nogc, 243 'j': FunctionAttribute.return_, 244 'l': FunctionAttribute.scope_, 245 'm': FunctionAttribute.live, 246 ]; 247 uint atts = 0; 248 249 // FuncAttrs --> FuncAttr | FuncAttr FuncAttrs 250 // FuncAttr --> empty | Na | Nb | Nc | Nd | Ne | Nf | Ni | Nj | Nm 251 // except 'Ng' == inout, because it is a qualifier of function type 252 while (mstr.length >= 2 && mstr[0] == 'N' && mstr[1] != 'g' && mstr[1] != 'k') 253 { 254 if (FunctionAttribute att = LOOKUP_ATTRIBUTE[ mstr[1] ]) 255 { 256 atts |= att; 257 mstr = mstr[2 .. $]; 258 } 259 else assert(0); 260 } 261 return Demangle!uint(atts, mstr); 262 } 263 264 static if (is(ucent)) 265 { 266 alias CentTypeList = AliasSeq!(cent, ucent); 267 alias SignedCentTypeList = AliasSeq!(cent); 268 alias UnsignedCentTypeList = AliasSeq!(ucent); 269 } 270 else 271 { 272 alias CentTypeList = AliasSeq!(); 273 alias SignedCentTypeList = AliasSeq!(); 274 alias UnsignedCentTypeList = AliasSeq!(); 275 } 276 277 alias IntegralTypeList = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList); 278 alias SignedIntTypeList = AliasSeq!(byte, short, int, long, SignedCentTypeList); 279 alias UnsignedIntTypeList = AliasSeq!(ubyte, ushort, uint, ulong, UnsignedCentTypeList); 280 alias FloatingPointTypeList = AliasSeq!(float, double, real); 281 alias ImaginaryTypeList = AliasSeq!(ifloat, idouble, ireal); 282 alias ComplexTypeList = AliasSeq!(cfloat, cdouble, creal); 283 alias NumericTypeList = AliasSeq!(IntegralTypeList, FloatingPointTypeList); 284 alias CharTypeList = AliasSeq!(char, wchar, dchar); 285 } 286 287 package 288 { 289 // Add the mutable qualifier to the given type T. 290 template MutableOf(T) { alias MutableOf = T ; } 291 } 292 293 /** 294 * Params: 295 * T = The type to qualify 296 * Returns: 297 * `T` with the `inout` qualifier added. 298 */ 299 template InoutOf(T) 300 { 301 alias InoutOf = inout(T); 302 } 303 304 /// 305 @safe unittest 306 { 307 static assert(is(InoutOf!(int) == inout int)); 308 static assert(is(InoutOf!(inout int) == inout int)); 309 static assert(is(InoutOf!(const int) == inout const int)); 310 static assert(is(InoutOf!(shared int) == inout shared int)); 311 } 312 313 /** 314 * Params: 315 * T = The type to qualify 316 * Returns: 317 * `T` with the `const` qualifier added. 318 */ 319 template ConstOf(T) 320 { 321 alias ConstOf = const(T); 322 } 323 324 /// 325 @safe unittest 326 { 327 static assert(is(ConstOf!(int) == const int)); 328 static assert(is(ConstOf!(const int) == const int)); 329 static assert(is(ConstOf!(inout int) == const inout int)); 330 static assert(is(ConstOf!(shared int) == const shared int)); 331 } 332 333 /** 334 * Params: 335 * T = The type to qualify 336 * Returns: 337 * `T` with the `shared` qualifier added. 338 */ 339 template SharedOf(T) 340 { 341 alias SharedOf = shared(T); 342 } 343 344 /// 345 @safe unittest 346 { 347 static assert(is(SharedOf!(int) == shared int)); 348 static assert(is(SharedOf!(shared int) == shared int)); 349 static assert(is(SharedOf!(inout int) == shared inout int)); 350 static assert(is(SharedOf!(immutable int) == shared immutable int)); 351 } 352 353 /** 354 * Params: 355 * T = The type to qualify 356 * Returns: 357 * `T` with the `inout` and `shared` qualifiers added. 358 */ 359 template SharedInoutOf(T) 360 { 361 alias SharedInoutOf = shared(inout(T)); 362 } 363 364 /// 365 @safe unittest 366 { 367 static assert(is(SharedInoutOf!(int) == shared inout int)); 368 static assert(is(SharedInoutOf!(int) == inout shared int)); 369 370 static assert(is(SharedInoutOf!(const int) == shared inout const int)); 371 static assert(is(SharedInoutOf!(immutable int) == shared inout immutable int)); 372 } 373 374 /** 375 * Params: 376 * T = The type to qualify 377 * Returns: 378 * `T` with the `const` and `shared` qualifiers added. 379 */ 380 template SharedConstOf(T) 381 { 382 alias SharedConstOf = shared(const(T)); 383 } 384 385 /// 386 @safe unittest 387 { 388 static assert(is(SharedConstOf!(int) == shared const int)); 389 static assert(is(SharedConstOf!(int) == const shared int)); 390 391 static assert(is(SharedConstOf!(inout int) == shared inout const int)); 392 // immutable variables are implicitly shared and const 393 static assert(is(SharedConstOf!(immutable int) == immutable int)); 394 } 395 396 /** 397 * Params: 398 * T = The type to qualify 399 * Returns: 400 * `T` with the `immutable` qualifier added. 401 */ 402 template ImmutableOf(T) 403 { 404 alias ImmutableOf = immutable(T); 405 } 406 407 /// 408 @safe unittest 409 { 410 static assert(is(ImmutableOf!(int) == immutable int)); 411 static assert(is(ImmutableOf!(const int) == immutable int)); 412 static assert(is(ImmutableOf!(inout int) == immutable int)); 413 static assert(is(ImmutableOf!(shared int) == immutable int)); 414 } 415 416 @safe unittest 417 { 418 static assert(is( MutableOf!int == int)); 419 static assert(is( InoutOf!int == inout int)); 420 static assert(is( ConstOf!int == const int)); 421 static assert(is( SharedOf!int == shared int)); 422 static assert(is(SharedInoutOf!int == shared inout int)); 423 static assert(is(SharedConstOf!int == shared const int)); 424 static assert(is( ImmutableOf!int == immutable int)); 425 } 426 427 /** 428 * Gives a template that can be used to apply the same 429 * attributes that are on the given type `T`. E.g. passing 430 * `inout shared int` will return `SharedInoutOf`. 431 * 432 * Params: 433 * T = the type to check qualifiers from 434 * Returns: 435 * The qualifier template from the given type `T` 436 */ 437 template QualifierOf(T) 438 { 439 static if (is(T == shared(const U), U)) 440 alias QualifierOf = SharedConstOf; 441 else static if (is(T == const U, U)) 442 alias QualifierOf = ConstOf; 443 else static if (is(T == shared(inout U), U)) 444 alias QualifierOf = SharedInoutOf; 445 else static if (is(T == inout U, U)) 446 alias QualifierOf = InoutOf; 447 else static if (is(T == immutable U, U)) 448 alias QualifierOf = ImmutableOf; 449 else static if (is(T == shared U, U)) 450 alias QualifierOf = SharedOf; 451 else 452 alias QualifierOf = MutableOf; 453 } 454 455 /// 456 @safe unittest 457 { 458 static assert(__traits(isSame, QualifierOf!(immutable int), ImmutableOf)); 459 static assert(__traits(isSame, QualifierOf!(shared int), SharedOf)); 460 static assert(__traits(isSame, QualifierOf!(shared inout int), SharedInoutOf)); 461 } 462 463 @safe unittest 464 { 465 alias Qual1 = QualifierOf!( int); static assert(is(Qual1!long == long)); 466 alias Qual2 = QualifierOf!( inout int); static assert(is(Qual2!long == inout long)); 467 alias Qual3 = QualifierOf!( const int); static assert(is(Qual3!long == const long)); 468 alias Qual4 = QualifierOf!(shared int); static assert(is(Qual4!long == shared long)); 469 alias Qual5 = QualifierOf!(shared inout int); static assert(is(Qual5!long == shared inout long)); 470 alias Qual6 = QualifierOf!(shared const int); static assert(is(Qual6!long == shared const long)); 471 alias Qual7 = QualifierOf!( immutable int); static assert(is(Qual7!long == immutable long)); 472 } 473 474 version (StdUnittest) 475 { 476 alias TypeQualifierList = AliasSeq!(MutableOf, ConstOf, SharedOf, SharedConstOf, ImmutableOf); 477 478 struct SubTypeOf(T) 479 { 480 T val; 481 alias val this; 482 } 483 } 484 485 private alias parentOf(alias sym) = Identity!(__traits(parent, sym)); 486 private alias parentOf(alias sym : T!Args, alias T, Args...) = Identity!(__traits(parent, T)); 487 488 /** 489 * Get the full package name for the given symbol. 490 */ 491 template packageName(alias T) 492 { 493 import std.algorithm.searching : startsWith; 494 495 enum bool isNotFunc = !isSomeFunction!(T); 496 497 static if (__traits(compiles, parentOf!T)) 498 enum parent = packageName!(parentOf!T); 499 else 500 enum string parent = null; 501 502 static if (isNotFunc && T.stringof.startsWith("package ")) 503 enum packageName = (parent.length ? parent ~ '.' : "") ~ T.stringof[8 .. $]; 504 else static if (parent) 505 enum packageName = parent; 506 else 507 static assert(false, T.stringof ~ " has no parent"); 508 } 509 510 /// 511 @safe unittest 512 { 513 static assert(packageName!packageName == "std"); 514 } 515 516 @safe unittest 517 { 518 import std.array; 519 520 static assert(packageName!std == "std"); 521 static assert(packageName!(std.traits) == "std"); // this module 522 static assert(packageName!packageName == "std"); // symbol in this module 523 static assert(packageName!(std.array) == "std"); // other module from same package 524 525 import core.sync.barrier; // local import 526 static assert(packageName!core == "core"); 527 static assert(packageName!(core.sync) == "core.sync"); 528 static assert(packageName!Barrier == "core.sync"); 529 530 struct X12287(T) { T i; } 531 static assert(packageName!(X12287!int.i) == "std"); 532 } 533 534 version (none) @safe unittest //Please uncomment me when changing packageName to test global imports 535 { 536 import core.sync.barrier; // global import 537 static assert(packageName!core == "core"); 538 static assert(packageName!(core.sync) == "core.sync"); 539 static assert(packageName!Barrier == "core.sync"); 540 } 541 542 /// 543 @safe unittest 544 { 545 static assert(packageName!moduleName == "std"); 546 } 547 548 // https://issues.dlang.org/show_bug.cgi?id=13741 549 @safe unittest 550 { 551 import std.ascii : isWhite; 552 static assert(packageName!(isWhite) == "std"); 553 554 struct Foo{void opCall(int){}} 555 static assert(packageName!(Foo.opCall) == "std"); 556 557 @property void function(int) vf; 558 static assert(packageName!(vf) == "std"); 559 } 560 561 /** 562 * Get the module name (including package) for the given symbol. 563 */ 564 template moduleName(alias T) 565 { 566 import std.algorithm.searching : startsWith; 567 568 enum bool isNotFunc = !isSomeFunction!(T); 569 570 static if (isNotFunc) 571 static assert(!T.stringof.startsWith("package "), 572 "cannot get the module name for a package"); 573 574 static if (isNotFunc && T.stringof.startsWith("module ")) 575 { 576 static if (__traits(compiles, packageName!T)) 577 enum packagePrefix = packageName!T ~ '.'; 578 else 579 enum packagePrefix = ""; 580 581 enum moduleName = packagePrefix ~ T.stringof[7..$]; 582 } 583 else 584 alias moduleName = moduleName!(parentOf!T); // If you use enum, it will cause compiler ICE 585 } 586 587 /// 588 @safe unittest 589 { 590 static assert(moduleName!moduleName == "std.traits"); 591 } 592 593 @safe unittest 594 { 595 import std.array; 596 597 static assert(!__traits(compiles, moduleName!std)); 598 static assert(moduleName!(std.traits) == "std.traits"); // this module 599 static assert(moduleName!moduleName == "std.traits"); // symbol in this module 600 static assert(moduleName!(std.array) == "std.array"); // other module 601 static assert(moduleName!(std.array.array) == "std.array"); // symbol in other module 602 603 import core.sync.barrier; // local import 604 static assert(!__traits(compiles, moduleName!(core.sync))); 605 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier"); 606 static assert(moduleName!Barrier == "core.sync.barrier"); 607 608 struct X12287(T) { T i; } 609 static assert(moduleName!(X12287!int.i) == "std.traits"); 610 } 611 612 // https://issues.dlang.org/show_bug.cgi?id=13741 613 @safe unittest 614 { 615 import std.ascii : isWhite; 616 static assert(moduleName!(isWhite) == "std.ascii"); 617 618 struct Foo{void opCall(int){}} 619 static assert(moduleName!(Foo.opCall) == "std.traits"); 620 621 @property void function(int) vf; 622 static assert(moduleName!(vf) == "std.traits"); 623 } 624 625 version (none) @safe unittest //Please uncomment me when changing moduleName to test global imports 626 { 627 import core.sync.barrier; // global import 628 static assert(!__traits(compiles, moduleName!(core.sync))); 629 static assert(moduleName!(core.sync.barrier) == "core.sync.barrier"); 630 static assert(moduleName!Barrier == "core.sync.barrier"); 631 } 632 633 /*** 634 * Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string converter. 635 636 Example: 637 ----------------- 638 module myModule; 639 struct MyStruct {} 640 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])"); 641 ----------------- 642 */ 643 template fullyQualifiedName(T...) 644 if (T.length == 1) 645 { 646 647 static if (is(T)) 648 enum fullyQualifiedName = fqnType!(T[0], false, false, false, false); 649 else 650 enum fullyQualifiedName = fqnSym!(T[0]); 651 } 652 653 /// 654 @safe unittest 655 { 656 static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName"); 657 } 658 659 version (StdUnittest) 660 { 661 // Used for both fqnType and fqnSym unittests 662 private struct QualifiedNameTests 663 { 664 struct Inner 665 { 666 bool value; 667 } 668 669 ref const(Inner[string]) func( ref Inner var1, lazy scope string var2 ); 670 ref const(Inner[string]) retfunc( return ref Inner var1 ); 671 Inner inoutFunc(inout Inner) inout; 672 shared(const(Inner[string])[]) data; 673 const Inner delegate(double, string) @safe nothrow deleg; 674 inout(int) delegate(inout int) inout inoutDeleg; 675 Inner function(out double, string) funcPtr; 676 extern(C) Inner function(double, string) cFuncPtr; 677 678 extern(C) void cVarArg(int, ...); 679 void dVarArg(...); 680 void dVarArg2(int, ...); 681 void typesafeVarArg(int[] ...); 682 683 Inner[] array; 684 Inner[16] sarray; 685 Inner[Inner] aarray; 686 const(Inner[const(Inner)]) qualAarray; 687 688 shared(immutable(Inner) delegate(ref double, scope string) const shared @trusted nothrow) attrDeleg; 689 690 struct Data(T) { int x; } 691 void tfunc(T...)(T args) {} 692 693 template Inst(alias A) { int x; } 694 695 class Test12309(T, int x, string s) {} 696 } 697 698 private enum QualifiedEnum 699 { 700 a = 42 701 } 702 } 703 704 private template fqnSym(alias T : X!A, alias X, A...) 705 { 706 template fqnTuple(T...) 707 { 708 static if (T.length == 0) 709 enum fqnTuple = ""; 710 else static if (T.length == 1) 711 { 712 static if (isExpressionTuple!T) 713 enum fqnTuple = T[0].stringof; 714 else 715 enum fqnTuple = fullyQualifiedName!(T[0]); 716 } 717 else 718 enum fqnTuple = fqnTuple!(T[0]) ~ ", " ~ fqnTuple!(T[1 .. $]); 719 } 720 721 enum fqnSym = 722 fqnSym!(__traits(parent, X)) ~ 723 '.' ~ __traits(identifier, X) ~ "!(" ~ fqnTuple!A ~ ")"; 724 } 725 726 private template fqnSym(alias T) 727 { 728 static if (__traits(compiles, __traits(parent, T)) && !__traits(isSame, T, __traits(parent, T))) 729 enum parentPrefix = fqnSym!(__traits(parent, T)) ~ "."; 730 else 731 enum parentPrefix = null; 732 733 static string adjustIdent(string s) 734 { 735 import std.algorithm.searching : findSplit, skipOver; 736 737 if (s.skipOver("package ") || s.skipOver("module ")) 738 return s; 739 return s.findSplit("(")[0]; 740 } 741 enum fqnSym = parentPrefix ~ adjustIdent(__traits(identifier, T)); 742 } 743 744 @safe unittest 745 { 746 alias fqn = fullyQualifiedName; 747 748 // Make sure those 2 are the same 749 static assert(fqnSym!fqn == fqn!fqn); 750 751 static assert(fqn!fqn == "std.traits.fullyQualifiedName"); 752 753 alias qnTests = QualifiedNameTests; 754 enum prefix = "std.traits.QualifiedNameTests."; 755 static assert(fqn!(qnTests.Inner) == prefix ~ "Inner"); 756 static assert(fqn!(qnTests.func) == prefix ~ "func"); 757 static assert(fqn!(qnTests.Data!int) == prefix ~ "Data!(int)"); 758 static assert(fqn!(qnTests.Data!int.x) == prefix ~ "Data!(int).x"); 759 static assert(fqn!(qnTests.tfunc!(int[])) == prefix ~ "tfunc!(int[])"); 760 static assert(fqn!(qnTests.Inst!(Object)) == prefix ~ "Inst!(object.Object)"); 761 static assert(fqn!(qnTests.Inst!(Object).x) == prefix ~ "Inst!(object.Object).x"); 762 763 static assert(fqn!(qnTests.Test12309!(int, 10, "str")) 764 == prefix ~ "Test12309!(int, 10, \"str\")"); 765 766 import core.sync.barrier; 767 static assert(fqn!Barrier == "core.sync.barrier.Barrier"); 768 } 769 770 @safe unittest 771 { 772 struct TemplatedStruct() 773 { 774 enum foo = 0; 775 } 776 alias TemplatedStructAlias = TemplatedStruct; 777 assert("TemplatedStruct.foo" == fullyQualifiedName!(TemplatedStructAlias!().foo)); 778 } 779 780 private template fqnType(T, 781 bool alreadyConst, bool alreadyImmutable, bool alreadyShared, bool alreadyInout) 782 { 783 import std.format : format; 784 785 // Convenience tags 786 enum { 787 _const = 0, 788 _immutable = 1, 789 _shared = 2, 790 _inout = 3 791 } 792 793 alias qualifiers = AliasSeq!(is(T == const), is(T == immutable), is(T == shared), is(T == inout)); 794 alias noQualifiers = AliasSeq!(false, false, false, false); 795 796 string storageClassesString(uint psc)() @property 797 { 798 import std.conv : text; 799 800 alias PSC = ParameterStorageClass; 801 802 return text( 803 psc & PSC.scope_ ? "scope " : "", 804 psc & PSC.return_ ? "return " : "", 805 psc & PSC.in_ ? "in " : "", 806 psc & PSC.out_ ? "out " : "", 807 psc & PSC.ref_ ? "ref " : "", 808 psc & PSC.lazy_ ? "lazy " : "", 809 ); 810 } 811 812 string parametersTypeString(T)() @property 813 { 814 alias parameters = Parameters!(T); 815 alias parameterStC = ParameterStorageClassTuple!(T); 816 817 enum variadic = variadicFunctionStyle!T; 818 static if (variadic == Variadic.no) 819 enum variadicStr = ""; 820 else static if (variadic == Variadic.c) 821 enum variadicStr = ", ..."; 822 else static if (variadic == Variadic.d) 823 enum variadicStr = parameters.length ? ", ..." : "..."; 824 else static if (variadic == Variadic.typesafe) 825 enum variadicStr = " ..."; 826 else 827 static assert(0, "New variadic style has been added, please update fullyQualifiedName implementation"); 828 829 static if (parameters.length) 830 { 831 import std.algorithm.iteration : map; 832 import std.array : join; 833 import std.meta : staticMap; 834 import std.range : zip; 835 836 string result = join( 837 map!(a => format("%s%s", a[0], a[1]))( 838 zip([staticMap!(storageClassesString, parameterStC)], 839 [staticMap!(fullyQualifiedName, parameters)]) 840 ), 841 ", " 842 ); 843 844 return result ~= variadicStr; 845 } 846 else 847 return variadicStr; 848 } 849 850 string linkageString(T)() @property 851 { 852 enum linkage = functionLinkage!T; 853 854 if (linkage != "D") 855 return format("extern(%s) ", linkage); 856 else 857 return ""; 858 } 859 860 string functionAttributeString(T)() @property 861 { 862 alias FA = FunctionAttribute; 863 enum attrs = functionAttributes!T; 864 865 static if (attrs == FA.none) 866 return ""; 867 else 868 return format("%s%s%s%s%s%s%s%s", 869 attrs & FA.pure_ ? " pure" : "", 870 attrs & FA.nothrow_ ? " nothrow" : "", 871 attrs & FA.ref_ ? " ref" : "", 872 attrs & FA.property ? " @property" : "", 873 attrs & FA.trusted ? " @trusted" : "", 874 attrs & FA.safe ? " @safe" : "", 875 attrs & FA.nogc ? " @nogc" : "", 876 attrs & FA.return_ ? " return" : "" 877 ); 878 } 879 880 string addQualifiers(string typeString, 881 bool addConst, bool addImmutable, bool addShared, bool addInout) 882 { 883 auto result = typeString; 884 if (addShared) 885 { 886 result = format("shared(%s)", result); 887 } 888 if (addConst || addImmutable || addInout) 889 { 890 result = format("%s(%s)", 891 addConst ? "const" : 892 addImmutable ? "immutable" : "inout", 893 result 894 ); 895 } 896 return result; 897 } 898 899 // Convenience template to avoid copy-paste 900 template chain(string current) 901 { 902 enum chain = addQualifiers(current, 903 qualifiers[_const] && !alreadyConst, 904 qualifiers[_immutable] && !alreadyImmutable, 905 qualifiers[_shared] && !alreadyShared, 906 qualifiers[_inout] && !alreadyInout); 907 } 908 909 static if (is(T == string)) 910 { 911 enum fqnType = "string"; 912 } 913 else static if (is(T == wstring)) 914 { 915 enum fqnType = "wstring"; 916 } 917 else static if (is(T == dstring)) 918 { 919 enum fqnType = "dstring"; 920 } 921 else static if (isBasicType!T && !is(T == enum)) 922 { 923 enum fqnType = chain!((Unqual!T).stringof); 924 } 925 else static if (isAggregateType!T || is(T == enum)) 926 { 927 enum fqnType = chain!(fqnSym!T); 928 } 929 else static if (isStaticArray!T) 930 { 931 enum fqnType = chain!( 932 format("%s[%s]", fqnType!(typeof(T.init[0]), qualifiers), T.length) 933 ); 934 } 935 else static if (isArray!T) 936 { 937 enum fqnType = chain!( 938 format("%s[]", fqnType!(typeof(T.init[0]), qualifiers)) 939 ); 940 } 941 else static if (isAssociativeArray!T) 942 { 943 enum fqnType = chain!( 944 format("%s[%s]", fqnType!(ValueType!T, qualifiers), fqnType!(KeyType!T, noQualifiers)) 945 ); 946 } 947 else static if (isSomeFunction!T) 948 { 949 static if (is(T F == delegate)) 950 { 951 enum qualifierString = format("%s%s", 952 is(F == shared) ? " shared" : "", 953 is(F == inout) ? " inout" : 954 is(F == immutable) ? " immutable" : 955 is(F == const) ? " const" : "" 956 ); 957 enum formatStr = "%s%s delegate(%s)%s%s"; 958 enum fqnType = chain!( 959 format(formatStr, linkageString!T, fqnType!(ReturnType!T, noQualifiers), 960 parametersTypeString!(T), functionAttributeString!T, qualifierString) 961 ); 962 } 963 else 964 { 965 static if (isFunctionPointer!T) 966 enum formatStr = "%s%s function(%s)%s"; 967 else 968 enum formatStr = "%s%s(%s)%s"; 969 970 enum fqnType = chain!( 971 format(formatStr, linkageString!T, fqnType!(ReturnType!T, noQualifiers), 972 parametersTypeString!(T), functionAttributeString!T) 973 ); 974 } 975 } 976 else static if (isPointer!T) 977 { 978 enum fqnType = chain!( 979 format("%s*", fqnType!(PointerTarget!T, qualifiers)) 980 ); 981 } 982 else static if (is(T : __vector(V[N]), V, size_t N)) 983 { 984 enum fqnType = chain!( 985 format("__vector(%s[%s])", fqnType!(V, qualifiers), N) 986 ); 987 } 988 else 989 // In case something is forgotten 990 static assert(0, "Unrecognized type " ~ T.stringof ~ ", can't convert to fully qualified string"); 991 } 992 993 @safe unittest 994 { 995 import std.format : format; 996 alias fqn = fullyQualifiedName; 997 998 // Verify those 2 are the same for simple case 999 alias Ambiguous = const(QualifiedNameTests.Inner); 1000 static assert(fqn!Ambiguous == fqnType!(Ambiguous, false, false, false, false)); 1001 1002 // Main tests 1003 enum inner_name = "std.traits.QualifiedNameTests.Inner"; 1004 with (QualifiedNameTests) 1005 { 1006 // Special cases 1007 static assert(fqn!(string) == "string"); 1008 static assert(fqn!(wstring) == "wstring"); 1009 static assert(fqn!(dstring) == "dstring"); 1010 static assert(fqn!(void) == "void"); 1011 static assert(fqn!(const(void)) == "const(void)"); 1012 static assert(fqn!(shared(void)) == "shared(void)"); 1013 static assert(fqn!(shared const(void)) == "const(shared(void))"); 1014 static assert(fqn!(shared inout(void)) == "inout(shared(void))"); 1015 static assert(fqn!(shared inout const(void)) == "const(shared(void))"); 1016 static assert(fqn!(inout(void)) == "inout(void)"); 1017 static assert(fqn!(inout const(void)) == "const(void)"); 1018 static assert(fqn!(immutable(void)) == "immutable(void)"); 1019 1020 // Basic qualified name 1021 static assert(fqn!(Inner) == inner_name); 1022 static assert(fqn!(QualifiedEnum) == "std.traits.QualifiedEnum"); // type 1023 static assert(fqn!(QualifiedEnum.a) == "std.traits.QualifiedEnum.a"); // symbol 1024 1025 // Array types 1026 static assert(fqn!(typeof(array)) == format("%s[]", inner_name)); 1027 static assert(fqn!(typeof(sarray)) == format("%s[16]", inner_name)); 1028 static assert(fqn!(typeof(aarray)) == format("%s[%s]", inner_name, inner_name)); 1029 1030 // qualified key for AA 1031 static assert(fqn!(typeof(qualAarray)) == format("const(%s[const(%s)])", inner_name, inner_name)); 1032 1033 // Qualified composed data types 1034 static assert(fqn!(typeof(data)) == format("shared(const(%s[string])[])", inner_name)); 1035 1036 // Function types + function attributes 1037 static assert(fqn!(typeof(func)) == format("const(%s[string])(ref %s, scope lazy string) ref", 1038 inner_name, inner_name)); 1039 static assert(fqn!(typeof(retfunc)) == format("const(%s[string])(return %s) ref", inner_name, inner_name)); 1040 static assert(fqn!(typeof(inoutFunc)) == format("inout(%s(inout(%s)))", inner_name, inner_name)); 1041 static assert(fqn!(typeof(deleg)) == format("const(%s delegate(double, string) nothrow @safe)", inner_name)); 1042 static assert(fqn!(typeof(inoutDeleg)) == "inout(int) delegate(inout(int)) inout"); 1043 static assert(fqn!(typeof(funcPtr)) == format("%s function(out double, string)", inner_name)); 1044 static assert(fqn!(typeof(cFuncPtr)) == format("extern(C) %s function(double, string)", inner_name)); 1045 1046 // Delegate type with qualified function type 1047 static assert(fqn!(typeof(attrDeleg)) == format("shared(immutable(%s) "~ 1048 "delegate(ref double, scope string) nothrow @trusted shared const)", inner_name)); 1049 1050 // Variable argument function types 1051 static assert(fqn!(typeof(cVarArg)) == "extern(C) void(int, ...)"); 1052 static assert(fqn!(typeof(dVarArg)) == "void(...)"); 1053 static assert(fqn!(typeof(dVarArg2)) == "void(int, ...)"); 1054 static assert(fqn!(typeof(typesafeVarArg)) == "void(int[] ...)"); 1055 1056 // SIMD vector 1057 static if (is(__vector(float[4]))) 1058 { 1059 static assert(fqn!(__vector(float[4])) == "__vector(float[4])"); 1060 } 1061 } 1062 } 1063 1064 /*** 1065 * Get the type of the return value from a function, 1066 * a pointer to function, a delegate, a struct 1067 * with an opCall, a pointer to a struct with an opCall, 1068 * or a class with an `opCall`. Please note that $(D_KEYWORD ref) 1069 * is not part of a type, but the attribute of the function 1070 * (see template $(LREF functionAttributes)). 1071 */ 1072 template ReturnType(func...) 1073 if (func.length == 1 && isCallable!func) 1074 { 1075 static if (is(FunctionTypeOf!func R == return)) 1076 alias ReturnType = R; 1077 else 1078 static assert(0, "argument has no return type"); 1079 } 1080 1081 /// 1082 @safe unittest 1083 { 1084 int foo(); 1085 ReturnType!foo x; // x is declared as int 1086 } 1087 1088 @safe unittest 1089 { 1090 struct G 1091 { 1092 int opCall (int i) { return 1;} 1093 } 1094 1095 alias ShouldBeInt = ReturnType!G; 1096 static assert(is(ShouldBeInt == int)); 1097 1098 G g; 1099 static assert(is(ReturnType!g == int)); 1100 1101 G* p; 1102 alias pg = ReturnType!p; 1103 static assert(is(pg == int)); 1104 1105 class C 1106 { 1107 int opCall (int i) { return 1;} 1108 } 1109 1110 static assert(is(ReturnType!C == int)); 1111 1112 C c; 1113 static assert(is(ReturnType!c == int)); 1114 1115 class Test 1116 { 1117 int prop() @property { return 0; } 1118 } 1119 alias R_Test_prop = ReturnType!(Test.prop); 1120 static assert(is(R_Test_prop == int)); 1121 1122 alias R_dglit = ReturnType!((int a) { return a; }); 1123 static assert(is(R_dglit == int)); 1124 } 1125 1126 /*** 1127 Get, as a tuple, the types of the parameters to a function, a pointer 1128 to function, a delegate, a struct with an `opCall`, a pointer to a 1129 struct with an `opCall`, or a class with an `opCall`. 1130 */ 1131 template Parameters(func...) 1132 if (func.length == 1 && isCallable!func) 1133 { 1134 static if (is(FunctionTypeOf!func P == function)) 1135 alias Parameters = P; 1136 else 1137 static assert(0, "argument has no parameters"); 1138 } 1139 1140 /// 1141 @safe unittest 1142 { 1143 int foo(int, long); 1144 void bar(Parameters!foo); // declares void bar(int, long); 1145 void abc(Parameters!foo[1]); // declares void abc(long); 1146 } 1147 1148 /** 1149 * Alternate name for $(LREF Parameters), kept for legacy compatibility. 1150 */ 1151 alias ParameterTypeTuple = Parameters; 1152 1153 @safe unittest 1154 { 1155 int foo(int i, bool b) { return 0; } 1156 static assert(is(ParameterTypeTuple!foo == AliasSeq!(int, bool))); 1157 static assert(is(ParameterTypeTuple!(typeof(&foo)) == AliasSeq!(int, bool))); 1158 1159 struct S { real opCall(real r, int i) { return 0.0; } } 1160 S s; 1161 static assert(is(ParameterTypeTuple!S == AliasSeq!(real, int))); 1162 static assert(is(ParameterTypeTuple!(S*) == AliasSeq!(real, int))); 1163 static assert(is(ParameterTypeTuple!s == AliasSeq!(real, int))); 1164 1165 class Test 1166 { 1167 int prop() @property { return 0; } 1168 } 1169 alias P_Test_prop = ParameterTypeTuple!(Test.prop); 1170 static assert(P_Test_prop.length == 0); 1171 1172 alias P_dglit = ParameterTypeTuple!((int a){}); 1173 static assert(P_dglit.length == 1); 1174 static assert(is(P_dglit[0] == int)); 1175 } 1176 1177 /** 1178 Returns the number of arguments of function `func`. 1179 arity is undefined for variadic functions. 1180 */ 1181 template arity(func...) 1182 if (func.length == 1 && isCallable!func && 1183 variadicFunctionStyle!func == Variadic.no) 1184 { 1185 enum size_t arity = Parameters!func.length; 1186 } 1187 1188 /// 1189 @safe unittest 1190 { 1191 void foo(){} 1192 static assert(arity!foo == 0); 1193 void bar(uint){} 1194 static assert(arity!bar == 1); 1195 void variadicFoo(uint...){} 1196 static assert(!__traits(compiles, arity!variadicFoo)); 1197 } 1198 1199 // https://issues.dlang.org/show_bug.cgi?id=11389 1200 @safe unittest 1201 { 1202 alias TheType = size_t function( string[] ); 1203 static assert(arity!TheType == 1); 1204 } 1205 1206 /** 1207 Get tuple, one per function parameter, of the storage classes of the parameters. 1208 Params: 1209 func = function symbol or type of function, delegate, or pointer to function 1210 Returns: 1211 A tuple of ParameterStorageClass bits 1212 */ 1213 enum ParameterStorageClass : uint 1214 { 1215 /** 1216 * These flags can be bitwise OR-ed together to represent complex storage 1217 * class. 1218 */ 1219 none = 0x00, 1220 in_ = 0x01, /// ditto 1221 ref_ = 0x02, /// ditto 1222 out_ = 0x04, /// ditto 1223 lazy_ = 0x08, /// ditto 1224 scope_ = 0x10, /// ditto 1225 return_ = 0x20, /// ditto 1226 } 1227 1228 /// ditto 1229 template ParameterStorageClassTuple(func...) 1230 if (func.length == 1 && isCallable!func) 1231 { 1232 alias Func = FunctionTypeOf!func; 1233 1234 static if (is(Func PT == __parameters)) 1235 { 1236 template StorageClass(size_t i) 1237 { 1238 static if (i < PT.length) 1239 { 1240 alias StorageClass = AliasSeq!( 1241 extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)), 1242 StorageClass!(i + 1)); 1243 } 1244 else 1245 alias StorageClass = AliasSeq!(); 1246 } 1247 alias ParameterStorageClassTuple = StorageClass!0; 1248 } 1249 else 1250 { 1251 static assert(0, func[0].stringof ~ " is not a function"); 1252 alias ParameterStorageClassTuple = AliasSeq!(); 1253 } 1254 } 1255 1256 /// 1257 @safe unittest 1258 { 1259 alias STC = ParameterStorageClass; // shorten the enum name 1260 1261 void func(ref int ctx, out real result, in real param, void* ptr) 1262 { 1263 } 1264 alias pstc = ParameterStorageClassTuple!func; 1265 static assert(pstc.length == 4); // number of parameters 1266 static assert(pstc[0] == STC.ref_); 1267 static assert(pstc[1] == STC.out_); 1268 version (none) 1269 { 1270 // TODO: When the DMD PR (dlang/dmd#11474) gets merged, 1271 // remove the versioning and the second test 1272 static assert(pstc[2] == STC.in_); 1273 // This is the current behavior, before `in` is fixed to not be an alias 1274 static assert(pstc[2] == STC.scope_); 1275 } 1276 static assert(pstc[3] == STC.none); 1277 } 1278 1279 /** 1280 Convert the result of `__traits(getParameterStorageClasses)` 1281 to $(LREF ParameterStorageClass) `enum`s. 1282 1283 Params: 1284 Attribs = The return value of `__traits(getParameterStorageClasses)` 1285 Returns: 1286 The bitwise OR of the equivalent $(LREF ParameterStorageClass) `enum`s. 1287 */ 1288 template extractParameterStorageClassFlags(Attribs...) 1289 { 1290 enum ParameterStorageClass extractParameterStorageClassFlags = () 1291 { 1292 auto result = ParameterStorageClass.none; 1293 static if (Attribs.length > 0) 1294 { 1295 static foreach (attrib; Attribs) 1296 { 1297 final switch (attrib) with (ParameterStorageClass) 1298 { 1299 case "scope": result |= scope_; break; 1300 case "in": result |= in_; break; 1301 case "out": result |= out_; break; 1302 case "ref": result |= ref_; break; 1303 case "lazy": result |= lazy_; break; 1304 case "return": result |= return_; break; 1305 } 1306 } 1307 /* Mimic behavor of original version of ParameterStorageClassTuple() 1308 * to avoid breaking existing code. 1309 */ 1310 if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_)) 1311 result = ParameterStorageClass.return_; 1312 } 1313 return result; 1314 }(); 1315 } 1316 1317 /// 1318 @safe unittest 1319 { 1320 static void func(ref int ctx, out real result); 1321 1322 enum param1 = extractParameterStorageClassFlags!( 1323 __traits(getParameterStorageClasses, func, 0) 1324 ); 1325 static assert(param1 == ParameterStorageClass.ref_); 1326 1327 enum param2 = extractParameterStorageClassFlags!( 1328 __traits(getParameterStorageClasses, func, 1) 1329 ); 1330 static assert(param2 == ParameterStorageClass.out_); 1331 1332 enum param3 = extractParameterStorageClassFlags!( 1333 __traits(getParameterStorageClasses, func, 0), 1334 __traits(getParameterStorageClasses, func, 1) 1335 ); 1336 static assert(param3 == (ParameterStorageClass.ref_ | ParameterStorageClass.out_)); 1337 } 1338 1339 @safe unittest 1340 { 1341 alias STC = ParameterStorageClass; 1342 1343 void noparam() {} 1344 static assert(ParameterStorageClassTuple!noparam.length == 0); 1345 1346 ref int test(scope int*, ref int, out int, lazy int, int, return ref int i) { return i; } 1347 alias test_pstc = ParameterStorageClassTuple!test; 1348 static assert(test_pstc.length == 6); 1349 static assert(test_pstc[0] == STC.scope_); 1350 static assert(test_pstc[1] == STC.ref_); 1351 static assert(test_pstc[2] == STC.out_); 1352 static assert(test_pstc[3] == STC.lazy_); 1353 static assert(test_pstc[4] == STC.none); 1354 static assert(test_pstc[5] == STC.return_); 1355 1356 interface Test 1357 { 1358 void test_const(int) const; 1359 void test_sharedconst(int) shared const; 1360 } 1361 Test testi; 1362 1363 alias test_const_pstc = ParameterStorageClassTuple!(Test.test_const); 1364 static assert(test_const_pstc.length == 1); 1365 static assert(test_const_pstc[0] == STC.none); 1366 1367 alias test_sharedconst_pstc = ParameterStorageClassTuple!(testi.test_sharedconst); 1368 static assert(test_sharedconst_pstc.length == 1); 1369 static assert(test_sharedconst_pstc[0] == STC.none); 1370 1371 alias dglit_pstc = ParameterStorageClassTuple!((ref int a) {}); 1372 static assert(dglit_pstc.length == 1); 1373 static assert(dglit_pstc[0] == STC.ref_); 1374 1375 // https://issues.dlang.org/show_bug.cgi?id=9317 1376 static inout(int) func(inout int param) { return param; } 1377 static assert(ParameterStorageClassTuple!(typeof(func))[0] == STC.none); 1378 } 1379 1380 @safe unittest 1381 { 1382 // https://issues.dlang.org/show_bug.cgi?id=14253 1383 static struct Foo { 1384 ref Foo opAssign(ref Foo rhs) return { return this; } 1385 } 1386 1387 alias tup = ParameterStorageClassTuple!(__traits(getOverloads, Foo, "opAssign")[0]); 1388 } 1389 1390 1391 /** 1392 Get, as a tuple, the identifiers of the parameters to a function symbol. 1393 */ 1394 template ParameterIdentifierTuple(func...) 1395 if (func.length == 1 && isCallable!func) 1396 { 1397 static if (is(FunctionTypeOf!func PT == __parameters)) 1398 { 1399 template Get(size_t i) 1400 { 1401 static if (!isFunctionPointer!func && !isDelegate!func 1402 // Unnamed parameters yield CT error. 1403 && is(typeof(__traits(identifier, PT[i .. i+1]))) 1404 // Filter out unnamed args, which look like (Type) instead of (Type name). 1405 && PT[i].stringof != PT[i .. i+1].stringof[1..$-1]) 1406 { 1407 enum Get = __traits(identifier, PT[i .. i+1]); 1408 } 1409 else 1410 { 1411 enum Get = ""; 1412 } 1413 } 1414 } 1415 else 1416 { 1417 static assert(0, func[0].stringof ~ "is not a function"); 1418 1419 // Define dummy entities to avoid pointless errors 1420 template Get(size_t i) { enum Get = ""; } 1421 alias PT = AliasSeq!(); 1422 } 1423 1424 template Impl(size_t i = 0) 1425 { 1426 static if (i == PT.length) 1427 alias Impl = AliasSeq!(); 1428 else 1429 alias Impl = AliasSeq!(Get!i, Impl!(i+1)); 1430 } 1431 1432 alias ParameterIdentifierTuple = Impl!(); 1433 } 1434 1435 /// 1436 @safe unittest 1437 { 1438 int foo(int num, string name, int); 1439 static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]); 1440 } 1441 1442 // https://issues.dlang.org/show_bug.cgi?id=19456 1443 @safe unittest 1444 { 1445 struct SomeType {} 1446 void foo(SomeType); 1447 void bar(int); 1448 static assert([ParameterIdentifierTuple!foo] == [""]); 1449 static assert([ParameterIdentifierTuple!bar] == [""]); 1450 } 1451 1452 @safe unittest 1453 { 1454 alias PIT = ParameterIdentifierTuple; 1455 1456 void bar(int num, string name, int[] array){} 1457 static assert([PIT!bar] == ["num", "name", "array"]); 1458 1459 // might be changed in the future? 1460 void function(int num, string name) fp; 1461 static assert([PIT!fp] == ["", ""]); 1462 1463 // might be changed in the future? 1464 void delegate(int num, string name, int[long] aa) dg; 1465 static assert([PIT!dg] == ["", "", ""]); 1466 1467 interface Test 1468 { 1469 @property string getter(); 1470 @property void setter(int a); 1471 Test method(int a, long b, string c); 1472 } 1473 static assert([PIT!(Test.getter)] == []); 1474 static assert([PIT!(Test.setter)] == ["a"]); 1475 static assert([PIT!(Test.method)] == ["a", "b", "c"]); 1476 1477 /+ 1478 // depends on internal 1479 void baw(int, string, int[]){} 1480 static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]); 1481 1482 // depends on internal 1483 void baz(AliasSeq!(int, string, int[]) args){} 1484 static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]); 1485 +/ 1486 } 1487 1488 1489 /** 1490 Get, as a tuple, the default value of the parameters to a function symbol. 1491 If a parameter doesn't have the default value, `void` is returned instead. 1492 */ 1493 template ParameterDefaults(func...) 1494 if (func.length == 1 && isCallable!func) 1495 { 1496 alias param_names = ParameterIdentifierTuple!func; 1497 static if (is(FunctionTypeOf!(func[0]) PT == __parameters)) 1498 { 1499 template Get(size_t i) 1500 { 1501 // `PT[i .. i+1]` declares a parameter with an arbitrary name. 1502 // To avoid a name clash, generate local names that are distinct 1503 // from the parameter name, and mix them in. 1504 enum name = param_names[i]; 1505 enum args = "args" ~ (name == "args" ? "_" : ""); 1506 enum val = "val" ~ (name == "val" ? "_" : ""); 1507 enum ptr = "ptr" ~ (name == "ptr" ? "_" : ""); 1508 mixin(" 1509 // workaround scope escape check, see 1510 // https://issues.dlang.org/show_bug.cgi?id=16582 1511 // should use return scope once available 1512 enum get = (PT[i .. i+1] " ~ args ~ ") @trusted 1513 { 1514 // If the parameter is lazy, we force it to be evaluated 1515 // like this. 1516 auto " ~ val ~ " = " ~ args ~ "[0]; 1517 auto " ~ ptr ~ " = &" ~ val ~ "; 1518 return *" ~ ptr ~ "; 1519 }; 1520 "); 1521 static if (is(typeof(get()))) 1522 enum Get = get(); 1523 else 1524 alias Get = void; 1525 // If default arg doesn't exist, returns void instead. 1526 } 1527 } 1528 else 1529 { 1530 static assert(0, func[0].stringof ~ "is not a function"); 1531 1532 // Define dummy entities to avoid pointless errors 1533 template Get(size_t i) { enum Get = ""; } 1534 alias PT = AliasSeq!(); 1535 } 1536 1537 template Impl(size_t i = 0) 1538 { 1539 static if (i == PT.length) 1540 alias Impl = AliasSeq!(); 1541 else 1542 alias Impl = AliasSeq!(Get!i, Impl!(i+1)); 1543 } 1544 1545 alias ParameterDefaults = Impl!(); 1546 } 1547 1548 /// 1549 @safe unittest 1550 { 1551 int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0); 1552 static assert(is(ParameterDefaults!foo[0] == void)); 1553 static assert( ParameterDefaults!foo[1] == "hello"); 1554 static assert( ParameterDefaults!foo[2] == [1,2,3]); 1555 static assert( ParameterDefaults!foo[3] == 0); 1556 } 1557 1558 // https://issues.dlang.org/show_bug.cgi?id=17192 1559 @safe unittest 1560 { 1561 static void func(int i, int PT, int __pd_value, int __pd_val, int __args, 1562 int name, int args, int val, int ptr, int args_, int val_, int ptr_) 1563 { 1564 } 1565 alias Voids = ParameterDefaults!func; 1566 static assert(Voids.length == 12); 1567 static foreach (V; Voids) static assert(is(V == void)); 1568 } 1569 1570 /** 1571 * Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility. 1572 */ 1573 alias ParameterDefaultValueTuple = ParameterDefaults; 1574 1575 @safe unittest 1576 { 1577 alias PDVT = ParameterDefaultValueTuple; 1578 1579 void bar(int n = 1, string s = "hello"){} 1580 static assert(PDVT!bar.length == 2); 1581 static assert(PDVT!bar[0] == 1); 1582 static assert(PDVT!bar[1] == "hello"); 1583 static assert(is(typeof(PDVT!bar) == typeof(AliasSeq!(1, "hello")))); 1584 1585 void baz(int x, int n = 1, string s = "hello"){} 1586 static assert(PDVT!baz.length == 3); 1587 static assert(is(PDVT!baz[0] == void)); 1588 static assert( PDVT!baz[1] == 1); 1589 static assert( PDVT!baz[2] == "hello"); 1590 static assert(is(typeof(PDVT!baz) == typeof(AliasSeq!(void, 1, "hello")))); 1591 1592 // property functions return empty string 1593 // https://issues.dlang.org/show_bug.cgi?id=10800 1594 @property void foo(int x = 3) { } 1595 static assert(PDVT!foo.length == 1); 1596 static assert(PDVT!foo[0] == 3); 1597 static assert(is(typeof(PDVT!foo) == typeof(AliasSeq!(3)))); 1598 1599 struct Colour 1600 { 1601 ubyte a,r,g,b; 1602 1603 static immutable Colour white = Colour(255,255,255,255); 1604 } 1605 // https://issues.dlang.org/show_bug.cgi?id=8106 1606 void bug8106(Colour c = Colour.white) {} 1607 //pragma(msg, PDVT!bug8106); 1608 static assert(PDVT!bug8106[0] == Colour.white); 1609 // https://issues.dlang.org/show_bug.cgi?id=16582 1610 void bug16582(scope int* val = null) {} 1611 static assert(PDVT!bug16582[0] is null); 1612 } 1613 1614 1615 /** 1616 Returns the FunctionAttribute mask for function `func`. 1617 1618 See_Also: 1619 $(LREF hasFunctionAttributes) 1620 */ 1621 enum FunctionAttribute : uint 1622 { 1623 /** 1624 * These flags can be bitwise OR-ed together to represent a complex attribute. 1625 */ 1626 none = 0, 1627 pure_ = 1 << 0, /// ditto 1628 nothrow_ = 1 << 1, /// ditto 1629 ref_ = 1 << 2, /// ditto 1630 property = 1 << 3, /// ditto 1631 trusted = 1 << 4, /// ditto 1632 safe = 1 << 5, /// ditto 1633 nogc = 1 << 6, /// ditto 1634 system = 1 << 7, /// ditto 1635 const_ = 1 << 8, /// ditto 1636 immutable_ = 1 << 9, /// ditto 1637 inout_ = 1 << 10, /// ditto 1638 shared_ = 1 << 11, /// ditto 1639 return_ = 1 << 12, /// ditto 1640 scope_ = 1 << 13, /// ditto 1641 live = 1 << 14, /// ditto 1642 } 1643 1644 /// ditto 1645 template functionAttributes(func...) 1646 if (func.length == 1 && isCallable!func) 1647 { 1648 // @bug: workaround for opCall 1649 alias FuncSym = Select!(is(typeof(__traits(getFunctionAttributes, func))), 1650 func, Unqual!(FunctionTypeOf!func)); 1651 1652 enum FunctionAttribute functionAttributes = 1653 extractAttribFlags!(__traits(getFunctionAttributes, FuncSym))(); 1654 } 1655 1656 /// 1657 @safe unittest 1658 { 1659 alias FA = FunctionAttribute; // shorten the enum name 1660 1661 real func(real x) pure nothrow @safe 1662 { 1663 return x; 1664 } 1665 static assert(functionAttributes!func & FA.pure_); 1666 static assert(functionAttributes!func & FA.safe); 1667 static assert(!(functionAttributes!func & FA.trusted)); // not @trusted 1668 } 1669 1670 @system unittest 1671 { 1672 alias FA = FunctionAttribute; 1673 1674 struct S 1675 { 1676 int noF() { return 0; } 1677 int constF() const { return 0; } 1678 int immutableF() immutable { return 0; } 1679 int inoutF() inout { return 0; } 1680 int sharedF() shared { return 0; } 1681 1682 int x; 1683 ref int refF() return { return x; } 1684 int propertyF() @property { return 0; } 1685 int nothrowF() nothrow { return 0; } 1686 int nogcF() @nogc { return 0; } 1687 1688 int systemF() @system { return 0; } 1689 int trustedF() @trusted { return 0; } 1690 int safeF() @safe { return 0; } 1691 1692 int pureF() pure { return 0; } 1693 1694 int liveF() @live { return 0; } 1695 } 1696 1697 static assert(functionAttributes!(S.noF) == FA.system); 1698 static assert(functionAttributes!(typeof(S.noF)) == FA.system); 1699 1700 static assert(functionAttributes!(S.constF) == (FA.const_ | FA.system)); 1701 static assert(functionAttributes!(typeof(S.constF)) == (FA.const_ | FA.system)); 1702 1703 static assert(functionAttributes!(S.immutableF) == (FA.immutable_ | FA.system)); 1704 static assert(functionAttributes!(typeof(S.immutableF)) == (FA.immutable_ | FA.system)); 1705 1706 static assert(functionAttributes!(S.inoutF) == (FA.inout_ | FA.system)); 1707 static assert(functionAttributes!(typeof(S.inoutF)) == (FA.inout_ | FA.system)); 1708 1709 static assert(functionAttributes!(S.sharedF) == (FA.shared_ | FA.system)); 1710 static assert(functionAttributes!(typeof(S.sharedF)) == (FA.shared_ | FA.system)); 1711 1712 static assert(functionAttributes!(S.refF) == (FA.ref_ | FA.system | FA.return_)); 1713 static assert(functionAttributes!(typeof(S.refF)) == (FA.ref_ | FA.system | FA.return_)); 1714 1715 static assert(functionAttributes!(S.propertyF) == (FA.property | FA.system)); 1716 static assert(functionAttributes!(typeof(&S.propertyF)) == (FA.property | FA.system)); 1717 1718 static assert(functionAttributes!(S.nothrowF) == (FA.nothrow_ | FA.system)); 1719 static assert(functionAttributes!(typeof(S.nothrowF)) == (FA.nothrow_ | FA.system)); 1720 1721 static assert(functionAttributes!(S.nogcF) == (FA.nogc | FA.system)); 1722 static assert(functionAttributes!(typeof(S.nogcF)) == (FA.nogc | FA.system)); 1723 1724 static assert(functionAttributes!(S.systemF) == FA.system); 1725 static assert(functionAttributes!(typeof(S.systemF)) == FA.system); 1726 1727 static assert(functionAttributes!(S.trustedF) == FA.trusted); 1728 static assert(functionAttributes!(typeof(S.trustedF)) == FA.trusted); 1729 1730 static assert(functionAttributes!(S.safeF) == FA.safe); 1731 static assert(functionAttributes!(typeof(S.safeF)) == FA.safe); 1732 1733 static assert(functionAttributes!(S.pureF) == (FA.pure_ | FA.system)); 1734 static assert(functionAttributes!(typeof(S.pureF)) == (FA.pure_ | FA.system)); 1735 1736 static assert(functionAttributes!(S.liveF) == (FA.live | FA.system)); 1737 static assert(functionAttributes!(typeof(S.liveF)) == (FA.live | FA.system)); 1738 1739 int pure_nothrow() nothrow pure; 1740 void safe_nothrow() @safe nothrow; 1741 static ref int static_ref_property() @property; 1742 ref int ref_property() @property; 1743 1744 static assert(functionAttributes!(pure_nothrow) == (FA.pure_ | FA.nothrow_ | FA.system)); 1745 static assert(functionAttributes!(typeof(pure_nothrow)) == (FA.pure_ | FA.nothrow_ | FA.system)); 1746 1747 static assert(functionAttributes!(safe_nothrow) == (FA.safe | FA.nothrow_)); 1748 static assert(functionAttributes!(typeof(safe_nothrow)) == (FA.safe | FA.nothrow_)); 1749 1750 static assert(functionAttributes!(static_ref_property) == (FA.property | FA.ref_ | FA.system)); 1751 static assert(functionAttributes!(typeof(&static_ref_property)) == (FA.property | FA.ref_ | FA.system)); 1752 1753 static assert(functionAttributes!(ref_property) == (FA.property | FA.ref_ | FA.system)); 1754 static assert(functionAttributes!(typeof(&ref_property)) == (FA.property | FA.ref_ | FA.system)); 1755 1756 struct S2 1757 { 1758 int pure_const() const pure { return 0; } 1759 int pure_sharedconst() const shared pure { return 0; } 1760 } 1761 1762 static assert(functionAttributes!(S2.pure_const) == (FA.const_ | FA.pure_ | FA.system)); 1763 static assert(functionAttributes!(typeof(S2.pure_const)) == (FA.const_ | FA.pure_ | FA.system)); 1764 1765 static assert(functionAttributes!(S2.pure_sharedconst) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system)); 1766 static assert(functionAttributes!(typeof(S2.pure_sharedconst)) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system)); 1767 1768 static assert(functionAttributes!((int a) { }) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe)); 1769 static assert(functionAttributes!(typeof((int a) { })) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe)); 1770 1771 auto safeDel = delegate() @safe { }; 1772 static assert(functionAttributes!(safeDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe)); 1773 static assert(functionAttributes!(typeof(safeDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe)); 1774 1775 auto trustedDel = delegate() @trusted { }; 1776 static assert(functionAttributes!(trustedDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted)); 1777 static assert(functionAttributes!(typeof(trustedDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted)); 1778 1779 auto systemDel = delegate() @system { }; 1780 static assert(functionAttributes!(systemDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system)); 1781 static assert(functionAttributes!(typeof(systemDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system)); 1782 } 1783 1784 private FunctionAttribute extractAttribFlags(Attribs...)() 1785 { 1786 auto res = FunctionAttribute.none; 1787 1788 static foreach (attrib; Attribs) 1789 { 1790 switch (attrib) with (FunctionAttribute) 1791 { 1792 case "pure": res |= pure_; break; 1793 case "nothrow": res |= nothrow_; break; 1794 case "ref": res |= ref_; break; 1795 case "@property": res |= property; break; 1796 case "@trusted": res |= trusted; break; 1797 case "@safe": res |= safe; break; 1798 case "@nogc": res |= nogc; break; 1799 case "@system": res |= system; break; 1800 case "const": res |= const_; break; 1801 case "immutable": res |= immutable_; break; 1802 case "inout": res |= inout_; break; 1803 case "shared": res |= shared_; break; 1804 case "return": res |= return_; break; 1805 case "scope": res |= scope_; break; 1806 case "@live": res |= live; break; 1807 default: assert(0, attrib); 1808 } 1809 } 1810 1811 return res; 1812 } 1813 1814 /** 1815 Checks whether a function has the given attributes attached. 1816 1817 Params: 1818 args = Function to check, followed by a 1819 variadic number of function attributes as strings 1820 1821 Returns: 1822 `true`, if the function has the list of attributes attached and `false` otherwise. 1823 1824 See_Also: 1825 $(LREF functionAttributes) 1826 */ 1827 template hasFunctionAttributes(args...) 1828 if (args.length > 0 && isCallable!(args[0]) 1829 && allSatisfy!(isSomeString, typeof(args[1 .. $]))) 1830 { 1831 enum bool hasFunctionAttributes = { 1832 import std.algorithm.searching : canFind; 1833 import std.range : only; 1834 enum funcAttribs = only(__traits(getFunctionAttributes, args[0])); 1835 static foreach (attribute; args[1 .. $]) 1836 { 1837 if (!funcAttribs.canFind(attribute)) 1838 return false; 1839 } 1840 return true; 1841 }(); 1842 } 1843 1844 /// 1845 @safe unittest 1846 { 1847 real func(real x) pure nothrow @safe; 1848 static assert(hasFunctionAttributes!(func, "@safe", "pure")); 1849 static assert(!hasFunctionAttributes!(func, "@trusted")); 1850 1851 // for templates attributes are automatically inferred 1852 bool myFunc(T)(T b) 1853 { 1854 return !b; 1855 } 1856 static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow")); 1857 static assert(!hasFunctionAttributes!(myFunc!bool, "shared")); 1858 } 1859 1860 @system unittest 1861 { 1862 struct S 1863 { 1864 int noF(); 1865 int constF() const; 1866 int immutableF() immutable; 1867 int inoutF() inout; 1868 int sharedF() shared; 1869 1870 ref int refF() return; 1871 int propertyF() @property; 1872 int nothrowF() nothrow; 1873 int nogcF() @nogc; 1874 1875 int systemF() @system; 1876 int trustedF() @trusted; 1877 int safeF() @safe; 1878 1879 int pureF() pure; 1880 1881 int liveF() @live; 1882 } 1883 1884 // true if no args passed 1885 static assert(hasFunctionAttributes!(S.noF)); 1886 1887 static assert(hasFunctionAttributes!(S.noF, "@system")); 1888 static assert(hasFunctionAttributes!(typeof(S.noF), "@system")); 1889 static assert(!hasFunctionAttributes!(S.noF, "@system", "pure")); 1890 1891 static assert(hasFunctionAttributes!(S.constF, "const", "@system")); 1892 static assert(hasFunctionAttributes!(typeof(S.constF), "const", "@system")); 1893 static assert(!hasFunctionAttributes!(S.constF, "const", "@system", "@nogc")); 1894 1895 static assert(hasFunctionAttributes!(S.immutableF, "immutable", "@system")); 1896 static assert(hasFunctionAttributes!(typeof(S.immutableF), "immutable", "@system")); 1897 static assert(!hasFunctionAttributes!(S.immutableF, "immutable", "@system", "pure")); 1898 1899 static assert(hasFunctionAttributes!(S.inoutF, "inout", "@system")); 1900 static assert(hasFunctionAttributes!(typeof(S.inoutF), "inout", "@system")); 1901 static assert(!hasFunctionAttributes!(S.inoutF, "inout", "@system", "pure")); 1902 1903 static assert(hasFunctionAttributes!(S.sharedF, "shared", "@system")); 1904 static assert(hasFunctionAttributes!(typeof(S.sharedF), "shared", "@system")); 1905 static assert(!hasFunctionAttributes!(S.sharedF, "shared", "@system", "@trusted")); 1906 1907 static assert(hasFunctionAttributes!(S.refF, "ref", "@system", "return")); 1908 static assert(hasFunctionAttributes!(typeof(S.refF), "ref", "@system", "return")); 1909 static assert(!hasFunctionAttributes!(S.refF, "ref", "@system", "return", "pure")); 1910 1911 static assert(hasFunctionAttributes!(S.propertyF, "@property", "@system")); 1912 static assert(hasFunctionAttributes!(typeof(&S.propertyF), "@property", "@system")); 1913 static assert(!hasFunctionAttributes!(S.propertyF, "@property", "@system", "ref")); 1914 1915 static assert(hasFunctionAttributes!(S.nothrowF, "nothrow", "@system")); 1916 static assert(hasFunctionAttributes!(typeof(S.nothrowF), "nothrow", "@system")); 1917 static assert(!hasFunctionAttributes!(S.nothrowF, "nothrow", "@system", "@trusted")); 1918 1919 static assert(hasFunctionAttributes!(S.nogcF, "@nogc", "@system")); 1920 static assert(hasFunctionAttributes!(typeof(S.nogcF), "@nogc", "@system")); 1921 static assert(!hasFunctionAttributes!(S.nogcF, "@nogc", "@system", "ref")); 1922 1923 static assert(hasFunctionAttributes!(S.systemF, "@system")); 1924 static assert(hasFunctionAttributes!(typeof(S.systemF), "@system")); 1925 static assert(!hasFunctionAttributes!(S.systemF, "@system", "ref")); 1926 1927 static assert(hasFunctionAttributes!(S.trustedF, "@trusted")); 1928 static assert(hasFunctionAttributes!(typeof(S.trustedF), "@trusted")); 1929 static assert(!hasFunctionAttributes!(S.trustedF, "@trusted", "@safe")); 1930 1931 static assert(hasFunctionAttributes!(S.safeF, "@safe")); 1932 static assert(hasFunctionAttributes!(typeof(S.safeF), "@safe")); 1933 static assert(!hasFunctionAttributes!(S.safeF, "@safe", "nothrow")); 1934 1935 static assert(hasFunctionAttributes!(S.pureF, "pure", "@system")); 1936 static assert(hasFunctionAttributes!(typeof(S.pureF), "pure", "@system")); 1937 static assert(!hasFunctionAttributes!(S.pureF, "pure", "@system", "ref")); 1938 1939 static assert(hasFunctionAttributes!(S.liveF, "@live", "@system")); 1940 static assert(hasFunctionAttributes!(typeof(S.liveF), "@live", "@system")); 1941 static assert(!hasFunctionAttributes!(S.liveF, "@live", "@system", "ref")); 1942 1943 int pure_nothrow() nothrow pure { return 0; } 1944 void safe_nothrow() @safe nothrow { } 1945 static ref int static_ref_property() @property { return *(new int); } 1946 ref int ref_property() @property { return *(new int); } 1947 1948 static assert(hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe")); 1949 static assert(hasFunctionAttributes!(typeof(pure_nothrow), "pure", "nothrow", "@safe")); 1950 static assert(!hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe", "@trusted")); 1951 1952 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow")); 1953 static assert(hasFunctionAttributes!(typeof(safe_nothrow), "@safe", "nothrow")); 1954 static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure")); 1955 static assert(!hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure", "@trusted")); 1956 1957 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe")); 1958 static assert(hasFunctionAttributes!(typeof(&static_ref_property), "@property", "ref", "@safe")); 1959 static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow")); 1960 static assert(!hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow", "@nogc")); 1961 1962 static assert(hasFunctionAttributes!(ref_property, "@property", "ref", "@safe")); 1963 static assert(hasFunctionAttributes!(typeof(&ref_property), "@property", "ref", "@safe")); 1964 static assert(!hasFunctionAttributes!(ref_property, "@property", "ref", "@safe", "@nogc")); 1965 1966 struct S2 1967 { 1968 int pure_const() const pure { return 0; } 1969 int pure_sharedconst() const shared pure { return 0; } 1970 } 1971 1972 static assert(hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system")); 1973 static assert(hasFunctionAttributes!(typeof(S2.pure_const), "const", "pure", "@system")); 1974 static assert(!hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system", "ref")); 1975 1976 static assert(hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system")); 1977 static assert(hasFunctionAttributes!(typeof(S2.pure_sharedconst), "const", "shared", "pure", "@system")); 1978 static assert(!hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system", "@nogc")); 1979 1980 static assert(hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe")); 1981 static assert(hasFunctionAttributes!(typeof((int a) { }), "pure", "nothrow", "@nogc", "@safe")); 1982 static assert(!hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe", "ref")); 1983 1984 auto safeDel = delegate() @safe { }; 1985 static assert(hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe")); 1986 static assert(hasFunctionAttributes!(typeof(safeDel), "pure", "nothrow", "@nogc", "@safe")); 1987 static assert(!hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe", "@system")); 1988 1989 auto trustedDel = delegate() @trusted { }; 1990 static assert(hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted")); 1991 static assert(hasFunctionAttributes!(typeof(trustedDel), "pure", "nothrow", "@nogc", "@trusted")); 1992 static assert(!hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted", "ref")); 1993 1994 auto systemDel = delegate() @system { }; 1995 static assert(hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system")); 1996 static assert(hasFunctionAttributes!(typeof(systemDel), "pure", "nothrow", "@nogc", "@system")); 1997 static assert(!hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system", "@property")); 1998 1999 2000 // call functions to make CodeCov happy 2001 { 2002 assert(pure_nothrow == 0); 2003 safe_nothrow; 2004 assert(static_ref_property == 0); 2005 assert(ref_property == 0); 2006 assert(S2().pure_const == 0); 2007 assert((shared S2()).pure_sharedconst == 0); 2008 cast(void) safeDel; 2009 cast(void) trustedDel; 2010 cast(void) systemDel; 2011 } 2012 } 2013 2014 /** 2015 `true` if `func` is `@safe` or `@trusted`. 2016 */ 2017 template isSafe(alias func) 2018 if (isCallable!func) 2019 { 2020 enum isSafe = (functionAttributes!func & FunctionAttribute.safe) != 0 || 2021 (functionAttributes!func & FunctionAttribute.trusted) != 0; 2022 } 2023 2024 /// 2025 @safe unittest 2026 { 2027 @safe int add(int a, int b) {return a+b;} 2028 @trusted int sub(int a, int b) {return a-b;} 2029 @system int mul(int a, int b) {return a*b;} 2030 2031 static assert( isSafe!add); 2032 static assert( isSafe!sub); 2033 static assert(!isSafe!mul); 2034 } 2035 2036 2037 @safe unittest 2038 { 2039 //Member functions 2040 interface Set 2041 { 2042 int systemF() @system; 2043 int trustedF() @trusted; 2044 int safeF() @safe; 2045 } 2046 static assert( isSafe!(Set.safeF)); 2047 static assert( isSafe!(Set.trustedF)); 2048 static assert(!isSafe!(Set.systemF)); 2049 2050 //Functions 2051 @safe static void safeFunc() {} 2052 @trusted static void trustedFunc() {} 2053 @system static void systemFunc() {} 2054 2055 static assert( isSafe!safeFunc); 2056 static assert( isSafe!trustedFunc); 2057 static assert(!isSafe!systemFunc); 2058 2059 //Delegates 2060 auto safeDel = delegate() @safe {}; 2061 auto trustedDel = delegate() @trusted {}; 2062 auto systemDel = delegate() @system {}; 2063 2064 static assert( isSafe!safeDel); 2065 static assert( isSafe!trustedDel); 2066 static assert(!isSafe!systemDel); 2067 2068 //Lambdas 2069 static assert( isSafe!({safeDel();})); 2070 static assert( isSafe!({trustedDel();})); 2071 static assert(!isSafe!({systemDel();})); 2072 2073 //Static opCall 2074 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } } 2075 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } } 2076 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } } 2077 2078 static assert( isSafe!(SafeStatic())); 2079 static assert( isSafe!(TrustedStatic())); 2080 static assert(!isSafe!(SystemStatic())); 2081 2082 //Non-static opCall 2083 struct Safe { @safe Safe opCall() { return Safe.init; } } 2084 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } } 2085 struct System { @system System opCall() { return System.init; } } 2086 2087 static assert( isSafe!(Safe.init())); 2088 static assert( isSafe!(Trusted.init())); 2089 static assert(!isSafe!(System.init())); 2090 } 2091 2092 2093 /** 2094 `true` if `func` is `@system`. 2095 */ 2096 template isUnsafe(alias func) 2097 { 2098 enum isUnsafe = !isSafe!func; 2099 } 2100 2101 /// 2102 @safe unittest 2103 { 2104 @safe int add(int a, int b) {return a+b;} 2105 @trusted int sub(int a, int b) {return a-b;} 2106 @system int mul(int a, int b) {return a*b;} 2107 2108 static assert(!isUnsafe!add); 2109 static assert(!isUnsafe!sub); 2110 static assert( isUnsafe!mul); 2111 } 2112 2113 @safe unittest 2114 { 2115 //Member functions 2116 interface Set 2117 { 2118 int systemF() @system; 2119 int trustedF() @trusted; 2120 int safeF() @safe; 2121 } 2122 static assert(!isUnsafe!(Set.safeF)); 2123 static assert(!isUnsafe!(Set.trustedF)); 2124 static assert( isUnsafe!(Set.systemF)); 2125 2126 //Functions 2127 @safe static void safeFunc() {} 2128 @trusted static void trustedFunc() {} 2129 @system static void systemFunc() {} 2130 2131 static assert(!isUnsafe!safeFunc); 2132 static assert(!isUnsafe!trustedFunc); 2133 static assert( isUnsafe!systemFunc); 2134 2135 //Delegates 2136 auto safeDel = delegate() @safe {}; 2137 auto trustedDel = delegate() @trusted {}; 2138 auto systemDel = delegate() @system {}; 2139 2140 static assert(!isUnsafe!safeDel); 2141 static assert(!isUnsafe!trustedDel); 2142 static assert( isUnsafe!systemDel); 2143 2144 //Lambdas 2145 static assert(!isUnsafe!({safeDel();})); 2146 static assert(!isUnsafe!({trustedDel();})); 2147 static assert( isUnsafe!({systemDel();})); 2148 2149 //Static opCall 2150 struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } } 2151 struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } } 2152 struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } } 2153 2154 static assert(!isUnsafe!(SafeStatic())); 2155 static assert(!isUnsafe!(TrustedStatic())); 2156 static assert( isUnsafe!(SystemStatic())); 2157 2158 //Non-static opCall 2159 struct Safe { @safe Safe opCall() { return Safe.init; } } 2160 struct Trusted { @trusted Trusted opCall() { return Trusted.init; } } 2161 struct System { @system System opCall() { return System.init; } } 2162 2163 static assert(!isUnsafe!(Safe.init())); 2164 static assert(!isUnsafe!(Trusted.init())); 2165 static assert( isUnsafe!(System.init())); 2166 } 2167 2168 2169 /** 2170 Determine the linkage attribute of the function. 2171 Params: 2172 func = the function symbol, or the type of a function, delegate, or pointer to function 2173 Returns: 2174 one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System". 2175 */ 2176 template functionLinkage(func...) 2177 if (func.length == 1 && isCallable!func) 2178 { 2179 enum string functionLinkage = __traits(getLinkage, FunctionTypeOf!func); 2180 } 2181 2182 /// 2183 @safe unittest 2184 { 2185 extern(D) void Dfunc() {} 2186 extern(C) void Cfunc() {} 2187 static assert(functionLinkage!Dfunc == "D"); 2188 static assert(functionLinkage!Cfunc == "C"); 2189 2190 string a = functionLinkage!Dfunc; 2191 assert(a == "D"); 2192 2193 auto fp = &Cfunc; 2194 string b = functionLinkage!fp; 2195 assert(b == "C"); 2196 } 2197 2198 @safe unittest 2199 { 2200 interface Test 2201 { 2202 void const_func() const; 2203 void sharedconst_func() shared const; 2204 } 2205 static assert(functionLinkage!(Test.const_func) == "D"); 2206 static assert(functionLinkage!(Test.sharedconst_func) == "D"); 2207 2208 static assert(functionLinkage!((int a){}) == "D"); 2209 } 2210 2211 2212 /** 2213 Determines what kind of variadic parameters function has. 2214 Params: 2215 func = function symbol or type of function, delegate, or pointer to function 2216 Returns: 2217 enum Variadic 2218 */ 2219 enum Variadic 2220 { 2221 /// Function is not variadic. 2222 no, 2223 /// Function is a _C-style variadic function, which uses 2224 /// `core.stdc.stdarg` 2225 c, 2226 /// Function is a _D-style variadic function, which uses 2227 /// `__argptr` and `__arguments`. 2228 d, 2229 /// Function is a typesafe variadic function. 2230 typesafe, 2231 } 2232 2233 /// ditto 2234 template variadicFunctionStyle(func...) 2235 if (func.length == 1 && isCallable!func) 2236 { 2237 enum string varargs = __traits(getFunctionVariadicStyle, FunctionTypeOf!func); 2238 enum Variadic variadicFunctionStyle = 2239 (varargs == "stdarg") ? Variadic.c : 2240 (varargs == "argptr") ? Variadic.d : 2241 (varargs == "typesafe") ? Variadic.typesafe : 2242 (varargs == "none") ? Variadic.no : Variadic.no; 2243 } 2244 2245 /// 2246 @safe unittest 2247 { 2248 void func() {} 2249 static assert(variadicFunctionStyle!func == Variadic.no); 2250 2251 extern(C) int printf(in char*, ...); 2252 static assert(variadicFunctionStyle!printf == Variadic.c); 2253 } 2254 2255 @safe unittest 2256 { 2257 import core.vararg; 2258 2259 extern(D) void novar() {} 2260 extern(C) void cstyle(int, ...) {} 2261 extern(D) void dstyle(...) {} 2262 extern(D) void typesafe(int[]...) {} 2263 2264 static assert(variadicFunctionStyle!novar == Variadic.no); 2265 static assert(variadicFunctionStyle!cstyle == Variadic.c); 2266 static assert(variadicFunctionStyle!dstyle == Variadic.d); 2267 static assert(variadicFunctionStyle!typesafe == Variadic.typesafe); 2268 2269 static assert(variadicFunctionStyle!((int[] a...) {}) == Variadic.typesafe); 2270 } 2271 2272 2273 /** 2274 Get the function type from a callable object `func`. 2275 2276 Using builtin `typeof` on a property function yields the types of the 2277 property value, not of the property function itself. Still, 2278 `FunctionTypeOf` is able to obtain function types of properties. 2279 2280 Note: 2281 Do not confuse function types with function pointer types; function types are 2282 usually used for compile-time reflection purposes. 2283 */ 2284 template FunctionTypeOf(func...) 2285 if (func.length == 1 && isCallable!func) 2286 { 2287 static if (is(typeof(& func[0]) Fsym : Fsym*) && is(Fsym == function) || is(typeof(& func[0]) Fsym == delegate)) 2288 { 2289 alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol 2290 } 2291 else static if (is(typeof(& func[0].opCall) Fobj == delegate)) 2292 { 2293 alias FunctionTypeOf = Fobj; // HIT: callable object 2294 } 2295 else static if (is(typeof(& func[0].opCall) Ftyp : Ftyp*) && is(Ftyp == function)) 2296 { 2297 alias FunctionTypeOf = Ftyp; // HIT: callable type 2298 } 2299 else static if (is(func[0] T) || is(typeof(func[0]) T)) 2300 { 2301 static if (is(T == function)) 2302 alias FunctionTypeOf = T; // HIT: function 2303 else static if (is(T Fptr : Fptr*) && is(Fptr == function)) 2304 alias FunctionTypeOf = Fptr; // HIT: function pointer 2305 else static if (is(T Fdlg == delegate)) 2306 alias FunctionTypeOf = Fdlg; // HIT: delegate 2307 else 2308 static assert(0); 2309 } 2310 else 2311 static assert(0); 2312 } 2313 2314 /// 2315 @safe unittest 2316 { 2317 class C 2318 { 2319 int value() @property { return 0; } 2320 } 2321 static assert(is( typeof(C.value) == int )); 2322 static assert(is( FunctionTypeOf!(C.value) == function )); 2323 } 2324 2325 @system unittest 2326 { 2327 int test(int a); 2328 int propGet() @property; 2329 int propSet(int a) @property; 2330 int function(int) test_fp; 2331 int delegate(int) test_dg; 2332 static assert(is( typeof(test) == FunctionTypeOf!(typeof(test)) )); 2333 static assert(is( typeof(test) == FunctionTypeOf!test )); 2334 static assert(is( typeof(test) == FunctionTypeOf!test_fp )); 2335 static assert(is( typeof(test) == FunctionTypeOf!test_dg )); 2336 alias int GetterType() @property; 2337 alias int SetterType(int) @property; 2338 static assert(is( FunctionTypeOf!propGet == GetterType )); 2339 static assert(is( FunctionTypeOf!propSet == SetterType )); 2340 2341 interface Prop { int prop() @property; } 2342 Prop prop; 2343 static assert(is( FunctionTypeOf!(Prop.prop) == GetterType )); 2344 static assert(is( FunctionTypeOf!(prop.prop) == GetterType )); 2345 2346 class Callable { int opCall(int) { return 0; } } 2347 auto call = new Callable; 2348 static assert(is( FunctionTypeOf!call == typeof(test) )); 2349 2350 struct StaticCallable { static int opCall(int) { return 0; } } 2351 StaticCallable stcall_val; 2352 StaticCallable* stcall_ptr; 2353 static assert(is( FunctionTypeOf!stcall_val == typeof(test) )); 2354 static assert(is( FunctionTypeOf!stcall_ptr == typeof(test) )); 2355 2356 interface Overloads 2357 { 2358 void test(string); 2359 real test(real); 2360 int test(int); 2361 int test() @property; 2362 } 2363 alias ov = __traits(getVirtualFunctions, Overloads, "test"); 2364 alias F_ov0 = FunctionTypeOf!(ov[0]); 2365 alias F_ov1 = FunctionTypeOf!(ov[1]); 2366 alias F_ov2 = FunctionTypeOf!(ov[2]); 2367 alias F_ov3 = FunctionTypeOf!(ov[3]); 2368 static assert(is(F_ov0* == void function(string))); 2369 static assert(is(F_ov1* == real function(real))); 2370 static assert(is(F_ov2* == int function(int))); 2371 static assert(is(F_ov3* == int function() @property)); 2372 2373 alias F_dglit = FunctionTypeOf!((int a){ return a; }); 2374 static assert(is(F_dglit* : int function(int))); 2375 } 2376 2377 /** 2378 * Constructs a new function or delegate type with the same basic signature 2379 * as the given one, but different attributes (including linkage). 2380 * 2381 * This is especially useful for adding/removing attributes to/from types in 2382 * generic code, where the actual type name cannot be spelt out. 2383 * 2384 * Params: 2385 * T = The base type. 2386 * linkage = The desired linkage of the result type. 2387 * attrs = The desired $(LREF FunctionAttribute)s of the result type. 2388 */ 2389 template SetFunctionAttributes(T, string linkage, uint attrs) 2390 if (isFunctionPointer!T || isDelegate!T) 2391 { 2392 mixin({ 2393 import std.algorithm.searching : canFind; 2394 2395 static assert(!(attrs & FunctionAttribute.trusted) || 2396 !(attrs & FunctionAttribute.safe), 2397 "Cannot have a function/delegate that is both trusted and safe."); 2398 2399 static immutable linkages = ["D", "C", "Windows", "C++", "System"]; 2400 static assert(canFind(linkages, linkage), "Invalid linkage '" ~ 2401 linkage ~ "', must be one of " ~ linkages.stringof ~ "."); 2402 2403 string result = "alias "; 2404 2405 static if (linkage != "D") 2406 result ~= "extern(" ~ linkage ~ ") "; 2407 2408 static if (attrs & FunctionAttribute.ref_) 2409 result ~= "ref "; 2410 2411 result ~= "ReturnType!T"; 2412 2413 static if (isDelegate!T) 2414 result ~= " delegate"; 2415 else 2416 result ~= " function"; 2417 2418 result ~= "("; 2419 2420 static if (Parameters!T.length > 0) 2421 result ~= "Parameters!T"; 2422 2423 enum varStyle = variadicFunctionStyle!T; 2424 static if (varStyle == Variadic.c) 2425 result ~= ", ..."; 2426 else static if (varStyle == Variadic.d) 2427 result ~= "..."; 2428 else static if (varStyle == Variadic.typesafe) 2429 result ~= "..."; 2430 2431 result ~= ")"; 2432 2433 static if (attrs & FunctionAttribute.pure_) 2434 result ~= " pure"; 2435 static if (attrs & FunctionAttribute.nothrow_) 2436 result ~= " nothrow"; 2437 static if (attrs & FunctionAttribute.property) 2438 result ~= " @property"; 2439 static if (attrs & FunctionAttribute.trusted) 2440 result ~= " @trusted"; 2441 static if (attrs & FunctionAttribute.safe) 2442 result ~= " @safe"; 2443 static if (attrs & FunctionAttribute.nogc) 2444 result ~= " @nogc"; 2445 static if (attrs & FunctionAttribute.system) 2446 result ~= " @system"; 2447 static if (attrs & FunctionAttribute.const_) 2448 result ~= " const"; 2449 static if (attrs & FunctionAttribute.immutable_) 2450 result ~= " immutable"; 2451 static if (attrs & FunctionAttribute.inout_) 2452 result ~= " inout"; 2453 static if (attrs & FunctionAttribute.shared_) 2454 result ~= " shared"; 2455 static if (attrs & FunctionAttribute.return_) 2456 result ~= " return"; 2457 static if (attrs & FunctionAttribute.live) 2458 result ~= " @live"; 2459 2460 result ~= " SetFunctionAttributes;"; 2461 return result; 2462 }()); 2463 } 2464 2465 /// Ditto 2466 template SetFunctionAttributes(T, string linkage, uint attrs) 2467 if (is(T == function)) 2468 { 2469 // To avoid a lot of syntactic headaches, we just use the above version to 2470 // operate on the corresponding function pointer type and then remove the 2471 // indirection again. 2472 alias SetFunctionAttributes = FunctionTypeOf!(SetFunctionAttributes!(T*, linkage, attrs)); 2473 } 2474 2475 /// 2476 @safe unittest 2477 { 2478 alias ExternC(T) = SetFunctionAttributes!(T, "C", functionAttributes!T); 2479 2480 auto assumePure(T)(T t) 2481 if (isFunctionPointer!T || isDelegate!T) 2482 { 2483 enum attrs = functionAttributes!T | FunctionAttribute.pure_; 2484 return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; 2485 } 2486 2487 int f() 2488 { 2489 import core.thread : getpid; 2490 return getpid(); 2491 } 2492 2493 int g() pure @trusted 2494 { 2495 auto pureF = assumePure(&f); 2496 return pureF(); 2497 } 2498 assert(g() > 0); 2499 } 2500 2501 version (StdUnittest) 2502 { 2503 private: 2504 // Some function types to test. 2505 int sc(scope int, ref int, out int, lazy int, int); 2506 extern(System) int novar(); 2507 extern(C) int cstyle(int, ...); 2508 extern(D) int dstyle(...); 2509 extern(D) int typesafe(int[]...); 2510 } 2511 @safe unittest 2512 { 2513 import std.algorithm.iteration : reduce; 2514 2515 alias FA = FunctionAttribute; 2516 static foreach (BaseT; AliasSeq!(typeof(&sc), typeof(&novar), typeof(&cstyle), 2517 typeof(&dstyle), typeof(&typesafe))) 2518 { 2519 static foreach (T; AliasSeq!(BaseT, FunctionTypeOf!BaseT)) 2520 {{ 2521 enum linkage = functionLinkage!T; 2522 enum attrs = functionAttributes!T; 2523 2524 static assert(is(SetFunctionAttributes!(T, linkage, attrs) == T), 2525 "Identity check failed for: " ~ T.stringof); 2526 2527 // Check that all linkage types work (D-style variadics require D linkage). 2528 static if (variadicFunctionStyle!T != Variadic.d) 2529 { 2530 static foreach (newLinkage; AliasSeq!("D", "C", "Windows", "C++")) 2531 {{ 2532 alias New = SetFunctionAttributes!(T, newLinkage, attrs); 2533 static assert(functionLinkage!New == newLinkage, 2534 "Linkage test failed for: " ~ T.stringof ~ ", " ~ newLinkage ~ 2535 " (got " ~ New.stringof ~ ")"); 2536 }} 2537 } 2538 2539 // Add @safe. 2540 alias T1 = SetFunctionAttributes!(T, functionLinkage!T, FA.safe); 2541 static assert(functionAttributes!T1 == FA.safe); 2542 2543 // Add all known attributes, excluding conflicting ones. 2544 enum allAttrs = reduce!"a | b"([EnumMembers!FA]) 2545 & ~FA.safe & ~FA.property & ~FA.const_ & ~FA.immutable_ & ~FA.inout_ 2546 & ~FA.shared_ & ~FA.system & ~FA.return_ & ~FA.scope_; 2547 2548 alias T2 = SetFunctionAttributes!(T1, functionLinkage!T, allAttrs); 2549 static assert(functionAttributes!T2 == allAttrs); 2550 2551 // Strip all attributes again. 2552 alias T3 = SetFunctionAttributes!(T2, functionLinkage!T, FA.none); 2553 static assert(is(T3 == T)); 2554 }} 2555 } 2556 } 2557 2558 2559 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 2560 // Aggregate Types 2561 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 2562 2563 /** 2564 Determines whether `T` is a class nested inside another class 2565 and that `T.outer` is the implicit reference to the outer class 2566 (i.e. `outer` has not been used as a field or method name) 2567 2568 Params: 2569 T = type to test 2570 2571 Returns: 2572 `true` if `T` is a class nested inside another, with the conditions described above; 2573 `false` otherwise 2574 */ 2575 template isInnerClass(T) 2576 if (is(T == class)) 2577 { 2578 static if (is(typeof(T.outer))) 2579 { 2580 bool hasOuterMember(string[] members...) 2581 { 2582 foreach (m; members) 2583 { 2584 if (m == "outer") 2585 return true; 2586 } 2587 return false; 2588 } 2589 enum isInnerClass = __traits(isSame, typeof(T.outer), __traits(parent, T)) && 2590 !hasOuterMember(__traits(allMembers, T)); 2591 } 2592 else 2593 enum isInnerClass = false; 2594 } 2595 2596 /// 2597 @safe unittest 2598 { 2599 class C 2600 { 2601 int outer; 2602 } 2603 static assert(!isInnerClass!C); 2604 2605 class Outer1 2606 { 2607 class Inner1 { } 2608 class Inner2 2609 { 2610 int outer; 2611 } 2612 } 2613 static assert(isInnerClass!(Outer1.Inner1)); 2614 static assert(!isInnerClass!(Outer1.Inner2)); 2615 2616 static class Outer2 2617 { 2618 static class Inner 2619 { 2620 int outer; 2621 } 2622 } 2623 static assert(!isInnerClass!(Outer2.Inner)); 2624 } 2625 2626 /** 2627 Determines whether `T` has its own context pointer. 2628 `T` must be either `class`, `struct`, or `union`. 2629 */ 2630 template isNested(T) 2631 if (is(T == class) || is(T == struct) || is(T == union)) 2632 { 2633 enum isNested = __traits(isNested, T); 2634 } 2635 2636 /// 2637 @safe unittest 2638 { 2639 static struct S { } 2640 static assert(!isNested!S); 2641 2642 int i; 2643 struct NestedStruct { void f() { ++i; } } 2644 static assert(isNested!NestedStruct); 2645 } 2646 2647 /** 2648 Determines whether `T` or any of its representation types 2649 have a context pointer. 2650 */ 2651 template hasNested(T) 2652 { 2653 import std.meta : Filter; 2654 2655 static if (isStaticArray!T && T.length) 2656 enum hasNested = hasNested!(typeof(T.init[0])); 2657 else static if (is(T == class) || is(T == struct) || is(T == union)) 2658 { 2659 // prevent infinite recursion for class with member of same type 2660 enum notSame(U) = !is(immutable T == immutable U); 2661 enum hasNested = isNested!T || 2662 anySatisfy!(.hasNested, Filter!(notSame, Fields!T)); 2663 } 2664 else 2665 enum hasNested = false; 2666 } 2667 2668 /// 2669 @safe unittest 2670 { 2671 static struct S { } 2672 2673 int i; 2674 struct NS { void f() { ++i; } } 2675 2676 static assert(!hasNested!(S[2])); 2677 static assert(hasNested!(NS[2])); 2678 } 2679 2680 @safe unittest 2681 { 2682 static assert(!__traits(compiles, isNested!int)); 2683 static assert(!hasNested!int); 2684 2685 static struct StaticStruct { } 2686 static assert(!isNested!StaticStruct); 2687 static assert(!hasNested!StaticStruct); 2688 2689 int i; 2690 struct NestedStruct { void f() { ++i; } } 2691 static assert( isNested!NestedStruct); 2692 static assert( hasNested!NestedStruct); 2693 static assert( isNested!(immutable NestedStruct)); 2694 static assert( hasNested!(immutable NestedStruct)); 2695 2696 static assert(!__traits(compiles, isNested!(NestedStruct[1]))); 2697 static assert( hasNested!(NestedStruct[1])); 2698 static assert(!hasNested!(NestedStruct[0])); 2699 2700 struct S1 { NestedStruct nested; } 2701 static assert(!isNested!S1); 2702 static assert( hasNested!S1); 2703 2704 static struct S2 { NestedStruct nested; } 2705 static assert(!isNested!S2); 2706 static assert( hasNested!S2); 2707 2708 static struct S3 { NestedStruct[0] nested; } 2709 static assert(!isNested!S3); 2710 static assert(!hasNested!S3); 2711 2712 static union U { NestedStruct nested; } 2713 static assert(!isNested!U); 2714 static assert( hasNested!U); 2715 2716 static class StaticClass { } 2717 static assert(!isNested!StaticClass); 2718 static assert(!hasNested!StaticClass); 2719 2720 class NestedClass { void f() { ++i; } } 2721 static assert( isNested!NestedClass); 2722 static assert( hasNested!NestedClass); 2723 static assert( isNested!(immutable NestedClass)); 2724 static assert( hasNested!(immutable NestedClass)); 2725 2726 static assert(!__traits(compiles, isNested!(NestedClass[1]))); 2727 static assert( hasNested!(NestedClass[1])); 2728 static assert(!hasNested!(NestedClass[0])); 2729 2730 static class A 2731 { 2732 A a; 2733 } 2734 static assert(!hasNested!A); 2735 } 2736 2737 2738 /*** 2739 * Get as a tuple the types of the fields of a struct, class, or union. 2740 * This consists of the fields that take up memory space, 2741 * excluding the hidden fields like the virtual function 2742 * table pointer or a context pointer for nested types. 2743 * If `T` isn't a struct, class, or union returns a tuple 2744 * with one element `T`. 2745 */ 2746 template Fields(T) 2747 { 2748 static if (is(T == struct) || is(T == union)) 2749 alias Fields = typeof(T.tupleof[0 .. $ - isNested!T]); 2750 else static if (is(T == class)) 2751 alias Fields = typeof(T.tupleof); 2752 else 2753 alias Fields = AliasSeq!T; 2754 } 2755 2756 /// 2757 @safe unittest 2758 { 2759 import std.meta : AliasSeq; 2760 struct S { int x; float y; } 2761 static assert(is(Fields!S == AliasSeq!(int, float))); 2762 } 2763 2764 /** 2765 * Alternate name for $(LREF Fields), kept for legacy compatibility. 2766 */ 2767 alias FieldTypeTuple = Fields; 2768 2769 @safe unittest 2770 { 2771 static assert(is(FieldTypeTuple!int == AliasSeq!int)); 2772 2773 static struct StaticStruct1 { } 2774 static assert(is(FieldTypeTuple!StaticStruct1 == AliasSeq!())); 2775 2776 static struct StaticStruct2 { int a, b; } 2777 static assert(is(FieldTypeTuple!StaticStruct2 == AliasSeq!(int, int))); 2778 2779 int i; 2780 2781 struct NestedStruct1 { void f() { ++i; } } 2782 static assert(is(FieldTypeTuple!NestedStruct1 == AliasSeq!())); 2783 2784 struct NestedStruct2 { int a; void f() { ++i; } } 2785 static assert(is(FieldTypeTuple!NestedStruct2 == AliasSeq!int)); 2786 2787 class NestedClass { int a; void f() { ++i; } } 2788 static assert(is(FieldTypeTuple!NestedClass == AliasSeq!int)); 2789 } 2790 2791 2792 //Required for FieldNameTuple 2793 private enum NameOf(alias T) = T.stringof; 2794 2795 /** 2796 * Get as an expression tuple the names of the fields of a struct, class, or 2797 * union. This consists of the fields that take up memory space, excluding the 2798 * hidden fields like the virtual function table pointer or a context pointer 2799 * for nested types. 2800 * Inherited fields (for classes) are not included. 2801 * If `T` isn't a struct, class, or union, an 2802 * expression tuple with an empty string is returned. 2803 */ 2804 template FieldNameTuple(T) 2805 { 2806 import std.meta : staticMap; 2807 static if (is(T == struct) || is(T == union)) 2808 alias FieldNameTuple = staticMap!(NameOf, T.tupleof[0 .. $ - isNested!T]); 2809 else static if (is(T == class)) 2810 alias FieldNameTuple = staticMap!(NameOf, T.tupleof); 2811 else 2812 alias FieldNameTuple = AliasSeq!""; 2813 } 2814 2815 /// 2816 @safe unittest 2817 { 2818 import std.meta : AliasSeq; 2819 struct S { int x; float y; } 2820 static assert(FieldNameTuple!S == AliasSeq!("x", "y")); 2821 static assert(FieldNameTuple!int == AliasSeq!""); 2822 } 2823 2824 @safe unittest 2825 { 2826 static assert(FieldNameTuple!int == AliasSeq!""); 2827 2828 static struct StaticStruct1 { } 2829 static assert(is(FieldNameTuple!StaticStruct1 == AliasSeq!())); 2830 2831 static struct StaticStruct2 { int a, b; } 2832 static assert(FieldNameTuple!StaticStruct2 == AliasSeq!("a", "b")); 2833 2834 static class StaticClass1 { } 2835 static assert(is(FieldNameTuple!StaticClass1 == AliasSeq!())); 2836 2837 static class StaticClass2 : StaticClass1 { int a, b; } 2838 static assert(FieldNameTuple!StaticClass2 == AliasSeq!("a", "b")); 2839 2840 static class StaticClass3 : StaticClass2 { int c; } 2841 static assert(FieldNameTuple!StaticClass3 == AliasSeq!("c")); 2842 2843 int i; 2844 2845 struct NestedStruct1 { void f() { ++i; } } 2846 static assert(is(FieldNameTuple!NestedStruct1 == AliasSeq!())); 2847 2848 struct NestedStruct2 { int a; void f() { ++i; } } 2849 static assert(FieldNameTuple!NestedStruct2 == AliasSeq!"a"); 2850 2851 class NestedClass { int a; void f() { ++i; } } 2852 static assert(FieldNameTuple!NestedClass == AliasSeq!"a"); 2853 } 2854 2855 2856 /*** 2857 Get the primitive types of the fields of a struct or class, in 2858 topological order. 2859 */ 2860 template RepresentationTypeTuple(T) 2861 { 2862 static if (is(T == struct) || is(T == union) || is(T == class)) 2863 { 2864 alias RepresentationTypeTuple = staticMapMeta!(RepresentationTypeTupleImpl, FieldTypeTuple!T); 2865 } 2866 else 2867 { 2868 alias RepresentationTypeTuple = RepresentationTypeTupleImpl!T; 2869 } 2870 } 2871 2872 /// 2873 @safe unittest 2874 { 2875 struct S1 { int a; float b; } 2876 struct S2 { char[] a; union { S1 b; S1 * c; } } 2877 alias R = RepresentationTypeTuple!S2; 2878 assert(R.length == 4 2879 && is(R[0] == char[]) && is(R[1] == int) 2880 && is(R[2] == float) && is(R[3] == S1*)); 2881 } 2882 2883 @safe unittest 2884 { 2885 alias S1 = RepresentationTypeTuple!int; 2886 static assert(is(S1 == AliasSeq!int)); 2887 2888 struct S2 { int a; } 2889 struct S3 { int a; char b; } 2890 struct S4 { S1 a; int b; S3 c; } 2891 static assert(is(RepresentationTypeTuple!S2 == AliasSeq!int)); 2892 static assert(is(RepresentationTypeTuple!S3 == AliasSeq!(int, char))); 2893 static assert(is(RepresentationTypeTuple!S4 == AliasSeq!(int, int, int, char))); 2894 2895 struct S11 { int a; float b; } 2896 struct S21 { char[] a; union { S11 b; S11 * c; } } 2897 alias R = RepresentationTypeTuple!S21; 2898 assert(R.length == 4 2899 && is(R[0] == char[]) && is(R[1] == int) 2900 && is(R[2] == float) && is(R[3] == S11*)); 2901 2902 class C { int a; float b; } 2903 alias R1 = RepresentationTypeTuple!C; 2904 static assert(R1.length == 2 && is(R1[0] == int) && is(R1[1] == float)); 2905 2906 /* https://issues.dlang.org/show_bug.cgi?id=6642 */ 2907 import std.typecons : Rebindable; 2908 2909 struct S5 { int a; Rebindable!(immutable Object) b; } 2910 alias R2 = RepresentationTypeTuple!S5; 2911 static assert(R2.length == 2 && is(R2[0] == int) && is(R2[1] == immutable(Object))); 2912 } 2913 2914 @safe unittest 2915 { 2916 struct VeryLargeType 2917 { 2918 import std.format : format; 2919 import std.range : iota; 2920 2921 static foreach (i; 500.iota) 2922 { 2923 mixin(format!"int v%s;"(i)); 2924 } 2925 } 2926 2927 alias BigList = RepresentationTypeTuple!VeryLargeType; 2928 } 2929 2930 private template RepresentationTypeTupleImpl(T) 2931 { 2932 import std.typecons : Rebindable; 2933 2934 static if (is(T R: Rebindable!R)) 2935 { 2936 alias RepresentationTypeTupleImpl 2937 = staticMapMeta!(.RepresentationTypeTupleImpl, RepresentationTypeTupleImpl!R); 2938 } 2939 else static if (is(T == struct) || is(T == union)) 2940 { 2941 // @@@BUG@@@ this should work 2942 //alias .RepresentationTypes!(T[0].tupleof) 2943 // RepresentationTypes; 2944 alias RepresentationTypeTupleImpl 2945 = staticMapMeta!(.RepresentationTypeTupleImpl, FieldTypeTuple!(T)); 2946 } 2947 else 2948 { 2949 alias RepresentationTypeTupleImpl 2950 = AliasSeq!T; 2951 } 2952 } 2953 2954 /* 2955 Statically evaluates to `true` if and only if `T`'s 2956 representation contains at least one field of pointer or array type. 2957 Members of class types are not considered raw pointers. Pointers to 2958 immutable objects are not considered raw aliasing. 2959 */ 2960 private template hasRawAliasing(T) 2961 { 2962 enum hasRawAliasing = anySatisfy!(hasRawAliasingImpl, RepresentationTypeTuple!T); 2963 } 2964 2965 // 2966 @safe unittest 2967 { 2968 // simple types 2969 static assert(!hasRawAliasing!int); 2970 static assert( hasRawAliasing!(char*)); 2971 // references aren't raw pointers 2972 static assert(!hasRawAliasing!Object); 2973 // built-in arrays do contain raw pointers 2974 static assert( hasRawAliasing!(int[])); 2975 // aggregate of simple types 2976 struct S1 { int a; double b; } 2977 static assert(!hasRawAliasing!S1); 2978 // indirect aggregation 2979 struct S2 { S1 a; double b; } 2980 static assert(!hasRawAliasing!S2); 2981 } 2982 2983 // https://issues.dlang.org/show_bug.cgi?id=19228 2984 @safe unittest 2985 { 2986 static struct C 2987 { 2988 int*[1] a; 2989 } 2990 static assert(hasRawAliasing!C); 2991 } 2992 2993 @safe unittest 2994 { 2995 // struct with a pointer member 2996 struct S3 { int a; double * b; } 2997 static assert( hasRawAliasing!S3); 2998 // struct with an indirect pointer member 2999 struct S4 { S3 a; double b; } 3000 static assert( hasRawAliasing!S4); 3001 struct S5 { int a; Object z; int c; } 3002 static assert( hasRawAliasing!S3); 3003 static assert( hasRawAliasing!S4); 3004 static assert(!hasRawAliasing!S5); 3005 3006 union S6 { int a; int b; } 3007 union S7 { int a; int * b; } 3008 static assert(!hasRawAliasing!S6); 3009 static assert( hasRawAliasing!S7); 3010 3011 static assert(!hasRawAliasing!(void delegate())); 3012 static assert(!hasRawAliasing!(void delegate() const)); 3013 static assert(!hasRawAliasing!(void delegate() immutable)); 3014 static assert(!hasRawAliasing!(void delegate() shared)); 3015 static assert(!hasRawAliasing!(void delegate() shared const)); 3016 static assert(!hasRawAliasing!(const(void delegate()))); 3017 static assert(!hasRawAliasing!(immutable(void delegate()))); 3018 3019 struct S8 { void delegate() a; int b; Object c; } 3020 class S12 { typeof(S8.tupleof) a; } 3021 class S13 { typeof(S8.tupleof) a; int* b; } 3022 static assert(!hasRawAliasing!S8); 3023 static assert(!hasRawAliasing!S12); 3024 static assert( hasRawAliasing!S13); 3025 3026 enum S9 { a } 3027 static assert(!hasRawAliasing!S9); 3028 3029 // indirect members 3030 struct S10 { S7 a; int b; } 3031 struct S11 { S6 a; int b; } 3032 static assert( hasRawAliasing!S10); 3033 static assert(!hasRawAliasing!S11); 3034 3035 static assert( hasRawAliasing!(int[string])); 3036 static assert(!hasRawAliasing!(immutable(int[string]))); 3037 } 3038 3039 private template hasRawAliasingImpl(T) 3040 { 3041 static if (is(T foo : U*, U) && !isFunctionPointer!T) 3042 enum hasRawAliasingImpl = !is(U == immutable); 3043 else static if (is(T foo : U[N], U, size_t N)) 3044 // separate static ifs to avoid forward reference 3045 static if (is(U == class) || is(U == interface)) 3046 enum hasRawAliasingImpl = false; 3047 else 3048 enum hasRawAliasingImpl = hasRawAliasingImpl!U; 3049 else static if (is(T foo : U[], U) && !isStaticArray!(T)) 3050 enum hasRawAliasingImpl = !is(U == immutable); 3051 else static if (isAssociativeArray!(T)) 3052 enum hasRawAliasingImpl = !is(T == immutable); 3053 else 3054 enum hasRawAliasingImpl = false; 3055 } 3056 3057 /* 3058 Statically evaluates to `true` if and only if `T`'s 3059 representation contains at least one non-shared field of pointer or 3060 array type. Members of class types are not considered raw pointers. 3061 Pointers to immutable objects are not considered raw aliasing. 3062 */ 3063 private template hasRawUnsharedAliasing(T) 3064 { 3065 enum hasRawUnsharedAliasing = anySatisfy!(hasRawUnsharedAliasingImpl, RepresentationTypeTuple!T); 3066 } 3067 3068 // 3069 @safe unittest 3070 { 3071 // simple types 3072 static assert(!hasRawUnsharedAliasing!int); 3073 static assert( hasRawUnsharedAliasing!(char*)); 3074 static assert(!hasRawUnsharedAliasing!(shared char*)); 3075 // references aren't raw pointers 3076 static assert(!hasRawUnsharedAliasing!Object); 3077 // built-in arrays do contain raw pointers 3078 static assert( hasRawUnsharedAliasing!(int[])); 3079 static assert(!hasRawUnsharedAliasing!(shared int[])); 3080 // aggregate of simple types 3081 struct S1 { int a; double b; } 3082 static assert(!hasRawUnsharedAliasing!S1); 3083 // indirect aggregation 3084 struct S2 { S1 a; double b; } 3085 static assert(!hasRawUnsharedAliasing!S2); 3086 // struct with a pointer member 3087 struct S3 { int a; double * b; } 3088 static assert( hasRawUnsharedAliasing!S3); 3089 struct S4 { int a; shared double * b; } 3090 static assert(!hasRawUnsharedAliasing!S4); 3091 } 3092 3093 @safe unittest 3094 { 3095 // struct with a pointer member 3096 struct S3 { int a; double * b; } 3097 static assert( hasRawUnsharedAliasing!S3); 3098 struct S4 { int a; shared double * b; } 3099 static assert(!hasRawUnsharedAliasing!S4); 3100 // struct with an indirect pointer member 3101 struct S5 { S3 a; double b; } 3102 static assert( hasRawUnsharedAliasing!S5); 3103 struct S6 { S4 a; double b; } 3104 static assert(!hasRawUnsharedAliasing!S6); 3105 struct S7 { int a; Object z; int c; } 3106 static assert( hasRawUnsharedAliasing!S5); 3107 static assert(!hasRawUnsharedAliasing!S6); 3108 static assert(!hasRawUnsharedAliasing!S7); 3109 3110 union S8 { int a; int b; } 3111 union S9 { int a; int* b; } 3112 union S10 { int a; shared int* b; } 3113 static assert(!hasRawUnsharedAliasing!S8); 3114 static assert( hasRawUnsharedAliasing!S9); 3115 static assert(!hasRawUnsharedAliasing!S10); 3116 3117 static assert(!hasRawUnsharedAliasing!(void delegate())); 3118 static assert(!hasRawUnsharedAliasing!(void delegate() const)); 3119 static assert(!hasRawUnsharedAliasing!(void delegate() immutable)); 3120 static assert(!hasRawUnsharedAliasing!(void delegate() shared)); 3121 static assert(!hasRawUnsharedAliasing!(void delegate() shared const)); 3122 static assert(!hasRawUnsharedAliasing!(const(void delegate()))); 3123 static assert(!hasRawUnsharedAliasing!(const(void delegate() const))); 3124 static assert(!hasRawUnsharedAliasing!(const(void delegate() immutable))); 3125 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared))); 3126 static assert(!hasRawUnsharedAliasing!(const(void delegate() shared const))); 3127 static assert(!hasRawUnsharedAliasing!(immutable(void delegate()))); 3128 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() const))); 3129 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() immutable))); 3130 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared))); 3131 static assert(!hasRawUnsharedAliasing!(immutable(void delegate() shared const))); 3132 static assert(!hasRawUnsharedAliasing!(shared(void delegate()))); 3133 static assert(!hasRawUnsharedAliasing!(shared(void delegate() const))); 3134 static assert(!hasRawUnsharedAliasing!(shared(void delegate() immutable))); 3135 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared))); 3136 static assert(!hasRawUnsharedAliasing!(shared(void delegate() shared const))); 3137 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate())))); 3138 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() const)))); 3139 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() immutable)))); 3140 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared)))); 3141 static assert(!hasRawUnsharedAliasing!(shared(const(void delegate() shared const)))); 3142 static assert(!hasRawUnsharedAliasing!(void function())); 3143 3144 enum S13 { a } 3145 static assert(!hasRawUnsharedAliasing!S13); 3146 3147 // indirect members 3148 struct S14 { S9 a; int b; } 3149 struct S15 { S10 a; int b; } 3150 struct S16 { S6 a; int b; } 3151 static assert( hasRawUnsharedAliasing!S14); 3152 static assert(!hasRawUnsharedAliasing!S15); 3153 static assert(!hasRawUnsharedAliasing!S16); 3154 3155 static assert( hasRawUnsharedAliasing!(int[string])); 3156 static assert(!hasRawUnsharedAliasing!(shared(int[string]))); 3157 static assert(!hasRawUnsharedAliasing!(immutable(int[string]))); 3158 3159 struct S17 3160 { 3161 void delegate() shared a; 3162 void delegate() immutable b; 3163 void delegate() shared const c; 3164 shared(void delegate()) d; 3165 shared(void delegate() shared) e; 3166 shared(void delegate() immutable) f; 3167 shared(void delegate() shared const) g; 3168 immutable(void delegate()) h; 3169 immutable(void delegate() shared) i; 3170 immutable(void delegate() immutable) j; 3171 immutable(void delegate() shared const) k; 3172 shared(const(void delegate())) l; 3173 shared(const(void delegate() shared)) m; 3174 shared(const(void delegate() immutable)) n; 3175 shared(const(void delegate() shared const)) o; 3176 } 3177 struct S18 { typeof(S17.tupleof) a; void delegate() p; } 3178 struct S19 { typeof(S17.tupleof) a; Object p; } 3179 struct S20 { typeof(S17.tupleof) a; int* p; } 3180 class S21 { typeof(S17.tupleof) a; } 3181 class S22 { typeof(S17.tupleof) a; void delegate() p; } 3182 class S23 { typeof(S17.tupleof) a; Object p; } 3183 class S24 { typeof(S17.tupleof) a; int* p; } 3184 static assert(!hasRawUnsharedAliasing!S17); 3185 static assert(!hasRawUnsharedAliasing!(immutable(S17))); 3186 static assert(!hasRawUnsharedAliasing!(shared(S17))); 3187 static assert(!hasRawUnsharedAliasing!S18); 3188 static assert(!hasRawUnsharedAliasing!(immutable(S18))); 3189 static assert(!hasRawUnsharedAliasing!(shared(S18))); 3190 static assert(!hasRawUnsharedAliasing!S19); 3191 static assert(!hasRawUnsharedAliasing!(immutable(S19))); 3192 static assert(!hasRawUnsharedAliasing!(shared(S19))); 3193 static assert( hasRawUnsharedAliasing!S20); 3194 static assert(!hasRawUnsharedAliasing!(immutable(S20))); 3195 static assert(!hasRawUnsharedAliasing!(shared(S20))); 3196 static assert(!hasRawUnsharedAliasing!S21); 3197 static assert(!hasRawUnsharedAliasing!(immutable(S21))); 3198 static assert(!hasRawUnsharedAliasing!(shared(S21))); 3199 static assert(!hasRawUnsharedAliasing!S22); 3200 static assert(!hasRawUnsharedAliasing!(immutable(S22))); 3201 static assert(!hasRawUnsharedAliasing!(shared(S22))); 3202 static assert(!hasRawUnsharedAliasing!S23); 3203 static assert(!hasRawUnsharedAliasing!(immutable(S23))); 3204 static assert(!hasRawUnsharedAliasing!(shared(S23))); 3205 static assert( hasRawUnsharedAliasing!S24); 3206 static assert(!hasRawUnsharedAliasing!(immutable(S24))); 3207 static assert(!hasRawUnsharedAliasing!(shared(S24))); 3208 struct S25 {} 3209 class S26 {} 3210 interface S27 {} 3211 union S28 {} 3212 static assert(!hasRawUnsharedAliasing!S25); 3213 static assert(!hasRawUnsharedAliasing!S26); 3214 static assert(!hasRawUnsharedAliasing!S27); 3215 static assert(!hasRawUnsharedAliasing!S28); 3216 } 3217 3218 private template hasRawUnsharedAliasingImpl(T) 3219 { 3220 static if (is(T foo : U*, U) && !isFunctionPointer!T) 3221 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared); 3222 else static if (is(T foo : U[], U) && !isStaticArray!T) 3223 enum hasRawUnsharedAliasingImpl = !is(U == immutable) && !is(U == shared); 3224 else static if (isAssociativeArray!T) 3225 enum hasRawUnsharedAliasingImpl = !is(T == immutable) && !is(T == shared); 3226 else 3227 enum hasRawUnsharedAliasingImpl = false; 3228 } 3229 3230 /* 3231 Statically evaluates to `true` if and only if `T`'s 3232 representation includes at least one non-immutable object reference. 3233 */ 3234 3235 private template hasObjects(T) 3236 { 3237 static if (is(T == struct)) 3238 { 3239 enum hasObjects = anySatisfy!(.hasObjects, RepresentationTypeTuple!T); 3240 } 3241 else 3242 { 3243 enum hasObjects = (is(T == class) || is(T == interface)) && !is(T == immutable); 3244 } 3245 } 3246 3247 /* 3248 Statically evaluates to `true` if and only if `T`'s 3249 representation includes at least one non-immutable non-shared object 3250 reference. 3251 */ 3252 private template hasUnsharedObjects(T) 3253 { 3254 static if (is(T == struct)) 3255 { 3256 enum hasUnsharedObjects = anySatisfy!(.hasUnsharedObjects, RepresentationTypeTuple!T); 3257 } 3258 else 3259 { 3260 enum hasUnsharedObjects = (is(T == class) || is(T == interface)) && 3261 !is(T == immutable) && !is(T == shared); 3262 } 3263 } 3264 3265 /** 3266 Returns `true` if and only if `T`'s representation includes at 3267 least one of the following: $(OL $(LI a raw pointer `U*` and `U` 3268 is not immutable;) $(LI an array `U[]` and `U` is not 3269 immutable;) $(LI a reference to a class or interface type `C` and `C` is 3270 not immutable.) $(LI an associative array that is not immutable.) 3271 $(LI a delegate.)) 3272 */ 3273 template hasAliasing(T...) 3274 { 3275 enum hasAliasing = anySatisfy!(hasAliasingImpl, T); 3276 } 3277 3278 /// 3279 @safe unittest 3280 { 3281 struct S1 { int a; Object b; } 3282 struct S2 { string a; } 3283 struct S3 { int a; immutable Object b; } 3284 struct S4 { float[3] vals; } 3285 static assert( hasAliasing!S1); 3286 static assert(!hasAliasing!S2); 3287 static assert(!hasAliasing!S3); 3288 static assert(!hasAliasing!S4); 3289 } 3290 3291 @safe unittest 3292 { 3293 static assert( hasAliasing!(uint[uint])); 3294 static assert(!hasAliasing!(immutable(uint[uint]))); 3295 static assert( hasAliasing!(void delegate())); 3296 static assert( hasAliasing!(void delegate() const)); 3297 static assert(!hasAliasing!(void delegate() immutable)); 3298 static assert( hasAliasing!(void delegate() shared)); 3299 static assert( hasAliasing!(void delegate() shared const)); 3300 static assert( hasAliasing!(const(void delegate()))); 3301 static assert( hasAliasing!(const(void delegate() const))); 3302 static assert(!hasAliasing!(const(void delegate() immutable))); 3303 static assert( hasAliasing!(const(void delegate() shared))); 3304 static assert( hasAliasing!(const(void delegate() shared const))); 3305 static assert(!hasAliasing!(immutable(void delegate()))); 3306 static assert(!hasAliasing!(immutable(void delegate() const))); 3307 static assert(!hasAliasing!(immutable(void delegate() immutable))); 3308 static assert(!hasAliasing!(immutable(void delegate() shared))); 3309 static assert(!hasAliasing!(immutable(void delegate() shared const))); 3310 static assert( hasAliasing!(shared(const(void delegate())))); 3311 static assert( hasAliasing!(shared(const(void delegate() const)))); 3312 static assert(!hasAliasing!(shared(const(void delegate() immutable)))); 3313 static assert( hasAliasing!(shared(const(void delegate() shared)))); 3314 static assert( hasAliasing!(shared(const(void delegate() shared const)))); 3315 static assert(!hasAliasing!(void function())); 3316 3317 interface I; 3318 static assert( hasAliasing!I); 3319 3320 import std.typecons : Rebindable; 3321 static assert( hasAliasing!(Rebindable!(const Object))); 3322 static assert(!hasAliasing!(Rebindable!(immutable Object))); 3323 static assert( hasAliasing!(Rebindable!(shared Object))); 3324 static assert( hasAliasing!(Rebindable!Object)); 3325 3326 struct S5 3327 { 3328 void delegate() immutable b; 3329 shared(void delegate() immutable) f; 3330 immutable(void delegate() immutable) j; 3331 shared(const(void delegate() immutable)) n; 3332 } 3333 struct S6 { typeof(S5.tupleof) a; void delegate() p; } 3334 static assert(!hasAliasing!S5); 3335 static assert( hasAliasing!S6); 3336 3337 struct S7 { void delegate() a; int b; Object c; } 3338 class S8 { int a; int b; } 3339 class S9 { typeof(S8.tupleof) a; } 3340 class S10 { typeof(S8.tupleof) a; int* b; } 3341 static assert( hasAliasing!S7); 3342 static assert( hasAliasing!S8); 3343 static assert( hasAliasing!S9); 3344 static assert( hasAliasing!S10); 3345 struct S11 {} 3346 class S12 {} 3347 interface S13 {} 3348 union S14 {} 3349 static assert(!hasAliasing!S11); 3350 static assert( hasAliasing!S12); 3351 static assert( hasAliasing!S13); 3352 static assert(!hasAliasing!S14); 3353 3354 class S15 { S15[1] a; } 3355 static assert( hasAliasing!S15); 3356 static assert(!hasAliasing!(immutable(S15))); 3357 } 3358 3359 private template hasAliasingImpl(T) 3360 { 3361 import std.typecons : Rebindable; 3362 3363 static if (is(T : Rebindable!R, R)) 3364 { 3365 enum hasAliasingImpl = hasAliasingImpl!R; 3366 } 3367 else 3368 { 3369 template isAliasingDelegate(T) 3370 { 3371 enum isAliasingDelegate = isDelegate!T 3372 && !is(T == immutable) 3373 && !is(FunctionTypeOf!T == immutable); 3374 } 3375 enum hasAliasingImpl = hasRawAliasing!T || hasObjects!T || 3376 anySatisfy!(isAliasingDelegate, T, RepresentationTypeTuple!T); 3377 } 3378 } 3379 3380 /** 3381 Returns `true` if and only if `T`'s representation includes at 3382 least one of the following: $(OL $(LI a raw pointer `U*`;) $(LI an 3383 array `U[]`;) $(LI a reference to a class type `C`.) 3384 $(LI an associative array.) $(LI a delegate.)) 3385 */ 3386 template hasIndirections(T) 3387 { 3388 static if (is(T == struct) || is(T == union)) 3389 enum hasIndirections = anySatisfy!(.hasIndirections, FieldTypeTuple!T); 3390 else static if (isStaticArray!T && is(T : E[N], E, size_t N)) 3391 enum hasIndirections = is(E == void) ? true : hasIndirections!E; 3392 else static if (isFunctionPointer!T) 3393 enum hasIndirections = false; 3394 else 3395 enum hasIndirections = isPointer!T || isDelegate!T || isDynamicArray!T || 3396 isAssociativeArray!T || is (T == class) || is(T == interface); 3397 } 3398 3399 /// 3400 @safe unittest 3401 { 3402 static assert( hasIndirections!(int[string])); 3403 static assert( hasIndirections!(void delegate())); 3404 static assert( hasIndirections!(void delegate() immutable)); 3405 static assert( hasIndirections!(immutable(void delegate()))); 3406 static assert( hasIndirections!(immutable(void delegate() immutable))); 3407 3408 static assert(!hasIndirections!(void function())); 3409 static assert( hasIndirections!(void*[1])); 3410 static assert(!hasIndirections!(byte[1])); 3411 } 3412 3413 @safe unittest 3414 { 3415 // void static array hides actual type of bits, so "may have indirections". 3416 static assert( hasIndirections!(void[1])); 3417 interface I {} 3418 struct S1 {} 3419 struct S2 { int a; } 3420 struct S3 { int a; int b; } 3421 struct S4 { int a; int* b; } 3422 struct S5 { int a; Object b; } 3423 struct S6 { int a; string b; } 3424 struct S7 { int a; immutable Object b; } 3425 struct S8 { int a; immutable I b; } 3426 struct S9 { int a; void delegate() b; } 3427 struct S10 { int a; immutable(void delegate()) b; } 3428 struct S11 { int a; void delegate() immutable b; } 3429 struct S12 { int a; immutable(void delegate() immutable) b; } 3430 class S13 {} 3431 class S14 { int a; } 3432 class S15 { int a; int b; } 3433 class S16 { int a; Object b; } 3434 class S17 { string a; } 3435 class S18 { int a; immutable Object b; } 3436 class S19 { int a; immutable(void delegate() immutable) b; } 3437 union S20 {} 3438 union S21 { int a; } 3439 union S22 { int a; int b; } 3440 union S23 { int a; Object b; } 3441 union S24 { string a; } 3442 union S25 { int a; immutable Object b; } 3443 union S26 { int a; immutable(void delegate() immutable) b; } 3444 static assert( hasIndirections!I); 3445 static assert(!hasIndirections!S1); 3446 static assert(!hasIndirections!S2); 3447 static assert(!hasIndirections!S3); 3448 static assert( hasIndirections!S4); 3449 static assert( hasIndirections!S5); 3450 static assert( hasIndirections!S6); 3451 static assert( hasIndirections!S7); 3452 static assert( hasIndirections!S8); 3453 static assert( hasIndirections!S9); 3454 static assert( hasIndirections!S10); 3455 static assert( hasIndirections!S12); 3456 static assert( hasIndirections!S13); 3457 static assert( hasIndirections!S14); 3458 static assert( hasIndirections!S15); 3459 static assert( hasIndirections!S16); 3460 static assert( hasIndirections!S17); 3461 static assert( hasIndirections!S18); 3462 static assert( hasIndirections!S19); 3463 static assert(!hasIndirections!S20); 3464 static assert(!hasIndirections!S21); 3465 static assert(!hasIndirections!S22); 3466 static assert( hasIndirections!S23); 3467 static assert( hasIndirections!S24); 3468 static assert( hasIndirections!S25); 3469 static assert( hasIndirections!S26); 3470 } 3471 3472 // https://issues.dlang.org/show_bug.cgi?id=12000 3473 @safe unittest 3474 { 3475 static struct S(T) 3476 { 3477 static assert(hasIndirections!T); 3478 } 3479 3480 static class A(T) 3481 { 3482 S!A a; 3483 } 3484 3485 A!int dummy; 3486 } 3487 3488 /** 3489 Returns `true` if and only if `T`'s representation includes at 3490 least one of the following: $(OL $(LI a raw pointer `U*` and `U` 3491 is not immutable or shared;) $(LI an array `U[]` and `U` is not 3492 immutable or shared;) $(LI a reference to a class type `C` and 3493 `C` is not immutable or shared.) $(LI an associative array that is not 3494 immutable or shared.) $(LI a delegate that is not shared.)) 3495 */ 3496 3497 template hasUnsharedAliasing(T...) 3498 { 3499 enum hasUnsharedAliasing = anySatisfy!(hasUnsharedAliasingImpl, T); 3500 } 3501 3502 /// 3503 @safe unittest 3504 { 3505 struct S1 { int a; Object b; } 3506 struct S2 { string a; } 3507 struct S3 { int a; immutable Object b; } 3508 static assert( hasUnsharedAliasing!S1); 3509 static assert(!hasUnsharedAliasing!S2); 3510 static assert(!hasUnsharedAliasing!S3); 3511 3512 struct S4 { int a; shared Object b; } 3513 struct S5 { char[] a; } 3514 struct S6 { shared char[] b; } 3515 struct S7 { float[3] vals; } 3516 static assert(!hasUnsharedAliasing!S4); 3517 static assert( hasUnsharedAliasing!S5); 3518 static assert(!hasUnsharedAliasing!S6); 3519 static assert(!hasUnsharedAliasing!S7); 3520 } 3521 3522 @safe unittest 3523 { 3524 /* https://issues.dlang.org/show_bug.cgi?id=6642 */ 3525 import std.typecons : Rebindable; 3526 struct S8 { int a; Rebindable!(immutable Object) b; } 3527 static assert(!hasUnsharedAliasing!S8); 3528 3529 static assert( hasUnsharedAliasing!(uint[uint])); 3530 3531 static assert( hasUnsharedAliasing!(void delegate())); 3532 static assert( hasUnsharedAliasing!(void delegate() const)); 3533 static assert(!hasUnsharedAliasing!(void delegate() immutable)); 3534 static assert(!hasUnsharedAliasing!(void delegate() shared)); 3535 static assert(!hasUnsharedAliasing!(void delegate() shared const)); 3536 } 3537 3538 @safe unittest 3539 { 3540 import std.typecons : Rebindable; 3541 static assert( hasUnsharedAliasing!(const(void delegate()))); 3542 static assert( hasUnsharedAliasing!(const(void delegate() const))); 3543 static assert(!hasUnsharedAliasing!(const(void delegate() immutable))); 3544 static assert(!hasUnsharedAliasing!(const(void delegate() shared))); 3545 static assert(!hasUnsharedAliasing!(const(void delegate() shared const))); 3546 static assert(!hasUnsharedAliasing!(immutable(void delegate()))); 3547 static assert(!hasUnsharedAliasing!(immutable(void delegate() const))); 3548 static assert(!hasUnsharedAliasing!(immutable(void delegate() immutable))); 3549 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared))); 3550 static assert(!hasUnsharedAliasing!(immutable(void delegate() shared const))); 3551 static assert(!hasUnsharedAliasing!(shared(void delegate()))); 3552 static assert(!hasUnsharedAliasing!(shared(void delegate() const))); 3553 static assert(!hasUnsharedAliasing!(shared(void delegate() immutable))); 3554 static assert(!hasUnsharedAliasing!(shared(void delegate() shared))); 3555 static assert(!hasUnsharedAliasing!(shared(void delegate() shared const))); 3556 static assert(!hasUnsharedAliasing!(shared(const(void delegate())))); 3557 static assert(!hasUnsharedAliasing!(shared(const(void delegate() const)))); 3558 static assert(!hasUnsharedAliasing!(shared(const(void delegate() immutable)))); 3559 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared)))); 3560 static assert(!hasUnsharedAliasing!(shared(const(void delegate() shared const)))); 3561 static assert(!hasUnsharedAliasing!(void function())); 3562 3563 interface I {} 3564 static assert(hasUnsharedAliasing!I); 3565 3566 static assert( hasUnsharedAliasing!(Rebindable!(const Object))); 3567 static assert(!hasUnsharedAliasing!(Rebindable!(immutable Object))); 3568 static assert(!hasUnsharedAliasing!(Rebindable!(shared Object))); 3569 static assert( hasUnsharedAliasing!(Rebindable!Object)); 3570 3571 /* https://issues.dlang.org/show_bug.cgi?id=6979 */ 3572 static assert(!hasUnsharedAliasing!(int, shared(int)*)); 3573 static assert( hasUnsharedAliasing!(int, int*)); 3574 static assert( hasUnsharedAliasing!(int, const(int)[])); 3575 static assert( hasUnsharedAliasing!(int, shared(int)*, Rebindable!Object)); 3576 static assert(!hasUnsharedAliasing!(shared(int)*, Rebindable!(shared Object))); 3577 static assert(!hasUnsharedAliasing!()); 3578 3579 struct S9 3580 { 3581 void delegate() shared a; 3582 void delegate() immutable b; 3583 void delegate() shared const c; 3584 shared(void delegate()) d; 3585 shared(void delegate() shared) e; 3586 shared(void delegate() immutable) f; 3587 shared(void delegate() shared const) g; 3588 immutable(void delegate()) h; 3589 immutable(void delegate() shared) i; 3590 immutable(void delegate() immutable) j; 3591 immutable(void delegate() shared const) k; 3592 shared(const(void delegate())) l; 3593 shared(const(void delegate() shared)) m; 3594 shared(const(void delegate() immutable)) n; 3595 shared(const(void delegate() shared const)) o; 3596 } 3597 struct S10 { typeof(S9.tupleof) a; void delegate() p; } 3598 struct S11 { typeof(S9.tupleof) a; Object p; } 3599 struct S12 { typeof(S9.tupleof) a; int* p; } 3600 class S13 { typeof(S9.tupleof) a; } 3601 class S14 { typeof(S9.tupleof) a; void delegate() p; } 3602 class S15 { typeof(S9.tupleof) a; Object p; } 3603 class S16 { typeof(S9.tupleof) a; int* p; } 3604 static assert(!hasUnsharedAliasing!S9); 3605 static assert(!hasUnsharedAliasing!(immutable(S9))); 3606 static assert(!hasUnsharedAliasing!(shared(S9))); 3607 static assert( hasUnsharedAliasing!S10); 3608 static assert(!hasUnsharedAliasing!(immutable(S10))); 3609 static assert(!hasUnsharedAliasing!(shared(S10))); 3610 static assert( hasUnsharedAliasing!S11); 3611 static assert(!hasUnsharedAliasing!(immutable(S11))); 3612 static assert(!hasUnsharedAliasing!(shared(S11))); 3613 static assert( hasUnsharedAliasing!S12); 3614 static assert(!hasUnsharedAliasing!(immutable(S12))); 3615 static assert(!hasUnsharedAliasing!(shared(S12))); 3616 static assert( hasUnsharedAliasing!S13); 3617 static assert(!hasUnsharedAliasing!(immutable(S13))); 3618 static assert(!hasUnsharedAliasing!(shared(S13))); 3619 static assert( hasUnsharedAliasing!S14); 3620 static assert(!hasUnsharedAliasing!(immutable(S14))); 3621 static assert(!hasUnsharedAliasing!(shared(S14))); 3622 static assert( hasUnsharedAliasing!S15); 3623 static assert(!hasUnsharedAliasing!(immutable(S15))); 3624 static assert(!hasUnsharedAliasing!(shared(S15))); 3625 static assert( hasUnsharedAliasing!S16); 3626 static assert(!hasUnsharedAliasing!(immutable(S16))); 3627 static assert(!hasUnsharedAliasing!(shared(S16))); 3628 struct S17 {} 3629 class S18 {} 3630 interface S19 {} 3631 union S20 {} 3632 static assert(!hasUnsharedAliasing!S17); 3633 static assert( hasUnsharedAliasing!S18); 3634 static assert( hasUnsharedAliasing!S19); 3635 static assert(!hasUnsharedAliasing!S20); 3636 } 3637 3638 private template hasUnsharedAliasingImpl(T) 3639 { 3640 import std.typecons : Rebindable; 3641 3642 static if (is(T R: Rebindable!R)) 3643 { 3644 enum hasUnsharedAliasingImpl = hasUnsharedAliasingImpl!R; 3645 } 3646 else 3647 { 3648 template unsharedDelegate(T) 3649 { 3650 enum bool unsharedDelegate = isDelegate!T 3651 && !is(T == shared) 3652 && !is(T == immutable) 3653 && !is(FunctionTypeOf!T == shared) 3654 && !is(FunctionTypeOf!T == immutable); 3655 } 3656 3657 enum hasUnsharedAliasingImpl = 3658 hasRawUnsharedAliasing!T || 3659 anySatisfy!(unsharedDelegate, RepresentationTypeTuple!T) || 3660 hasUnsharedObjects!T; 3661 } 3662 } 3663 3664 /** 3665 True if `S` or any type embedded directly in the representation of `S` 3666 defines an elaborate copy constructor. Elaborate copy constructors are 3667 introduced by defining `this(this)` for a `struct`. 3668 3669 Classes and unions never have elaborate copy constructors. 3670 */ 3671 template hasElaborateCopyConstructor(S) 3672 { 3673 import core.internal.traits : hasElabCCtor = hasElaborateCopyConstructor; 3674 alias hasElaborateCopyConstructor = hasElabCCtor!(S); 3675 } 3676 3677 /// 3678 @safe unittest 3679 { 3680 static assert(!hasElaborateCopyConstructor!int); 3681 3682 static struct S1 { } 3683 static struct S2 { this(this) {} } 3684 static struct S3 { S2 field; } 3685 static struct S4 { S3[1] field; } 3686 static struct S5 { S3[] field; } 3687 static struct S6 { S3[0] field; } 3688 static struct S7 { @disable this(); S3 field; } 3689 static assert(!hasElaborateCopyConstructor!S1); 3690 static assert( hasElaborateCopyConstructor!S2); 3691 static assert( hasElaborateCopyConstructor!(immutable S2)); 3692 static assert( hasElaborateCopyConstructor!S3); 3693 static assert( hasElaborateCopyConstructor!(S3[1])); 3694 static assert(!hasElaborateCopyConstructor!(S3[0])); 3695 static assert( hasElaborateCopyConstructor!S4); 3696 static assert(!hasElaborateCopyConstructor!S5); 3697 static assert(!hasElaborateCopyConstructor!S6); 3698 static assert( hasElaborateCopyConstructor!S7); 3699 } 3700 3701 /** 3702 True if `S` or any type directly embedded in the representation of `S` 3703 defines an elaborate assignment. Elaborate assignments are introduced by 3704 defining `opAssign(typeof(this))` or $(D opAssign(ref typeof(this))) 3705 for a `struct` or when there is a compiler-generated `opAssign`. 3706 3707 A type `S` gets compiler-generated `opAssign` if it has 3708 an elaborate destructor. 3709 3710 Classes and unions never have elaborate assignments. 3711 3712 Note: Structs with (possibly nested) postblit operator(s) will have a 3713 hidden yet elaborate compiler generated assignment operator (unless 3714 explicitly disabled). 3715 */ 3716 template hasElaborateAssign(S) 3717 { 3718 static if (isStaticArray!S && S.length) 3719 { 3720 enum bool hasElaborateAssign = hasElaborateAssign!(typeof(S.init[0])); 3721 } 3722 else static if (is(S == struct)) 3723 { 3724 enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) || 3725 is(typeof(S.init.opAssign(lvalueOf!S))) || 3726 anySatisfy!(.hasElaborateAssign, FieldTypeTuple!S); 3727 } 3728 else 3729 { 3730 enum bool hasElaborateAssign = false; 3731 } 3732 } 3733 3734 /// 3735 @safe unittest 3736 { 3737 static assert(!hasElaborateAssign!int); 3738 3739 static struct S { void opAssign(S) {} } 3740 static assert( hasElaborateAssign!S); 3741 static assert(!hasElaborateAssign!(const(S))); 3742 3743 static struct S1 { void opAssign(ref S1) {} } 3744 static struct S2 { void opAssign(int) {} } 3745 static struct S3 { S s; } 3746 static assert( hasElaborateAssign!S1); 3747 static assert(!hasElaborateAssign!S2); 3748 static assert( hasElaborateAssign!S3); 3749 static assert( hasElaborateAssign!(S3[1])); 3750 static assert(!hasElaborateAssign!(S3[0])); 3751 } 3752 3753 @safe unittest 3754 { 3755 static struct S { void opAssign(S) {} } 3756 static struct S4 3757 { 3758 void opAssign(U)(U u) {} 3759 @disable void opAssign(U)(ref U u); 3760 } 3761 static assert( hasElaborateAssign!S4); 3762 3763 static struct S41 3764 { 3765 void opAssign(U)(ref U u) {} 3766 @disable void opAssign(U)(U u); 3767 } 3768 static assert( hasElaborateAssign!S41); 3769 3770 static struct S5 { @disable this(); this(int n){ s = S(); } S s; } 3771 static assert( hasElaborateAssign!S5); 3772 3773 static struct S6 { this(this) {} } 3774 static struct S7 { this(this) {} @disable void opAssign(S7); } 3775 static struct S8 { this(this) {} @disable void opAssign(S8); void opAssign(int) {} } 3776 static struct S9 { this(this) {} void opAssign(int) {} } 3777 static struct S10 { ~this() { } } 3778 static assert( hasElaborateAssign!S6); 3779 static assert(!hasElaborateAssign!S7); 3780 static assert(!hasElaborateAssign!S8); 3781 static assert( hasElaborateAssign!S9); 3782 static assert( hasElaborateAssign!S10); 3783 static struct SS6 { S6 s; } 3784 static struct SS7 { S7 s; } 3785 static struct SS8 { S8 s; } 3786 static struct SS9 { S9 s; } 3787 static assert( hasElaborateAssign!SS6); 3788 static assert(!hasElaborateAssign!SS7); 3789 static assert(!hasElaborateAssign!SS8); 3790 static assert( hasElaborateAssign!SS9); 3791 } 3792 3793 /** 3794 True if `S` or any type directly embedded in the representation 3795 of `S` defines an elaborate destructor. Elaborate destructors 3796 are introduced by defining `~this()` for a $(D 3797 struct). 3798 3799 Classes and unions never have elaborate destructors, even 3800 though classes may define `~this()`. 3801 */ 3802 template hasElaborateDestructor(S) 3803 { 3804 import core.internal.traits : hasElabDest = hasElaborateDestructor; 3805 alias hasElaborateDestructor = hasElabDest!(S); 3806 } 3807 3808 /// 3809 @safe unittest 3810 { 3811 static assert(!hasElaborateDestructor!int); 3812 3813 static struct S1 { } 3814 static struct S2 { ~this() {} } 3815 static struct S3 { S2 field; } 3816 static struct S4 { S3[1] field; } 3817 static struct S5 { S3[] field; } 3818 static struct S6 { S3[0] field; } 3819 static struct S7 { @disable this(); S3 field; } 3820 static assert(!hasElaborateDestructor!S1); 3821 static assert( hasElaborateDestructor!S2); 3822 static assert( hasElaborateDestructor!(immutable S2)); 3823 static assert( hasElaborateDestructor!S3); 3824 static assert( hasElaborateDestructor!(S3[1])); 3825 static assert(!hasElaborateDestructor!(S3[0])); 3826 static assert( hasElaborateDestructor!S4); 3827 static assert(!hasElaborateDestructor!S5); 3828 static assert(!hasElaborateDestructor!S6); 3829 static assert( hasElaborateDestructor!S7); 3830 } 3831 3832 /** 3833 True if `S` or any type embedded directly in the representation of `S` 3834 defines elaborate move semantics. Elaborate move semantics are 3835 introduced by defining `opPostMove(ref typeof(this))` for a `struct`. 3836 3837 Classes and unions never have elaborate move semantics. 3838 */ 3839 template hasElaborateMove(S) 3840 { 3841 import core.internal.traits : hasElabMove = hasElaborateMove; 3842 alias hasElaborateMove = hasElabMove!(S); 3843 } 3844 3845 /// 3846 @safe unittest 3847 { 3848 static assert(!hasElaborateMove!int); 3849 3850 static struct S1 { } 3851 static struct S2 { void opPostMove(ref S2) {} } 3852 static struct S3 { void opPostMove(inout ref S3) inout {} } 3853 static struct S4 { void opPostMove(const ref S4) {} } 3854 static struct S5 { void opPostMove(S5) {} } 3855 static struct S6 { void opPostMove(int) {} } 3856 static struct S7 { S3[1] field; } 3857 static struct S8 { S3[] field; } 3858 static struct S9 { S3[0] field; } 3859 static struct S10 { @disable this(); S3 field; } 3860 static assert(!hasElaborateMove!S1); 3861 static assert( hasElaborateMove!S2); 3862 static assert( hasElaborateMove!S3); 3863 static assert( hasElaborateMove!(immutable S3)); 3864 static assert( hasElaborateMove!S4); 3865 static assert(!hasElaborateMove!S5); 3866 static assert(!hasElaborateMove!S6); 3867 static assert( hasElaborateMove!S7); 3868 static assert(!hasElaborateMove!S8); 3869 static assert(!hasElaborateMove!S9); 3870 static assert( hasElaborateMove!S10); 3871 } 3872 3873 package alias Identity(alias A) = A; 3874 3875 /** 3876 Yields `true` if and only if `T` is an aggregate that defines 3877 a symbol called `name`. 3878 */ 3879 enum hasMember(T, string name) = __traits(hasMember, T, name); 3880 3881 /// 3882 @safe unittest 3883 { 3884 static assert(!hasMember!(int, "blah")); 3885 struct S1 { int blah; } 3886 struct S2 { int blah(){ return 0; } } 3887 class C1 { int blah; } 3888 class C2 { int blah(){ return 0; } } 3889 static assert(hasMember!(S1, "blah")); 3890 static assert(hasMember!(S2, "blah")); 3891 static assert(hasMember!(C1, "blah")); 3892 static assert(hasMember!(C2, "blah")); 3893 } 3894 3895 @safe unittest 3896 { 3897 // https://issues.dlang.org/show_bug.cgi?id=8321 3898 struct S { 3899 int x; 3900 void f(){} 3901 void t()(){} 3902 template T(){} 3903 } 3904 struct R1(T) { 3905 T t; 3906 alias t this; 3907 } 3908 struct R2(T) { 3909 T t; 3910 @property ref inout(T) payload() inout { return t; } 3911 alias t this; 3912 } 3913 static assert(hasMember!(S, "x")); 3914 static assert(hasMember!(S, "f")); 3915 static assert(hasMember!(S, "t")); 3916 static assert(hasMember!(S, "T")); 3917 static assert(hasMember!(R1!S, "x")); 3918 static assert(hasMember!(R1!S, "f")); 3919 static assert(hasMember!(R1!S, "t")); 3920 static assert(hasMember!(R1!S, "T")); 3921 static assert(hasMember!(R2!S, "x")); 3922 static assert(hasMember!(R2!S, "f")); 3923 static assert(hasMember!(R2!S, "t")); 3924 static assert(hasMember!(R2!S, "T")); 3925 } 3926 3927 @safe unittest 3928 { 3929 static struct S 3930 { 3931 void opDispatch(string n, A)(A dummy) {} 3932 } 3933 static assert(hasMember!(S, "foo")); 3934 } 3935 3936 /** 3937 * Whether the symbol represented by the string, member, exists and is a static member of T. 3938 * 3939 * Params: 3940 * T = Type containing symbol `member`. 3941 * member = Name of symbol to test that resides in `T`. 3942 * 3943 * Returns: 3944 * `true` iff `member` exists and is static. 3945 */ 3946 template hasStaticMember(T, string member) 3947 { 3948 static if (__traits(hasMember, T, member)) 3949 { 3950 static if (isPointer!T) 3951 alias U = PointerTarget!T; 3952 else 3953 alias U = T; 3954 3955 import std.meta : Alias; 3956 alias sym = Alias!(__traits(getMember, U, member)); 3957 3958 static if (__traits(getOverloads, U, member).length == 0) 3959 enum bool hasStaticMember = __traits(compiles, &sym); 3960 else 3961 enum bool hasStaticMember = __traits(isStaticFunction, sym); 3962 } 3963 else 3964 { 3965 enum bool hasStaticMember = false; 3966 } 3967 } 3968 3969 /// 3970 @safe unittest 3971 { 3972 static struct S 3973 { 3974 static void sf() {} 3975 void f() {} 3976 3977 static int si; 3978 int i; 3979 } 3980 3981 static assert( hasStaticMember!(S, "sf")); 3982 static assert(!hasStaticMember!(S, "f")); 3983 3984 static assert( hasStaticMember!(S, "si")); 3985 static assert(!hasStaticMember!(S, "i")); 3986 3987 static assert(!hasStaticMember!(S, "hello")); 3988 } 3989 3990 @safe unittest 3991 { 3992 static struct S 3993 { 3994 enum X = 10; 3995 enum Y 3996 { 3997 i = 10 3998 } 3999 struct S {} 4000 class C {} 4001 4002 static int sx = 0; 4003 __gshared int gx = 0; 4004 4005 Y y; 4006 static Y sy; 4007 4008 static void f(); 4009 static void f2() pure nothrow @nogc @safe; 4010 4011 void g() shared; 4012 4013 static void function() fp; 4014 __gshared void function() gfp; 4015 void function() fpm; 4016 4017 void delegate() dm; 4018 static void delegate() sd; 4019 4020 void m(); 4021 void m2() const pure nothrow @nogc @safe; 4022 4023 inout(int) iom() inout; 4024 static inout(int) iosf(inout int x); 4025 4026 @property int p(); 4027 static @property int sp(); 4028 } 4029 4030 static class C 4031 { 4032 enum X = 10; 4033 enum Y 4034 { 4035 i = 10 4036 } 4037 struct S {} 4038 class C {} 4039 4040 static int sx = 0; 4041 __gshared int gx = 0; 4042 4043 Y y; 4044 static Y sy; 4045 4046 static void f(); 4047 static void f2() pure nothrow @nogc @safe; 4048 4049 void g() shared { } 4050 4051 static void function() fp; 4052 __gshared void function() gfp; 4053 void function() fpm; 4054 4055 void delegate() dm; 4056 static void delegate() sd; 4057 4058 void m() {} 4059 final void m2() const pure nothrow @nogc @safe; 4060 4061 inout(int) iom() inout { return 10; } 4062 static inout(int) iosf(inout int x); 4063 4064 @property int p() { return 10; } 4065 static @property int sp(); 4066 } 4067 4068 static assert(!hasStaticMember!(S, "na")); 4069 static assert(!hasStaticMember!(S, "X")); 4070 static assert(!hasStaticMember!(S, "Y")); 4071 static assert(!hasStaticMember!(S, "Y.i")); 4072 static assert(!hasStaticMember!(S, "S")); 4073 static assert(!hasStaticMember!(S, "C")); 4074 static assert( hasStaticMember!(S, "sx")); 4075 static assert( hasStaticMember!(S, "gx")); 4076 static assert(!hasStaticMember!(S, "y")); 4077 static assert( hasStaticMember!(S, "sy")); 4078 static assert( hasStaticMember!(S, "f")); 4079 static assert( hasStaticMember!(S, "f2")); 4080 static assert(!hasStaticMember!(S, "dm")); 4081 static assert( hasStaticMember!(S, "sd")); 4082 static assert(!hasStaticMember!(S, "g")); 4083 static assert( hasStaticMember!(S, "fp")); 4084 static assert( hasStaticMember!(S, "gfp")); 4085 static assert(!hasStaticMember!(S, "fpm")); 4086 static assert(!hasStaticMember!(S, "m")); 4087 static assert(!hasStaticMember!(S, "m2")); 4088 static assert(!hasStaticMember!(S, "iom")); 4089 static assert( hasStaticMember!(S, "iosf")); 4090 static assert(!hasStaticMember!(S, "p")); 4091 static assert( hasStaticMember!(S, "sp")); 4092 4093 static assert(!hasStaticMember!(C, "na")); 4094 static assert(!hasStaticMember!(C, "X")); 4095 static assert(!hasStaticMember!(C, "Y")); 4096 static assert(!hasStaticMember!(C, "Y.i")); 4097 static assert(!hasStaticMember!(C, "S")); 4098 static assert(!hasStaticMember!(C, "C")); 4099 static assert( hasStaticMember!(C, "sx")); 4100 static assert( hasStaticMember!(C, "gx")); 4101 static assert(!hasStaticMember!(C, "y")); 4102 static assert( hasStaticMember!(C, "sy")); 4103 static assert( hasStaticMember!(C, "f")); 4104 static assert( hasStaticMember!(C, "f2")); 4105 static assert(!hasStaticMember!(C, "dm")); 4106 static assert( hasStaticMember!(C, "sd")); 4107 static assert(!hasStaticMember!(C, "g")); 4108 static assert( hasStaticMember!(C, "fp")); 4109 static assert( hasStaticMember!(C, "gfp")); 4110 static assert(!hasStaticMember!(C, "fpm")); 4111 static assert(!hasStaticMember!(C, "m")); 4112 static assert(!hasStaticMember!(C, "m2")); 4113 static assert(!hasStaticMember!(C, "iom")); 4114 static assert( hasStaticMember!(C, "iosf")); 4115 static assert(!hasStaticMember!(C, "p")); 4116 static assert( hasStaticMember!(C, "sp")); 4117 4118 alias P = S*; 4119 static assert(!hasStaticMember!(P, "na")); 4120 static assert(!hasStaticMember!(P, "X")); 4121 static assert(!hasStaticMember!(P, "Y")); 4122 static assert(!hasStaticMember!(P, "Y.i")); 4123 static assert(!hasStaticMember!(P, "S")); 4124 static assert(!hasStaticMember!(P, "C")); 4125 static assert( hasStaticMember!(P, "sx")); 4126 static assert( hasStaticMember!(P, "gx")); 4127 static assert(!hasStaticMember!(P, "y")); 4128 static assert( hasStaticMember!(P, "sy")); 4129 static assert( hasStaticMember!(P, "f")); 4130 static assert( hasStaticMember!(P, "f2")); 4131 static assert(!hasStaticMember!(P, "dm")); 4132 static assert( hasStaticMember!(P, "sd")); 4133 static assert(!hasStaticMember!(P, "g")); 4134 static assert( hasStaticMember!(P, "fp")); 4135 static assert( hasStaticMember!(P, "gfp")); 4136 static assert(!hasStaticMember!(P, "fpm")); 4137 static assert(!hasStaticMember!(P, "m")); 4138 static assert(!hasStaticMember!(P, "m2")); 4139 static assert(!hasStaticMember!(P, "iom")); 4140 static assert( hasStaticMember!(P, "iosf")); 4141 static assert(!hasStaticMember!(P, "p")); 4142 static assert( hasStaticMember!(P, "sp")); 4143 } 4144 4145 /** 4146 Retrieves the members of an enumerated type `enum E`. 4147 4148 Params: 4149 E = An enumerated type. `E` may have duplicated values. 4150 4151 Returns: 4152 Static tuple composed of the members of the enumerated type `E`. 4153 The members are arranged in the same order as declared in `E`. 4154 The name of the enum can be found by querying the compiler for the 4155 name of the identifier, i.e. `__traits(identifier, EnumMembers!MyEnum[i])`. 4156 For enumerations with unique values, $(REF to, std,conv) can also be used. 4157 4158 Note: 4159 An enum can have multiple members which have the same value. If you want 4160 to use EnumMembers to e.g. generate switch cases at compile-time, 4161 you should use the $(REF NoDuplicates, std,meta) template to avoid 4162 generating duplicate switch cases. 4163 4164 Note: 4165 Returned values are strictly typed with `E`. Thus, the following code 4166 does not work without the explicit cast: 4167 -------------------- 4168 enum E : int { a, b, c } 4169 int[] abc = cast(int[]) [ EnumMembers!E ]; 4170 -------------------- 4171 Cast is not necessary if the type of the variable is inferred. See the 4172 example below. 4173 */ 4174 template EnumMembers(E) 4175 if (is(E == enum)) 4176 { 4177 import std.meta : AliasSeq; 4178 // Supply the specified identifier to an constant value. 4179 template WithIdentifier(string ident) 4180 { 4181 static if (ident == "Symbolize") 4182 { 4183 template Symbolize(alias value) 4184 { 4185 enum Symbolize = value; 4186 } 4187 } 4188 else 4189 { 4190 mixin("template Symbolize(alias "~ ident ~")" 4191 ~"{" 4192 ~"alias Symbolize = "~ ident ~";" 4193 ~"}"); 4194 } 4195 } 4196 4197 template EnumSpecificMembers(names...) 4198 { 4199 static if (names.length == 1) 4200 { 4201 alias EnumSpecificMembers = AliasSeq!(WithIdentifier!(names[0]) 4202 .Symbolize!(__traits(getMember, E, names[0]))); 4203 } 4204 else static if (names.length > 0) 4205 { 4206 alias EnumSpecificMembers = 4207 AliasSeq!( 4208 WithIdentifier!(names[0]) 4209 .Symbolize!(__traits(getMember, E, names[0])), 4210 EnumSpecificMembers!(names[1 .. $/2]), 4211 EnumSpecificMembers!(names[$/2..$]) 4212 ); 4213 } 4214 else 4215 { 4216 alias EnumSpecificMembers = AliasSeq!(); 4217 } 4218 } 4219 4220 alias EnumMembers = EnumSpecificMembers!(__traits(allMembers, E)); 4221 } 4222 4223 /// Create an array of enumerated values 4224 @safe unittest 4225 { 4226 enum Sqrts : real 4227 { 4228 one = 1, 4229 two = 1.41421, 4230 three = 1.73205 4231 } 4232 auto sqrts = [EnumMembers!Sqrts]; 4233 assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]); 4234 } 4235 4236 /** 4237 A generic function `rank(v)` in the following example uses this 4238 template for finding a member `e` in an enumerated type `E`. 4239 */ 4240 @safe unittest 4241 { 4242 // Returns i if e is the i-th enumerator of E. 4243 static size_t rank(E)(E e) 4244 if (is(E == enum)) 4245 { 4246 static foreach (i, member; EnumMembers!E) 4247 { 4248 if (e == member) 4249 return i; 4250 } 4251 assert(0, "Not an enum member"); 4252 } 4253 4254 enum Mode 4255 { 4256 read = 1, 4257 write = 2, 4258 map = 4 4259 } 4260 assert(rank(Mode.read) == 0); 4261 assert(rank(Mode.write) == 1); 4262 assert(rank(Mode.map) == 2); 4263 } 4264 4265 /** 4266 Use EnumMembers to generate a switch statement using static foreach. 4267 */ 4268 4269 @safe unittest 4270 { 4271 import std.conv : to; 4272 class FooClass 4273 { 4274 string calledMethod; 4275 void foo() @safe { calledMethod = "foo"; } 4276 void bar() @safe { calledMethod = "bar"; } 4277 void baz() @safe { calledMethod = "baz"; } 4278 } 4279 4280 enum FooEnum { foo, bar, baz } 4281 4282 auto var = FooEnum.bar; 4283 auto fooObj = new FooClass(); 4284 s: final switch (var) 4285 { 4286 static foreach (member; EnumMembers!FooEnum) 4287 { 4288 case member: // Generate a case for each enum value. 4289 // Call fooObj.{name of enum value}(). 4290 __traits(getMember, fooObj, to!string(member))(); 4291 break s; 4292 } 4293 } 4294 // As we pass in FooEnum.bar, the bar() method gets called. 4295 assert(fooObj.calledMethod == "bar"); 4296 } 4297 4298 @safe unittest 4299 { 4300 enum A { a } 4301 static assert([ EnumMembers!A ] == [ A.a ]); 4302 enum B { a, b, c, d, e } 4303 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c, B.d, B.e ]); 4304 } 4305 4306 @safe unittest // typed enums 4307 { 4308 enum A : string { a = "alpha", b = "beta" } 4309 static assert([ EnumMembers!A ] == [ A.a, A.b ]); 4310 4311 static struct S 4312 { 4313 int value; 4314 int opCmp(S rhs) const nothrow { return value - rhs.value; } 4315 } 4316 enum B : S { a = S(1), b = S(2), c = S(3) } 4317 static assert([ EnumMembers!B ] == [ B.a, B.b, B.c ]); 4318 } 4319 4320 @safe unittest // duplicated values 4321 { 4322 enum A 4323 { 4324 a = 0, b = 0, 4325 c = 1, d = 1, e 4326 } 4327 static assert([ EnumMembers!A ] == [ A.a, A.b, A.c, A.d, A.e ]); 4328 } 4329 4330 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums 4331 @safe unittest 4332 { 4333 string genEnum() 4334 { 4335 string result = "enum TLAs {"; 4336 foreach (c0; '0'..'2'+1) 4337 foreach (c1; '0'..'9'+1) 4338 foreach (c2; '0'..'9'+1) 4339 foreach (c3; '0'..'9'+1) 4340 { 4341 result ~= '_'; 4342 result ~= c0; 4343 result ~= c1; 4344 result ~= c2; 4345 result ~= c3; 4346 result ~= ','; 4347 } 4348 result ~= '}'; 4349 return result; 4350 } 4351 mixin(genEnum); 4352 static assert(EnumMembers!TLAs[0] == TLAs._0000); 4353 static assert(EnumMembers!TLAs[$-1] == TLAs._2999); 4354 } 4355 4356 @safe unittest 4357 { 4358 enum E { member, a = 0, b = 0 } 4359 static assert(__traits(identifier, EnumMembers!E[0]) == "member"); 4360 static assert(__traits(identifier, EnumMembers!E[1]) == "a"); 4361 static assert(__traits(identifier, EnumMembers!E[2]) == "b"); 4362 } 4363 4364 4365 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 4366 // Classes and Interfaces 4367 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 4368 4369 /*** 4370 * Get a $(D_PARAM AliasSeq) of the base class and base interfaces of 4371 * this class or interface. $(D_PARAM BaseTypeTuple!Object) returns 4372 * the empty type tuple. 4373 */ 4374 template BaseTypeTuple(A) 4375 { 4376 static if (is(A P == super)) 4377 alias BaseTypeTuple = P; 4378 else 4379 static assert(0, "argument is not a class or interface"); 4380 } 4381 4382 /// 4383 @safe unittest 4384 { 4385 import std.meta : AliasSeq; 4386 4387 interface I1 { } 4388 interface I2 { } 4389 interface I12 : I1, I2 { } 4390 static assert(is(BaseTypeTuple!I12 == AliasSeq!(I1, I2))); 4391 4392 interface I3 : I1 { } 4393 interface I123 : I1, I2, I3 { } 4394 static assert(is(BaseTypeTuple!I123 == AliasSeq!(I1, I2, I3))); 4395 } 4396 4397 @safe unittest 4398 { 4399 interface I1 { } 4400 interface I2 { } 4401 class A { } 4402 class C : A, I1, I2 { } 4403 4404 alias TL = BaseTypeTuple!C; 4405 assert(TL.length == 3); 4406 assert(is (TL[0] == A)); 4407 assert(is (TL[1] == I1)); 4408 assert(is (TL[2] == I2)); 4409 4410 assert(BaseTypeTuple!Object.length == 0); 4411 } 4412 4413 /** 4414 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of this class, 4415 * in decreasing order. Interfaces are not included. $(D_PARAM 4416 * BaseClassesTuple!Object) yields the empty type tuple. 4417 */ 4418 template BaseClassesTuple(T) 4419 if (is(T == class)) 4420 { 4421 static if (is(T == Object)) 4422 { 4423 alias BaseClassesTuple = AliasSeq!(); 4424 } 4425 else static if (is(BaseTypeTuple!T[0] == Object)) 4426 { 4427 alias BaseClassesTuple = AliasSeq!Object; 4428 } 4429 else static if (!is(BaseTypeTuple!T[0] == Object) && !is(BaseTypeTuple!T[0] == class)) 4430 { 4431 alias BaseClassesTuple = AliasSeq!(); 4432 } 4433 else 4434 { 4435 alias BaseClassesTuple = 4436 AliasSeq!(BaseTypeTuple!T[0], 4437 BaseClassesTuple!(BaseTypeTuple!T[0])); 4438 } 4439 } 4440 4441 /// 4442 @safe unittest 4443 { 4444 import std.meta : AliasSeq; 4445 4446 class C1 { } 4447 class C2 : C1 { } 4448 class C3 : C2 { } 4449 static assert(!BaseClassesTuple!Object.length); 4450 static assert(is(BaseClassesTuple!C1 == AliasSeq!(Object))); 4451 static assert(is(BaseClassesTuple!C2 == AliasSeq!(C1, Object))); 4452 static assert(is(BaseClassesTuple!C3 == AliasSeq!(C2, C1, Object))); 4453 } 4454 4455 // https://issues.dlang.org/show_bug.cgi?id=17276 4456 @safe unittest 4457 { 4458 extern (C++) static interface Ext 4459 { 4460 void someext(); 4461 } 4462 4463 extern (C++) static class E : Ext 4464 { 4465 void someext() {} 4466 } 4467 4468 alias BaseClassesWithNoObject = BaseClassesTuple!E; 4469 } 4470 4471 @safe unittest 4472 { 4473 struct S { } 4474 static assert(!__traits(compiles, BaseClassesTuple!S)); 4475 interface I { } 4476 static assert(!__traits(compiles, BaseClassesTuple!I)); 4477 class C4 : I { } 4478 class C5 : C4, I { } 4479 static assert(is(BaseClassesTuple!C5 == AliasSeq!(C4, Object))); 4480 } 4481 4482 /** 4483 Params: 4484 T = The `class` or `interface` to search. 4485 4486 Returns: 4487 $(REF AliasSeq,std,meta) of all interfaces directly or 4488 indirectly inherited by this class or interface. Interfaces 4489 do not repeat if multiply implemented. 4490 4491 `InterfacesTuple!Object` yields an empty `AliasSeq`. 4492 */ 4493 template InterfacesTuple(T) 4494 { 4495 import std.meta : NoDuplicates; 4496 template Flatten(H, T...) 4497 { 4498 static if (T.length) 4499 { 4500 alias Flatten = AliasSeq!(Flatten!H, Flatten!T); 4501 } 4502 else 4503 { 4504 static if (is(H == interface)) 4505 alias Flatten = AliasSeq!(H, InterfacesTuple!H); 4506 else 4507 alias Flatten = InterfacesTuple!H; 4508 } 4509 } 4510 4511 static if (is(T S == super) && S.length) 4512 alias InterfacesTuple = NoDuplicates!(Flatten!S); 4513 else 4514 alias InterfacesTuple = AliasSeq!(); 4515 } 4516 4517 /// 4518 @safe unittest 4519 { 4520 interface I1 {} 4521 interface I2 {} 4522 class A : I1, I2 {} 4523 class B : A, I1 {} 4524 class C : B {} 4525 4526 alias TL = InterfacesTuple!C; 4527 static assert(is(TL[0] == I1) && is(TL[1] == I2)); 4528 } 4529 4530 @safe unittest 4531 { 4532 interface Iaa {} 4533 interface Iab {} 4534 interface Iba {} 4535 interface Ibb {} 4536 interface Ia : Iaa, Iab {} 4537 interface Ib : Iba, Ibb {} 4538 interface I : Ia, Ib {} 4539 interface J {} 4540 class B2 : J {} 4541 class C2 : B2, Ia, Ib {} 4542 static assert(is(InterfacesTuple!I == 4543 AliasSeq!(Ia, Iaa, Iab, Ib, Iba, Ibb))); 4544 static assert(is(InterfacesTuple!C2 == 4545 AliasSeq!(J, Ia, Iaa, Iab, Ib, Iba, Ibb))); 4546 4547 } 4548 4549 /** 4550 * Get a $(D_PARAM AliasSeq) of $(I all) base classes of $(D_PARAM 4551 * T), in decreasing order, followed by $(D_PARAM T)'s 4552 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!Object) yields the 4553 * empty type tuple. 4554 */ 4555 template TransitiveBaseTypeTuple(T) 4556 { 4557 static if (is(T == Object)) 4558 alias TransitiveBaseTypeTuple = AliasSeq!(); 4559 else 4560 alias TransitiveBaseTypeTuple = 4561 AliasSeq!(BaseClassesTuple!T, InterfacesTuple!T); 4562 } 4563 4564 /// 4565 @safe unittest 4566 { 4567 interface J1 {} 4568 interface J2 {} 4569 class B1 {} 4570 class B2 : B1, J1, J2 {} 4571 class B3 : B2, J1 {} 4572 alias TL = TransitiveBaseTypeTuple!B3; 4573 assert(TL.length == 5); 4574 assert(is (TL[0] == B2)); 4575 assert(is (TL[1] == B1)); 4576 assert(is (TL[2] == Object)); 4577 assert(is (TL[3] == J1)); 4578 assert(is (TL[4] == J2)); 4579 4580 assert(TransitiveBaseTypeTuple!Object.length == 0); 4581 } 4582 4583 4584 /** 4585 Returns a tuple of non-static functions with the name `name` declared in the 4586 class or interface `C`. Covariant duplicates are shrunk into the most 4587 derived one. 4588 */ 4589 template MemberFunctionsTuple(C, string name) 4590 if (is(C == class) || is(C == interface)) 4591 { 4592 static if (__traits(hasMember, C, name)) 4593 { 4594 /* 4595 * First, collect all overloads in the class hierarchy. 4596 */ 4597 template CollectOverloads(Node) 4598 { 4599 static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name))) 4600 { 4601 // Get all overloads in sight (not hidden). 4602 alias inSight = __traits(getVirtualFunctions, Node, name); 4603 4604 // And collect all overloads in ancestor classes to reveal hidden 4605 // methods. The result may contain duplicates. 4606 template walkThru(Parents...) 4607 { 4608 static if (Parents.length > 0) 4609 alias walkThru = AliasSeq!( 4610 CollectOverloads!(Parents[0]), 4611 walkThru!(Parents[1 .. $]) 4612 ); 4613 else 4614 alias walkThru = AliasSeq!(); 4615 } 4616 4617 static if (is(Node Parents == super)) 4618 alias CollectOverloads = AliasSeq!(inSight, walkThru!Parents); 4619 else 4620 alias CollectOverloads = AliasSeq!inSight; 4621 } 4622 else 4623 alias CollectOverloads = AliasSeq!(); // no overloads in this hierarchy 4624 } 4625 4626 static if (name == "__ctor" || name == "__dtor") 4627 alias overloads = AliasSeq!(__traits(getOverloads, C, name)); 4628 else 4629 // duplicates in this tuple will be removed by shrink() 4630 alias overloads = CollectOverloads!C; 4631 4632 // shrinkOne!args[0] = the most derived one in the covariant siblings of target 4633 // shrinkOne!args[1..$] = non-covariant others 4634 template shrinkOne(/+ alias target, rest... +/ args...) 4635 { 4636 import std.meta : AliasSeq; 4637 alias target = args[0 .. 1]; // prevent property functions from being evaluated 4638 alias rest = args[1 .. $]; 4639 4640 static if (rest.length > 0) 4641 { 4642 alias Target = FunctionTypeOf!target; 4643 alias Rest0 = FunctionTypeOf!(rest[0]); 4644 4645 static if (isCovariantWith!(Target, Rest0) && isCovariantWith!(Rest0, Target)) 4646 { 4647 // One of these overrides the other. Choose the one from the most derived parent. 4648 static if (is(__traits(parent, target) : __traits(parent, rest[0]))) 4649 alias shrinkOne = shrinkOne!(target, rest[1 .. $]); 4650 else 4651 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]); 4652 } 4653 else static if (isCovariantWith!(Target, Rest0)) 4654 // target overrides rest[0] -- erase rest[0]. 4655 alias shrinkOne = shrinkOne!(target, rest[1 .. $]); 4656 else static if (isCovariantWith!(Rest0, Target)) 4657 // rest[0] overrides target -- erase target. 4658 alias shrinkOne = shrinkOne!(rest[0], rest[1 .. $]); 4659 else 4660 // target and rest[0] are distinct. 4661 alias shrinkOne = AliasSeq!( 4662 shrinkOne!(target, rest[1 .. $]), 4663 rest[0] // keep 4664 ); 4665 } 4666 else 4667 alias shrinkOne = AliasSeq!target; // done 4668 } 4669 4670 /* 4671 * Now shrink covariant overloads into one. 4672 */ 4673 template shrink(overloads...) 4674 { 4675 static if (overloads.length > 0) 4676 { 4677 alias temp = shrinkOne!overloads; 4678 alias shrink = AliasSeq!(temp[0], shrink!(temp[1 .. $])); 4679 } 4680 else 4681 alias shrink = AliasSeq!(); // done 4682 } 4683 4684 // done. 4685 alias MemberFunctionsTuple = shrink!overloads; 4686 } 4687 else 4688 alias MemberFunctionsTuple = AliasSeq!(); 4689 } 4690 4691 /// 4692 @safe unittest 4693 { 4694 interface I { I foo(); } 4695 class B 4696 { 4697 real foo(real v) { return v; } 4698 } 4699 class C : B, I 4700 { 4701 override C foo() { return this; } // covariant overriding of I.foo() 4702 } 4703 alias foos = MemberFunctionsTuple!(C, "foo"); 4704 static assert(foos.length == 2); 4705 static assert(__traits(isSame, foos[0], C.foo)); 4706 static assert(__traits(isSame, foos[1], B.foo)); 4707 } 4708 4709 // https://issues.dlang.org/show_bug.cgi?id=15920 4710 @safe unittest 4711 { 4712 import std.meta : AliasSeq; 4713 class A 4714 { 4715 void f(){} 4716 void f(int){} 4717 } 4718 class B : A 4719 { 4720 override void f(){} 4721 override void f(int){} 4722 } 4723 alias fs = MemberFunctionsTuple!(B, "f"); 4724 alias bfs = __traits(getOverloads, B, "f"); 4725 assert(__traits(isSame, fs[0], bfs[0]) || __traits(isSame, fs[0], bfs[1])); 4726 assert(__traits(isSame, fs[1], bfs[0]) || __traits(isSame, fs[1], bfs[1])); 4727 } 4728 4729 // https://issues.dlang.org/show_bug.cgi?id=8388 4730 @safe unittest 4731 { 4732 class C 4733 { 4734 this() {} 4735 this(int i) {} 4736 this(int i, float j) {} 4737 this(string s) {} 4738 4739 /* 4740 Commented out, because this causes a cyclic dependency 4741 between module constructors/destructors error. Might 4742 be caused by https://issues.dlang.org/show_bug.cgi?id=20529. */ 4743 // static this() {} 4744 4745 ~this() {} 4746 } 4747 4748 class D : C 4749 { 4750 this() {} 4751 ~this() {} 4752 } 4753 4754 alias test_ctor = MemberFunctionsTuple!(C, "__ctor"); 4755 assert(test_ctor.length == 4); 4756 alias test_dtor = MemberFunctionsTuple!(C, "__dtor"); 4757 assert(test_dtor.length == 1); 4758 alias test2_ctor = MemberFunctionsTuple!(D, "__ctor"); 4759 assert(test2_ctor.length == 1); 4760 alias test2_dtor = MemberFunctionsTuple!(D, "__dtor"); 4761 assert(test2_dtor.length == 1); 4762 } 4763 4764 @safe unittest 4765 { 4766 interface I { I test(); } 4767 interface J : I { J test(); } 4768 interface K { K test(int); } 4769 class B : I, K 4770 { 4771 K test(int) { return this; } 4772 B test() { return this; } 4773 static void test(string) { } 4774 } 4775 class C : B, J 4776 { 4777 override C test() { return this; } 4778 } 4779 alias test =MemberFunctionsTuple!(C, "test"); 4780 static assert(test.length == 2); 4781 static assert(is(FunctionTypeOf!(test[0]) == FunctionTypeOf!(C.test))); 4782 static assert(is(FunctionTypeOf!(test[1]) == FunctionTypeOf!(K.test))); 4783 alias noexist = MemberFunctionsTuple!(C, "noexist"); 4784 static assert(noexist.length == 0); 4785 4786 interface L { int prop() @property; } 4787 alias prop = MemberFunctionsTuple!(L, "prop"); 4788 static assert(prop.length == 1); 4789 4790 interface Test_I 4791 { 4792 void foo(); 4793 void foo(int); 4794 void foo(int, int); 4795 } 4796 interface Test : Test_I {} 4797 alias Test_foo = MemberFunctionsTuple!(Test, "foo"); 4798 static assert(Test_foo.length == 3); 4799 static assert(is(typeof(&Test_foo[0]) == void function())); 4800 static assert(is(typeof(&Test_foo[2]) == void function(int))); 4801 static assert(is(typeof(&Test_foo[1]) == void function(int, int))); 4802 } 4803 4804 4805 /** 4806 Returns an alias to the template that `T` is an instance of. 4807 It will return `void` if a symbol without a template is given. 4808 */ 4809 template TemplateOf(alias T : Base!Args, alias Base, Args...) 4810 { 4811 alias TemplateOf = Base; 4812 } 4813 4814 /// ditto 4815 template TemplateOf(T : Base!Args, alias Base, Args...) 4816 { 4817 alias TemplateOf = Base; 4818 } 4819 4820 /// ditto 4821 template TemplateOf(T) 4822 { 4823 alias TemplateOf = void; 4824 } 4825 4826 /// 4827 @safe unittest 4828 { 4829 struct Foo(T, U) {} 4830 static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo)); 4831 } 4832 4833 @safe unittest 4834 { 4835 template Foo1(A) {} 4836 template Foo2(A, B) {} 4837 template Foo3(alias A) {} 4838 template Foo4(string A) {} 4839 struct Foo5(A) {} 4840 struct Foo6(A, B) {} 4841 struct Foo7(alias A) {} 4842 template Foo8(A) { template Foo9(B) {} } 4843 template Foo10() {} 4844 4845 static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1)); 4846 static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2)); 4847 static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3)); 4848 static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4)); 4849 static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5)); 4850 static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6)); 4851 static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7)); 4852 static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9)); 4853 static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10)); 4854 } 4855 4856 // https://issues.dlang.org/show_bug.cgi?id=18214 4857 @safe unittest 4858 { 4859 static assert(is(TemplateOf!(int[]) == void)); 4860 static assert(is(TemplateOf!bool == void)); 4861 } 4862 4863 /** 4864 Returns a `AliasSeq` of the template arguments used to instantiate `T`. 4865 */ 4866 template TemplateArgsOf(alias T : Base!Args, alias Base, Args...) 4867 { 4868 alias TemplateArgsOf = Args; 4869 } 4870 4871 /// ditto 4872 template TemplateArgsOf(T : Base!Args, alias Base, Args...) 4873 { 4874 alias TemplateArgsOf = Args; 4875 } 4876 4877 /// 4878 @safe unittest 4879 { 4880 import std.meta : AliasSeq; 4881 4882 struct Foo(T, U) {} 4883 static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real))); 4884 } 4885 4886 @safe unittest 4887 { 4888 template Foo1(A) {} 4889 template Foo2(A, B) {} 4890 template Foo3(alias A) {} 4891 template Foo4(string A) {} 4892 struct Foo5(A) {} 4893 struct Foo6(A, B) {} 4894 struct Foo7(alias A) {} 4895 template Foo8(A) { template Foo9(B) {} } 4896 template Foo10() {} 4897 4898 enum x = 123; 4899 enum y = "123"; 4900 static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int))); 4901 static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int))); 4902 static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x))); 4903 static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y)); 4904 static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int))); 4905 static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int))); 4906 static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x))); 4907 static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real))); 4908 static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!())); 4909 } 4910 4911 4912 package template maxAlignment(U...) 4913 if (isTypeTuple!U) 4914 { 4915 static if (U.length == 0) 4916 static assert(0); 4917 else static if (U.length == 1) 4918 enum maxAlignment = U[0].alignof; 4919 else static if (U.length == 2) 4920 enum maxAlignment = U[0].alignof > U[1].alignof ? U[0].alignof : U[1].alignof; 4921 else 4922 { 4923 enum a = maxAlignment!(U[0 .. ($+1)/2]); 4924 enum b = maxAlignment!(U[($+1)/2 .. $]); 4925 enum maxAlignment = a > b ? a : b; 4926 } 4927 } 4928 4929 4930 /** 4931 Returns class instance alignment. 4932 */ 4933 template classInstanceAlignment(T) 4934 if (is(T == class)) 4935 { 4936 alias classInstanceAlignment = maxAlignment!(void*, typeof(T.tupleof)); 4937 } 4938 4939 /// 4940 @safe unittest 4941 { 4942 class A { byte b; } 4943 class B { long l; } 4944 4945 // As class instance always has a hidden pointer 4946 static assert(classInstanceAlignment!A == (void*).alignof); 4947 static assert(classInstanceAlignment!B == long.alignof); 4948 } 4949 4950 4951 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 4952 // Type Conversion 4953 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 4954 4955 /** 4956 Get the type that all types can be implicitly converted to. Useful 4957 e.g. in figuring out an array type from a bunch of initializing 4958 values. Returns $(D_PARAM void) if passed an empty list, or if the 4959 types have no common type. 4960 */ 4961 template CommonType(T...) 4962 { 4963 static if (!T.length) 4964 { 4965 alias CommonType = void; 4966 } 4967 else static if (T.length == 1) 4968 { 4969 static if (is(typeof(T[0]))) 4970 { 4971 alias CommonType = typeof(T[0]); 4972 } 4973 else 4974 { 4975 alias CommonType = T[0]; 4976 } 4977 } 4978 else static if (is(typeof(true ? T[0].init : T[1].init) U)) 4979 { 4980 alias CommonType = CommonType!(U, T[2 .. $]); 4981 } 4982 else 4983 alias CommonType = void; 4984 } 4985 4986 /// 4987 @safe unittest 4988 { 4989 alias X = CommonType!(int, long, short); 4990 assert(is(X == long)); 4991 alias Y = CommonType!(int, char[], short); 4992 assert(is(Y == void)); 4993 } 4994 4995 /// 4996 @safe unittest 4997 { 4998 static assert(is(CommonType!(3) == int)); 4999 static assert(is(CommonType!(double, 4, float) == double)); 5000 static assert(is(CommonType!(string, char[]) == const(char)[])); 5001 static assert(is(CommonType!(3, 3U) == uint)); 5002 static assert(is(CommonType!(double, int) == double)); 5003 } 5004 5005 5006 /** 5007 Params: 5008 T = The type to check 5009 5010 Returns: 5011 An $(REF AliasSeq,std,meta) with all possible target types of an implicit 5012 conversion `T`. 5013 5014 If `T` is a class derived from `Object`, the the result of 5015 $(LREF TransitiveBaseTypeTuple) is returned. 5016 5017 If the type is not a built-in value type or a class derived from 5018 `Object`, the an empty $(REF AliasSeq,std,meta) is returned. 5019 5020 Note: 5021 The possible targets are computed more conservatively than the 5022 language allows, eliminating all dangerous conversions. For example, 5023 `ImplicitConversionTargets!double` does not include `float`. 5024 5025 See_Also: 5026 $(LREF isImplicitlyConvertible) 5027 */ 5028 template ImplicitConversionTargets(T) 5029 { 5030 static if (is(T == bool)) 5031 alias ImplicitConversionTargets = 5032 AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList, 5033 float, double, real, char, wchar, dchar); 5034 else static if (is(T == byte)) 5035 alias ImplicitConversionTargets = 5036 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList, 5037 float, double, real, char, wchar, dchar); 5038 else static if (is(T == ubyte)) 5039 alias ImplicitConversionTargets = 5040 AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList, 5041 float, double, real, char, wchar, dchar); 5042 else static if (is(T == short)) 5043 alias ImplicitConversionTargets = 5044 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real); 5045 else static if (is(T == ushort)) 5046 alias ImplicitConversionTargets = 5047 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real); 5048 else static if (is(T == int)) 5049 alias ImplicitConversionTargets = 5050 AliasSeq!(long, ulong, CentTypeList, float, double, real); 5051 else static if (is(T == uint)) 5052 alias ImplicitConversionTargets = 5053 AliasSeq!(long, ulong, CentTypeList, float, double, real); 5054 else static if (is(T == long)) 5055 alias ImplicitConversionTargets = AliasSeq!(float, double, real); 5056 else static if (is(T == ulong)) 5057 alias ImplicitConversionTargets = AliasSeq!(float, double, real); 5058 else static if (is(cent) && is(T == cent)) 5059 alias ImplicitConversionTargets = AliasSeq!(float, double, real); 5060 else static if (is(ucent) && is(T == ucent)) 5061 alias ImplicitConversionTargets = AliasSeq!(float, double, real); 5062 else static if (is(T == float)) 5063 alias ImplicitConversionTargets = AliasSeq!(double, real); 5064 else static if (is(T == double)) 5065 alias ImplicitConversionTargets = AliasSeq!real; 5066 else static if (is(T == char)) 5067 alias ImplicitConversionTargets = 5068 AliasSeq!(wchar, dchar, byte, ubyte, short, ushort, 5069 int, uint, long, ulong, CentTypeList, float, double, real); 5070 else static if (is(T == wchar)) 5071 alias ImplicitConversionTargets = 5072 AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList, 5073 float, double, real); 5074 else static if (is(T == dchar)) 5075 alias ImplicitConversionTargets = 5076 AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real); 5077 else static if (is(T : typeof(null))) 5078 alias ImplicitConversionTargets = AliasSeq!(typeof(null)); 5079 else static if (is(T == class)) 5080 alias ImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T)); 5081 else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const)) 5082 { 5083 static if (is(typeof(T.init[0]) == shared)) 5084 alias ImplicitConversionTargets = 5085 AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]); 5086 else 5087 alias ImplicitConversionTargets = 5088 AliasSeq!(const(Unqual!(typeof(T.init[0])))[]); 5089 } 5090 else static if (is(T : void*)) 5091 alias ImplicitConversionTargets = AliasSeq!(void*); 5092 else 5093 alias ImplicitConversionTargets = AliasSeq!(); 5094 } 5095 5096 /// 5097 @safe unittest 5098 { 5099 import std.meta : AliasSeq; 5100 5101 static assert(is(ImplicitConversionTargets!(ulong) == AliasSeq!(float, double, real))); 5102 static assert(is(ImplicitConversionTargets!(int) == AliasSeq!(long, ulong, float, double, real))); 5103 static assert(is(ImplicitConversionTargets!(float) == AliasSeq!(double, real))); 5104 static assert(is(ImplicitConversionTargets!(double) == AliasSeq!(real))); 5105 5106 static assert(is(ImplicitConversionTargets!(char) == AliasSeq!( 5107 wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real 5108 ))); 5109 static assert(is(ImplicitConversionTargets!(wchar) == AliasSeq!( 5110 dchar, short, ushort, int, uint, long, ulong, float, double, real 5111 ))); 5112 static assert(is(ImplicitConversionTargets!(dchar) == AliasSeq!( 5113 int, uint, long, ulong, float, double, real 5114 ))); 5115 5116 static assert(is(ImplicitConversionTargets!(string) == AliasSeq!(const(char)[]))); 5117 static assert(is(ImplicitConversionTargets!(void*) == AliasSeq!(void*))); 5118 5119 interface A {} 5120 interface B {} 5121 class C : A, B {} 5122 5123 static assert(is(ImplicitConversionTargets!(C) == AliasSeq!(Object, A, B))); 5124 static assert(is(ImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B))); 5125 static assert(is(ImplicitConversionTargets!(immutable C) == AliasSeq!( 5126 immutable Object, immutable A, immutable B 5127 ))); 5128 } 5129 5130 @safe unittest 5131 { 5132 static assert(is(ImplicitConversionTargets!(double)[0] == real)); 5133 static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[])); 5134 } 5135 5136 /** 5137 Is `From` implicitly convertible to `To`? 5138 */ 5139 enum bool isImplicitlyConvertible(From, To) = is(From : To); 5140 5141 /// 5142 @safe unittest 5143 { 5144 static assert( isImplicitlyConvertible!(immutable(char), char)); 5145 static assert( isImplicitlyConvertible!(const(char), char)); 5146 static assert( isImplicitlyConvertible!(char, wchar)); 5147 static assert(!isImplicitlyConvertible!(wchar, char)); 5148 5149 static assert(!isImplicitlyConvertible!(const(ushort), ubyte)); 5150 static assert(!isImplicitlyConvertible!(const(uint), ubyte)); 5151 static assert(!isImplicitlyConvertible!(const(ulong), ubyte)); 5152 5153 static assert(!isImplicitlyConvertible!(const(char)[], string)); 5154 static assert( isImplicitlyConvertible!(string, const(char)[])); 5155 } 5156 5157 /** 5158 Returns `true` iff a value of type `Rhs` can be assigned to a variable of 5159 type `Lhs`. 5160 5161 `isAssignable` returns whether both an lvalue and rvalue can be assigned. 5162 5163 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`. 5164 */ 5165 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs); 5166 5167 /// 5168 @safe unittest 5169 { 5170 static assert( isAssignable!(long, int)); 5171 static assert(!isAssignable!(int, long)); 5172 static assert( isAssignable!(const(char)[], string)); 5173 static assert(!isAssignable!(string, char[])); 5174 5175 // int is assignable to int 5176 static assert( isAssignable!int); 5177 5178 // immutable int is not assignable to immutable int 5179 static assert(!isAssignable!(immutable int)); 5180 } 5181 5182 // ditto 5183 private enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; }); 5184 5185 // ditto 5186 private enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; }); 5187 5188 @safe unittest 5189 { 5190 static assert(!isAssignable!(immutable int, int)); 5191 static assert( isAssignable!(int, immutable int)); 5192 5193 static assert(!isAssignable!(inout int, int)); 5194 static assert( isAssignable!(int, inout int)); 5195 static assert(!isAssignable!(inout int)); 5196 5197 static assert( isAssignable!(shared int, int)); 5198 static assert( isAssignable!(int, shared int)); 5199 static assert( isAssignable!(shared int)); 5200 5201 static assert( isAssignable!(void[1], void[1])); 5202 5203 struct S { @disable this(); this(int n){} } 5204 static assert( isAssignable!(S, S)); 5205 5206 struct S2 { this(int n){} } 5207 static assert( isAssignable!(S2, S2)); 5208 static assert(!isAssignable!(S2, int)); 5209 5210 struct S3 { @disable void opAssign(); } 5211 static assert( isAssignable!(S3, S3)); 5212 5213 struct S3X { @disable void opAssign(S3X); } 5214 static assert(!isAssignable!(S3X, S3X)); 5215 5216 struct S4 { void opAssign(int); } 5217 static assert( isAssignable!(S4, S4)); 5218 static assert( isAssignable!(S4, int)); 5219 static assert( isAssignable!(S4, immutable int)); 5220 5221 struct S5 { @disable this(); @disable this(this); } 5222 5223 // `-preview=in` is enabled 5224 static if (!is(typeof(mixin(q{(in ref int a) => a})))) 5225 { 5226 struct S6 { void opAssign(in S5); } 5227 5228 static assert(isRvalueAssignable!(S6, S5)); 5229 static assert(isLvalueAssignable!(S6, S5)); 5230 static assert(isAssignable!(S6, S5)); 5231 static assert(isAssignable!(S6, immutable S5)); 5232 } 5233 else 5234 { 5235 mixin(q{ struct S6 { void opAssign(in ref S5); } }); 5236 5237 static assert(!isRvalueAssignable!(S6, S5)); 5238 static assert( isLvalueAssignable!(S6, S5)); 5239 static assert(!isAssignable!(S6, S5)); 5240 static assert( isLvalueAssignable!(S6, immutable S5)); 5241 } 5242 } 5243 5244 5245 // Equivalent with TypeStruct::isAssignable in compiler code. 5246 package template isBlitAssignable(T) 5247 { 5248 static if (is(OriginalType!T U) && !is(T == U)) 5249 { 5250 enum isBlitAssignable = isBlitAssignable!U; 5251 } 5252 else static if (isStaticArray!T && is(T == E[n], E, size_t n)) 5253 // Workaround for issue 11499 : isStaticArray!T should not be necessary. 5254 { 5255 enum isBlitAssignable = isBlitAssignable!E; 5256 } 5257 else static if (is(T == struct) || is(T == union)) 5258 { 5259 enum isBlitAssignable = isMutable!T && 5260 { 5261 size_t offset = 0; 5262 bool assignable = true; 5263 foreach (i, F; FieldTypeTuple!T) 5264 { 5265 static if (i == 0) 5266 { 5267 } 5268 else 5269 { 5270 if (T.tupleof[i].offsetof == offset) 5271 { 5272 if (assignable) 5273 continue; 5274 } 5275 else 5276 { 5277 if (!assignable) 5278 return false; 5279 } 5280 } 5281 assignable = isBlitAssignable!(typeof(T.tupleof[i])); 5282 offset = T.tupleof[i].offsetof; 5283 } 5284 return assignable; 5285 }(); 5286 } 5287 else 5288 enum isBlitAssignable = isMutable!T; 5289 } 5290 5291 @safe unittest 5292 { 5293 static assert( isBlitAssignable!int); 5294 static assert(!isBlitAssignable!(const int)); 5295 5296 class C{ const int i; } 5297 static assert( isBlitAssignable!C); 5298 5299 struct S1{ int i; } 5300 struct S2{ const int i; } 5301 static assert( isBlitAssignable!S1); 5302 static assert(!isBlitAssignable!S2); 5303 5304 struct S3X { union { int x; int y; } } 5305 struct S3Y { union { int x; const int y; } } 5306 struct S3Z { union { const int x; const int y; } } 5307 static assert( isBlitAssignable!(S3X)); 5308 static assert( isBlitAssignable!(S3Y)); 5309 static assert(!isBlitAssignable!(S3Z)); 5310 static assert(!isBlitAssignable!(const S3X)); 5311 static assert(!isBlitAssignable!(inout S3Y)); 5312 static assert(!isBlitAssignable!(immutable S3Z)); 5313 static assert( isBlitAssignable!(S3X[3])); 5314 static assert( isBlitAssignable!(S3Y[3])); 5315 static assert(!isBlitAssignable!(S3Z[3])); 5316 enum ES3X : S3X { a = S3X() } 5317 enum ES3Y : S3Y { a = S3Y() } 5318 enum ES3Z : S3Z { a = S3Z() } 5319 static assert( isBlitAssignable!(ES3X)); 5320 static assert( isBlitAssignable!(ES3Y)); 5321 static assert(!isBlitAssignable!(ES3Z)); 5322 static assert(!isBlitAssignable!(const ES3X)); 5323 static assert(!isBlitAssignable!(inout ES3Y)); 5324 static assert(!isBlitAssignable!(immutable ES3Z)); 5325 static assert( isBlitAssignable!(ES3X[3])); 5326 static assert( isBlitAssignable!(ES3Y[3])); 5327 static assert(!isBlitAssignable!(ES3Z[3])); 5328 5329 union U1X { int x; int y; } 5330 union U1Y { int x; const int y; } 5331 union U1Z { const int x; const int y; } 5332 static assert( isBlitAssignable!(U1X)); 5333 static assert( isBlitAssignable!(U1Y)); 5334 static assert(!isBlitAssignable!(U1Z)); 5335 static assert(!isBlitAssignable!(const U1X)); 5336 static assert(!isBlitAssignable!(inout U1Y)); 5337 static assert(!isBlitAssignable!(immutable U1Z)); 5338 static assert( isBlitAssignable!(U1X[3])); 5339 static assert( isBlitAssignable!(U1Y[3])); 5340 static assert(!isBlitAssignable!(U1Z[3])); 5341 enum EU1X : U1X { a = U1X() } 5342 enum EU1Y : U1Y { a = U1Y() } 5343 enum EU1Z : U1Z { a = U1Z() } 5344 static assert( isBlitAssignable!(EU1X)); 5345 static assert( isBlitAssignable!(EU1Y)); 5346 static assert(!isBlitAssignable!(EU1Z)); 5347 static assert(!isBlitAssignable!(const EU1X)); 5348 static assert(!isBlitAssignable!(inout EU1Y)); 5349 static assert(!isBlitAssignable!(immutable EU1Z)); 5350 static assert( isBlitAssignable!(EU1X[3])); 5351 static assert( isBlitAssignable!(EU1Y[3])); 5352 static assert(!isBlitAssignable!(EU1Z[3])); 5353 5354 struct SA 5355 { 5356 @property int[3] foo() { return [1,2,3]; } 5357 alias foo this; 5358 const int x; // SA is not blit assignable 5359 } 5360 static assert(!isStaticArray!SA); 5361 static assert(!isBlitAssignable!(SA[3])); 5362 } 5363 5364 5365 /* 5366 Works like `isImplicitlyConvertible`, except this cares only about storage 5367 classes of the arguments. 5368 */ 5369 private template isStorageClassImplicitlyConvertible(From, To) 5370 { 5371 alias Pointify(T) = void*; 5372 5373 enum isStorageClassImplicitlyConvertible = isImplicitlyConvertible!( 5374 ModifyTypePreservingTQ!(Pointify, From), 5375 ModifyTypePreservingTQ!(Pointify, To) ); 5376 } 5377 5378 @safe unittest 5379 { 5380 static assert( isStorageClassImplicitlyConvertible!( int, const int)); 5381 static assert( isStorageClassImplicitlyConvertible!(immutable int, const int)); 5382 5383 static assert(!isStorageClassImplicitlyConvertible!(const int, int)); 5384 static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int)); 5385 static assert(!isStorageClassImplicitlyConvertible!(int, shared int)); 5386 static assert(!isStorageClassImplicitlyConvertible!(shared int, int)); 5387 } 5388 5389 5390 /** 5391 Determines whether the function type `F` is covariant with `G`, i.e., 5392 functions of the type `F` can override ones of the type `G`. 5393 */ 5394 template isCovariantWith(F, G) 5395 if (is(F == function) && is(G == function) || 5396 is(F == delegate) && is(G == delegate) || 5397 isFunctionPointer!F && isFunctionPointer!G) 5398 { 5399 static if (is(F : G)) 5400 enum isCovariantWith = true; 5401 else 5402 { 5403 alias Upr = F; 5404 alias Lwr = G; 5405 5406 /* 5407 * Check for calling convention: require exact match. 5408 */ 5409 template checkLinkage() 5410 { 5411 enum ok = functionLinkage!Upr == functionLinkage!Lwr; 5412 } 5413 /* 5414 * Check for variadic parameter: require exact match. 5415 */ 5416 template checkVariadicity() 5417 { 5418 enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr; 5419 } 5420 /* 5421 * Check for function storage class: 5422 * - overrider can have narrower storage class than base 5423 */ 5424 template checkSTC() 5425 { 5426 // Note the order of arguments. The convertion order Lwr -> Upr is 5427 // correct since Upr should be semantically 'narrower' than Lwr. 5428 enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr); 5429 } 5430 /* 5431 * Check for function attributes: 5432 * - require exact match for ref and @property 5433 * - overrider can add pure and nothrow, but can't remove them 5434 * - @safe and @trusted are covariant with each other, unremovable 5435 */ 5436 template checkAttributes() 5437 { 5438 alias FA = FunctionAttribute; 5439 enum uprAtts = functionAttributes!Upr; 5440 enum lwrAtts = functionAttributes!Lwr; 5441 // 5442 enum wantExact = FA.ref_ | FA.property; 5443 enum safety = FA.safe | FA.trusted; 5444 enum ok = 5445 ( (uprAtts & wantExact) == (lwrAtts & wantExact)) && 5446 ( (uprAtts & FA.pure_ ) >= (lwrAtts & FA.pure_ )) && 5447 ( (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) && 5448 (!!(uprAtts & safety ) >= !!(lwrAtts & safety )) ; 5449 } 5450 /* 5451 * Check for return type: usual implicit convertion. 5452 */ 5453 template checkReturnType() 5454 { 5455 enum ok = is(ReturnType!Upr : ReturnType!Lwr); 5456 } 5457 /* 5458 * Check for parameters: 5459 * - require exact match for types 5460 * (cf. https://issues.dlang.org/show_bug.cgi?id=3075) 5461 * - require exact match for in, out, ref and lazy 5462 * - overrider can add scope, but can't remove 5463 */ 5464 template checkParameters() 5465 { 5466 alias STC = ParameterStorageClass; 5467 alias UprParams = Parameters!Upr; 5468 alias LwrParams = Parameters!Lwr; 5469 alias UprPSTCs = ParameterStorageClassTuple!Upr; 5470 alias LwrPSTCs = ParameterStorageClassTuple!Lwr; 5471 // 5472 template checkNext(size_t i) 5473 { 5474 static if (i < UprParams.length) 5475 { 5476 enum uprStc = UprPSTCs[i]; 5477 enum lwrStc = LwrPSTCs[i]; 5478 // 5479 enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_; 5480 enum ok = 5481 ((uprStc & wantExact ) == (lwrStc & wantExact )) && 5482 ((uprStc & STC.scope_) >= (lwrStc & STC.scope_)) && 5483 checkNext!(i + 1).ok; 5484 } 5485 else 5486 enum ok = true; // done 5487 } 5488 static if (UprParams.length == LwrParams.length) 5489 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok; 5490 else 5491 enum ok = false; 5492 } 5493 5494 /* run all the checks */ 5495 enum isCovariantWith = 5496 checkLinkage !().ok && 5497 checkVariadicity!().ok && 5498 checkSTC !().ok && 5499 checkAttributes !().ok && 5500 checkReturnType !().ok && 5501 checkParameters !().ok ; 5502 } 5503 } 5504 5505 /// 5506 @safe unittest 5507 { 5508 interface I { I clone(); } 5509 interface J { J clone(); } 5510 class C : I 5511 { 5512 override C clone() // covariant overriding of I.clone() 5513 { 5514 return new C; 5515 } 5516 } 5517 5518 // C.clone() can override I.clone(), indeed. 5519 static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone))); 5520 5521 // C.clone() can't override J.clone(); the return type C is not implicitly 5522 // convertible to J. 5523 static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone))); 5524 } 5525 5526 @safe unittest 5527 { 5528 enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g)); 5529 5530 // covariant return type 5531 interface I {} 5532 interface J : I {} 5533 interface BaseA { const(I) test(int); } 5534 interface DerivA_1 : BaseA { override const(J) test(int); } 5535 interface DerivA_2 : BaseA { override J test(int); } 5536 static assert( isCovariantWith!(DerivA_1.test, BaseA.test)); 5537 static assert( isCovariantWith!(DerivA_2.test, BaseA.test)); 5538 static assert(!isCovariantWith!(BaseA.test, DerivA_1.test)); 5539 static assert(!isCovariantWith!(BaseA.test, DerivA_2.test)); 5540 static assert( isCovariantWith!(BaseA.test, BaseA.test)); 5541 static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test)); 5542 static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test)); 5543 5544 // function, function pointer and delegate 5545 J function() derived_function; 5546 I function() base_function; 5547 J delegate() derived_delegate; 5548 I delegate() base_delegate; 5549 static assert(.isCovariantWith!(typeof(derived_function), typeof(base_function))); 5550 static assert(.isCovariantWith!(typeof(*derived_function), typeof(*base_function))); 5551 static assert(.isCovariantWith!(typeof(derived_delegate), typeof(base_delegate))); 5552 5553 // scope parameter 5554 interface BaseB { void test( int*, int*); } 5555 interface DerivB_1 : BaseB { override void test(scope int*, int*); } 5556 interface DerivB_2 : BaseB { override void test( int*, scope int*); } 5557 interface DerivB_3 : BaseB { override void test(scope int*, scope int*); } 5558 static assert( isCovariantWith!(DerivB_1.test, BaseB.test)); 5559 static assert( isCovariantWith!(DerivB_2.test, BaseB.test)); 5560 static assert( isCovariantWith!(DerivB_3.test, BaseB.test)); 5561 static assert(!isCovariantWith!(BaseB.test, DerivB_1.test)); 5562 static assert(!isCovariantWith!(BaseB.test, DerivB_2.test)); 5563 static assert(!isCovariantWith!(BaseB.test, DerivB_3.test)); 5564 5565 // function storage class 5566 interface BaseC { void test() ; } 5567 interface DerivC_1 : BaseC { override void test() const; } 5568 static assert( isCovariantWith!(DerivC_1.test, BaseC.test)); 5569 static assert(!isCovariantWith!(BaseC.test, DerivC_1.test)); 5570 5571 // increasing safety 5572 interface BaseE { void test() ; } 5573 interface DerivE_1 : BaseE { override void test() @safe ; } 5574 interface DerivE_2 : BaseE { override void test() @trusted; } 5575 static assert( isCovariantWith!(DerivE_1.test, BaseE.test)); 5576 static assert( isCovariantWith!(DerivE_2.test, BaseE.test)); 5577 static assert(!isCovariantWith!(BaseE.test, DerivE_1.test)); 5578 static assert(!isCovariantWith!(BaseE.test, DerivE_2.test)); 5579 5580 // @safe and @trusted 5581 interface BaseF 5582 { 5583 void test1() @safe; 5584 void test2() @trusted; 5585 } 5586 interface DerivF : BaseF 5587 { 5588 override void test1() @trusted; 5589 override void test2() @safe; 5590 } 5591 static assert( isCovariantWith!(DerivF.test1, BaseF.test1)); 5592 static assert( isCovariantWith!(DerivF.test2, BaseF.test2)); 5593 } 5594 5595 5596 // Needed for rvalueOf/lvalueOf because "inout on return means 5597 // inout must be on a parameter as well" 5598 private struct __InoutWorkaroundStruct{} 5599 5600 /** 5601 Creates an lvalue or rvalue of type `T` for `typeof(...)` and 5602 `__traits(compiles, ...)` purposes. No actual value is returned. 5603 5604 Params: 5605 T = The type to transform 5606 5607 Note: Trying to use returned value will result in a 5608 "Symbol Undefined" error at link time. 5609 */ 5610 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 5611 5612 /// ditto 5613 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); 5614 5615 // Note: can't put these unittests together as function overloads 5616 // aren't allowed inside functions. 5617 /// 5618 @system unittest 5619 { 5620 static int f(int); 5621 static assert(is(typeof(f(rvalueOf!int)) == int)); 5622 } 5623 5624 /// 5625 @system unittest 5626 { 5627 static bool f(ref int); 5628 static assert(is(typeof(f(lvalueOf!int)) == bool)); 5629 } 5630 5631 @system unittest 5632 { 5633 void needLvalue(T)(ref T); 5634 static struct S { } 5635 int i; 5636 struct Nested { void f() { ++i; } } 5637 static foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object)) 5638 { 5639 static assert(!__traits(compiles, needLvalue(rvalueOf!T))); 5640 static assert( __traits(compiles, needLvalue(lvalueOf!T))); 5641 static assert(is(typeof(rvalueOf!T) == T)); 5642 static assert(is(typeof(lvalueOf!T) == T)); 5643 } 5644 5645 static assert(!__traits(compiles, rvalueOf!int = 1)); 5646 static assert( __traits(compiles, lvalueOf!byte = 127)); 5647 static assert(!__traits(compiles, lvalueOf!byte = 128)); 5648 } 5649 5650 5651 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 5652 // SomethingTypeOf 5653 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 5654 5655 private template AliasThisTypeOf(T) 5656 { 5657 alias members = __traits(getAliasThis, T); 5658 5659 static if (members.length == 1) 5660 { 5661 alias AliasThisTypeOf = typeof(__traits(getMember, T.init, members[0])); 5662 } 5663 else 5664 static assert(0, T.stringof~" does not have alias this type"); 5665 } 5666 5667 /* 5668 */ 5669 template BooleanTypeOf(T) 5670 { 5671 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) 5672 alias X = BooleanTypeOf!AT; 5673 else 5674 alias X = OriginalType!T; 5675 5676 static if (is(immutable X == immutable bool)) 5677 { 5678 alias BooleanTypeOf = X; 5679 } 5680 else 5681 static assert(0, T.stringof~" is not boolean type"); 5682 } 5683 5684 @safe unittest 5685 { 5686 // unexpected failure, maybe dmd type-merging bug 5687 static foreach (T; AliasSeq!bool) 5688 static foreach (Q; TypeQualifierList) 5689 { 5690 static assert( is(Q!T == BooleanTypeOf!( Q!T ))); 5691 static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) ))); 5692 } 5693 5694 static foreach (T; AliasSeq!(void, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList)) 5695 static foreach (Q; TypeQualifierList) 5696 { 5697 static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof); 5698 static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) ))); 5699 } 5700 } 5701 5702 @safe unittest 5703 { 5704 struct B 5705 { 5706 bool val; 5707 alias val this; 5708 } 5709 struct S 5710 { 5711 B b; 5712 alias b this; 5713 } 5714 static assert(is(BooleanTypeOf!B == bool)); 5715 static assert(is(BooleanTypeOf!S == bool)); 5716 } 5717 5718 /* 5719 */ 5720 template IntegralTypeOf(T) 5721 { 5722 import std.meta : staticIndexOf; 5723 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) 5724 alias X = IntegralTypeOf!AT; 5725 else 5726 alias X = OriginalType!T; 5727 5728 static if (staticIndexOf!(Unqual!X, IntegralTypeList) >= 0) 5729 { 5730 alias IntegralTypeOf = X; 5731 } 5732 else 5733 static assert(0, T.stringof~" is not an integral type"); 5734 } 5735 5736 @safe unittest 5737 { 5738 static foreach (T; IntegralTypeList) 5739 static foreach (Q; TypeQualifierList) 5740 { 5741 static assert( is(Q!T == IntegralTypeOf!( Q!T ))); 5742 static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) ))); 5743 } 5744 5745 static foreach (T; AliasSeq!(void, bool, FloatingPointTypeList, 5746 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList)) 5747 static foreach (Q; TypeQualifierList) 5748 { 5749 static assert(!is(IntegralTypeOf!( Q!T ))); 5750 static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) ))); 5751 } 5752 } 5753 5754 /* 5755 */ 5756 template FloatingPointTypeOf(T) 5757 { 5758 import std.meta : staticIndexOf; 5759 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) 5760 alias X = FloatingPointTypeOf!AT; 5761 else 5762 alias X = OriginalType!T; 5763 5764 static if (staticIndexOf!(Unqual!X, FloatingPointTypeList) >= 0) 5765 { 5766 alias FloatingPointTypeOf = X; 5767 } 5768 else 5769 static assert(0, T.stringof~" is not a floating point type"); 5770 } 5771 5772 @safe unittest 5773 { 5774 static foreach (T; FloatingPointTypeList) 5775 static foreach (Q; TypeQualifierList) 5776 { 5777 static assert( is(Q!T == FloatingPointTypeOf!( Q!T ))); 5778 static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) ))); 5779 } 5780 5781 static foreach (T; AliasSeq!(void, bool, IntegralTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList)) 5782 static foreach (Q; TypeQualifierList) 5783 { 5784 static assert(!is(FloatingPointTypeOf!( Q!T ))); 5785 static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) ))); 5786 } 5787 } 5788 5789 /* 5790 */ 5791 template NumericTypeOf(T) 5792 { 5793 static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X)) 5794 { 5795 alias NumericTypeOf = X; 5796 } 5797 else 5798 static assert(0, T.stringof~" is not a numeric type"); 5799 } 5800 5801 @safe unittest 5802 { 5803 static foreach (T; NumericTypeList) 5804 static foreach (Q; TypeQualifierList) 5805 { 5806 static assert( is(Q!T == NumericTypeOf!( Q!T ))); 5807 static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) ))); 5808 } 5809 5810 static foreach (T; AliasSeq!(void, bool, CharTypeList, /*ImaginaryTypeList, ComplexTypeList*/)) 5811 static foreach (Q; TypeQualifierList) 5812 { 5813 static assert(!is(NumericTypeOf!( Q!T ))); 5814 static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) ))); 5815 } 5816 } 5817 5818 /* 5819 */ 5820 template UnsignedTypeOf(T) 5821 { 5822 import std.meta : staticIndexOf; 5823 static if (is(IntegralTypeOf!T X) && 5824 staticIndexOf!(Unqual!X, UnsignedIntTypeList) >= 0) 5825 alias UnsignedTypeOf = X; 5826 else 5827 static assert(0, T.stringof~" is not an unsigned type."); 5828 } 5829 5830 /* 5831 */ 5832 template SignedTypeOf(T) 5833 { 5834 import std.meta : staticIndexOf; 5835 static if (is(IntegralTypeOf!T X) && 5836 staticIndexOf!(Unqual!X, SignedIntTypeList) >= 0) 5837 alias SignedTypeOf = X; 5838 else static if (is(FloatingPointTypeOf!T X)) 5839 alias SignedTypeOf = X; 5840 else 5841 static assert(0, T.stringof~" is not an signed type."); 5842 } 5843 5844 /* 5845 */ 5846 template CharTypeOf(T) 5847 { 5848 import std.meta : staticIndexOf; 5849 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) 5850 alias X = CharTypeOf!AT; 5851 else 5852 alias X = OriginalType!T; 5853 5854 static if (staticIndexOf!(Unqual!X, CharTypeList) >= 0) 5855 { 5856 alias CharTypeOf = X; 5857 } 5858 else 5859 static assert(0, T.stringof~" is not a character type"); 5860 } 5861 5862 @safe unittest 5863 { 5864 static foreach (T; CharTypeList) 5865 static foreach (Q; TypeQualifierList) 5866 { 5867 static assert( is(CharTypeOf!( Q!T ))); 5868 static assert( is(CharTypeOf!( SubTypeOf!(Q!T) ))); 5869 } 5870 5871 static foreach (T; AliasSeq!(void, bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/)) 5872 static foreach (Q; TypeQualifierList) 5873 { 5874 static assert(!is(CharTypeOf!( Q!T ))); 5875 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) ))); 5876 } 5877 5878 static foreach (T; AliasSeq!(string, wstring, dstring, char[4])) 5879 static foreach (Q; TypeQualifierList) 5880 { 5881 static assert(!is(CharTypeOf!( Q!T ))); 5882 static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) ))); 5883 } 5884 } 5885 5886 /* 5887 */ 5888 template StaticArrayTypeOf(T) 5889 { 5890 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) 5891 alias X = StaticArrayTypeOf!AT; 5892 else 5893 alias X = OriginalType!T; 5894 5895 static if (is(X : E[n], E, size_t n)) 5896 alias StaticArrayTypeOf = X; 5897 else 5898 static assert(0, T.stringof~" is not a static array type"); 5899 } 5900 5901 @safe unittest 5902 { 5903 static foreach (T; AliasSeq!(bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/)) 5904 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf)) 5905 { 5906 static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) )); 5907 5908 static foreach (P; TypeQualifierList) 5909 { // SubTypeOf cannot have inout type 5910 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) )); 5911 } 5912 } 5913 5914 static foreach (T; AliasSeq!void) 5915 static foreach (Q; AliasSeq!TypeQualifierList) 5916 { 5917 static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) )); 5918 } 5919 } 5920 5921 /* 5922 */ 5923 template DynamicArrayTypeOf(T) 5924 { 5925 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) 5926 alias X = DynamicArrayTypeOf!AT; 5927 else 5928 alias X = OriginalType!T; 5929 5930 static if (is(Unqual!X : E[], E) && !is(typeof({ enum n = X.length; }))) 5931 { 5932 alias DynamicArrayTypeOf = X; 5933 } 5934 else 5935 static assert(0, T.stringof~" is not a dynamic array"); 5936 } 5937 5938 @safe unittest 5939 { 5940 static foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/)) 5941 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf)) 5942 { 5943 static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) )); 5944 static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) )); 5945 5946 static foreach (P; AliasSeq!(MutableOf, ConstOf, ImmutableOf)) 5947 { 5948 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) )); 5949 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) )); 5950 } 5951 } 5952 5953 static assert(!is(DynamicArrayTypeOf!(int[3]))); 5954 static assert(!is(DynamicArrayTypeOf!(void[3]))); 5955 static assert(!is(DynamicArrayTypeOf!(typeof(null)))); 5956 } 5957 5958 /* 5959 */ 5960 template ArrayTypeOf(T) 5961 { 5962 static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X)) 5963 { 5964 alias ArrayTypeOf = X; 5965 } 5966 else 5967 static assert(0, T.stringof~" is not an array type"); 5968 } 5969 5970 /* 5971 * Converts strings and string-like types to the corresponding dynamic array of characters. 5972 * Params: 5973 * T = one of the following: 5974 * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const` 5975 * (`shared` is rejected) 5976 * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const` 5977 * (`shared` is rejected) 5978 * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3) 5979 * 5980 * Other cases are rejected with a compile time error. 5981 * `typeof(null)` is rejected. 5982 * 5983 * Returns: 5984 * The result of `[]` applied to the qualified character type. 5985 */ 5986 template StringTypeOf(T) 5987 { 5988 static if (is(T == typeof(null))) 5989 { 5990 // It is impossible to determine exact string type from typeof(null) - 5991 // it means that StringTypeOf!(typeof(null)) is undefined. 5992 // Then this behavior is convenient for template constraint. 5993 static assert(0, T.stringof~" is not a string type"); 5994 } 5995 else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[])) 5996 { 5997 static if (is(T : U[], U)) 5998 alias StringTypeOf = U[]; 5999 else 6000 static assert(0); 6001 } 6002 else 6003 static assert(0, T.stringof~" is not a string type"); 6004 } 6005 6006 @safe unittest 6007 { 6008 static foreach (T; CharTypeList) 6009 static foreach (Q; AliasSeq!(MutableOf, ConstOf, ImmutableOf, InoutOf)) 6010 { 6011 static assert(is(Q!T[] == StringTypeOf!( Q!T[] ))); 6012 6013 static if (!__traits(isSame, Q, InoutOf)) 6014 {{ 6015 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) ))); 6016 6017 alias Str = Q!T[]; 6018 class C(S) { S val; alias val this; } 6019 static assert(is(StringTypeOf!(C!Str) == Str)); 6020 }} 6021 } 6022 6023 static foreach (T; CharTypeList) 6024 static foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf)) 6025 { 6026 static assert(!is(StringTypeOf!( Q!T[] ))); 6027 } 6028 } 6029 6030 @safe unittest 6031 { 6032 static assert(is(StringTypeOf!(char[4]) == char[])); 6033 6034 struct S 6035 { 6036 string s; 6037 alias s this; 6038 } 6039 6040 struct T 6041 { 6042 S s; 6043 alias s this; 6044 } 6045 6046 static assert(is(StringTypeOf!S == string)); 6047 static assert(is(StringTypeOf!T == string)); 6048 } 6049 6050 /* 6051 */ 6052 template AssocArrayTypeOf(T) 6053 { 6054 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) 6055 alias X = AssocArrayTypeOf!AT; 6056 else 6057 alias X = OriginalType!T; 6058 6059 static if (is(Unqual!X : V[K], K, V)) 6060 { 6061 alias AssocArrayTypeOf = X; 6062 } 6063 else 6064 static assert(0, T.stringof~" is not an associative array type"); 6065 } 6066 6067 @safe unittest 6068 { 6069 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/)) 6070 static foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf)) 6071 static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf)) 6072 static foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf)) 6073 { 6074 static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) )); 6075 } 6076 6077 static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/)) 6078 static foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf)) 6079 static foreach (P; AliasSeq!TypeQualifierList) 6080 static foreach (Q; AliasSeq!TypeQualifierList) 6081 static foreach (R; AliasSeq!TypeQualifierList) 6082 { 6083 static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) )); 6084 } 6085 } 6086 6087 /* 6088 */ 6089 template BuiltinTypeOf(T) 6090 { 6091 static if (is(T : void)) alias BuiltinTypeOf = void; 6092 else static if (is(BooleanTypeOf!T X)) alias BuiltinTypeOf = X; 6093 else static if (is(IntegralTypeOf!T X)) alias BuiltinTypeOf = X; 6094 else static if (is(FloatingPointTypeOf!T X))alias BuiltinTypeOf = X; 6095 else static if (is(T : const(ireal))) alias BuiltinTypeOf = ireal; //TODO 6096 else static if (is(T : const(creal))) alias BuiltinTypeOf = creal; //TODO 6097 else static if (is(CharTypeOf!T X)) alias BuiltinTypeOf = X; 6098 else static if (is(ArrayTypeOf!T X)) alias BuiltinTypeOf = X; 6099 else static if (is(AssocArrayTypeOf!T X)) alias BuiltinTypeOf = X; 6100 else static assert(0); 6101 } 6102 6103 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 6104 // isSomething 6105 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 6106 6107 /** 6108 * Detect whether `T` is a built-in boolean type. 6109 */ 6110 enum bool isBoolean(T) = __traits(isUnsigned, T) && is(BooleanTypeOf!T); 6111 6112 /// 6113 @safe unittest 6114 { 6115 static assert( isBoolean!bool); 6116 enum EB : bool { a = true } 6117 static assert( isBoolean!EB); 6118 static assert(!isBoolean!(SubTypeOf!bool)); 6119 } 6120 6121 @safe unittest 6122 { 6123 static struct S(T) 6124 { 6125 T t; 6126 alias t this; 6127 } 6128 static assert(!isIntegral!(S!bool)); 6129 } 6130 6131 /** 6132 * Detect whether `T` is a built-in integral type. Types `bool`, 6133 * `char`, `wchar`, and `dchar` are not considered integral. 6134 */ 6135 enum bool isIntegral(T) = __traits(isIntegral, T) && is(IntegralTypeOf!T); 6136 6137 /// 6138 @safe unittest 6139 { 6140 static assert( 6141 isIntegral!byte && 6142 isIntegral!short && 6143 isIntegral!int && 6144 isIntegral!long && 6145 isIntegral!(const(long)) && 6146 isIntegral!(immutable(long)) 6147 ); 6148 6149 static assert( 6150 !isIntegral!bool && 6151 !isIntegral!char && 6152 !isIntegral!double 6153 ); 6154 6155 // types which act as integral values do not pass 6156 struct S 6157 { 6158 int val; 6159 alias val this; 6160 } 6161 6162 static assert(!isIntegral!S); 6163 } 6164 6165 @safe unittest 6166 { 6167 static foreach (T; IntegralTypeList) 6168 { 6169 static foreach (Q; TypeQualifierList) 6170 { 6171 static assert( isIntegral!(Q!T)); 6172 static assert(!isIntegral!(SubTypeOf!(Q!T))); 6173 } 6174 } 6175 6176 static assert(!isIntegral!float); 6177 6178 enum EU : uint { a = 0, b = 1, c = 2 } // base type is unsigned 6179 // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909) 6180 enum EI : int { a = -1, b = 0, c = 1 } 6181 static assert(isIntegral!EU && isUnsigned!EU && !isSigned!EU); 6182 static assert(isIntegral!EI && !isUnsigned!EI && isSigned!EI); 6183 } 6184 6185 /** 6186 * Detect whether `T` is a built-in floating point type. 6187 */ 6188 enum bool isFloatingPoint(T) = __traits(isFloating, T) && !is(T : ireal) && !is(T : creal); 6189 6190 /// 6191 @safe unittest 6192 { 6193 static assert( 6194 isFloatingPoint!float && 6195 isFloatingPoint!double && 6196 isFloatingPoint!real && 6197 isFloatingPoint!(const(real)) && 6198 isFloatingPoint!(immutable(real)) 6199 ); 6200 6201 static assert(!isFloatingPoint!int); 6202 6203 // complex and imaginary numbers do not pass 6204 static assert( 6205 !isFloatingPoint!cfloat && 6206 !isFloatingPoint!ifloat 6207 ); 6208 6209 // types which act as floating point values do not pass 6210 struct S 6211 { 6212 float val; 6213 alias val this; 6214 } 6215 6216 static assert(!isFloatingPoint!S); 6217 } 6218 6219 @safe unittest 6220 { 6221 enum EF : real { a = 1.414, b = 1.732, c = 2.236 } 6222 6223 static foreach (T; AliasSeq!(FloatingPointTypeList, EF)) 6224 { 6225 static foreach (Q; TypeQualifierList) 6226 { 6227 static assert( isFloatingPoint!(Q!T)); 6228 static assert(!isFloatingPoint!(SubTypeOf!(Q!T))); 6229 } 6230 } 6231 static foreach (T; IntegralTypeList) 6232 { 6233 static foreach (Q; TypeQualifierList) 6234 { 6235 static assert(!isFloatingPoint!(Q!T)); 6236 } 6237 } 6238 } 6239 6240 // https://issues.dlang.org/show_bug.cgi?id=17195 6241 @safe unittest 6242 { 6243 static assert(!isFloatingPoint!cfloat); 6244 static assert(!isFloatingPoint!cdouble); 6245 static assert(!isFloatingPoint!creal); 6246 6247 static assert(!isFloatingPoint!ifloat); 6248 static assert(!isFloatingPoint!idouble); 6249 static assert(!isFloatingPoint!ireal); 6250 } 6251 6252 /** 6253 * Detect whether `T` is a built-in numeric type (integral or floating 6254 * point). 6255 */ 6256 enum bool isNumeric(T) = __traits(isArithmetic, T) && !(is(immutable T == immutable bool) || 6257 is(immutable T == immutable char) || 6258 is(immutable T == immutable wchar) || 6259 is(immutable T == immutable dchar)); 6260 6261 /// 6262 @safe unittest 6263 { 6264 static assert( 6265 isNumeric!byte && 6266 isNumeric!short && 6267 isNumeric!int && 6268 isNumeric!long && 6269 isNumeric!float && 6270 isNumeric!double && 6271 isNumeric!real && 6272 isNumeric!(const(real)) && 6273 isNumeric!(immutable(real)) 6274 ); 6275 6276 static assert( 6277 !isNumeric!void && 6278 !isNumeric!bool && 6279 !isNumeric!char && 6280 !isNumeric!wchar && 6281 !isNumeric!dchar 6282 ); 6283 6284 // types which act as numeric values do not pass 6285 struct S 6286 { 6287 int val; 6288 alias val this; 6289 } 6290 6291 static assert(!isIntegral!S); 6292 } 6293 6294 @safe unittest 6295 { 6296 static foreach (T; AliasSeq!(NumericTypeList)) 6297 { 6298 static foreach (Q; TypeQualifierList) 6299 { 6300 static assert( isNumeric!(Q!T)); 6301 static assert(!isNumeric!(SubTypeOf!(Q!T))); 6302 } 6303 } 6304 6305 static struct S(T) 6306 { 6307 T t; 6308 alias t this; 6309 } 6310 static assert(!isNumeric!(S!int)); 6311 } 6312 6313 /** 6314 * Detect whether `T` is a scalar type (a built-in numeric, character or 6315 * boolean type). 6316 */ 6317 enum bool isScalarType(T) = __traits(isScalar, T) && is(T : real); 6318 6319 /// 6320 @safe unittest 6321 { 6322 static assert(!isScalarType!void); 6323 static assert( isScalarType!(immutable(byte))); 6324 static assert( isScalarType!(immutable(ushort))); 6325 static assert( isScalarType!(immutable(int))); 6326 static assert( isScalarType!(ulong)); 6327 static assert( isScalarType!(shared(float))); 6328 static assert( isScalarType!(shared(const bool))); 6329 static assert( isScalarType!(const(char))); 6330 static assert( isScalarType!(wchar)); 6331 static assert( isScalarType!(const(dchar))); 6332 static assert( isScalarType!(const(double))); 6333 static assert( isScalarType!(const(real))); 6334 } 6335 6336 @safe unittest 6337 { 6338 static struct S(T) 6339 { 6340 T t; 6341 alias t this; 6342 } 6343 static assert(!isScalarType!(S!int)); 6344 } 6345 6346 /** 6347 * Detect whether `T` is a basic type (scalar type or void). 6348 */ 6349 enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void); 6350 6351 /// 6352 @safe unittest 6353 { 6354 static assert(isBasicType!void); 6355 static assert(isBasicType!(const(void))); 6356 static assert(isBasicType!(shared(void))); 6357 static assert(isBasicType!(immutable(void))); 6358 static assert(isBasicType!(shared const(void))); 6359 static assert(isBasicType!(shared inout(void))); 6360 static assert(isBasicType!(shared inout const(void))); 6361 static assert(isBasicType!(inout(void))); 6362 static assert(isBasicType!(inout const(void))); 6363 static assert(isBasicType!(immutable(int))); 6364 static assert(isBasicType!(shared(float))); 6365 static assert(isBasicType!(shared(const bool))); 6366 static assert(isBasicType!(const(dchar))); 6367 } 6368 6369 /** 6370 * Detect whether `T` is a built-in unsigned numeric type. 6371 */ 6372 enum bool isUnsigned(T) = __traits(isUnsigned, T) && !(is(immutable T == immutable char) || 6373 is(immutable T == immutable wchar) || 6374 is(immutable T == immutable dchar) || 6375 is(immutable T == immutable bool)); 6376 6377 /// 6378 @safe unittest 6379 { 6380 static assert( 6381 isUnsigned!uint && 6382 isUnsigned!ulong 6383 ); 6384 6385 static assert( 6386 !isUnsigned!char && 6387 !isUnsigned!int && 6388 !isUnsigned!long && 6389 !isUnsigned!char && 6390 !isUnsigned!wchar && 6391 !isUnsigned!dchar 6392 ); 6393 } 6394 6395 @safe unittest 6396 { 6397 static foreach (T; AliasSeq!(UnsignedIntTypeList)) 6398 { 6399 static foreach (Q; TypeQualifierList) 6400 { 6401 static assert( isUnsigned!(Q!T)); 6402 static assert(!isUnsigned!(SubTypeOf!(Q!T))); 6403 } 6404 } 6405 6406 static struct S(T) 6407 { 6408 T t; 6409 alias t this; 6410 } 6411 static assert(!isUnsigned!(S!uint)); 6412 } 6413 6414 /** 6415 * Detect whether `T` is a built-in signed numeric type. 6416 */ 6417 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T); 6418 6419 /// 6420 @safe unittest 6421 { 6422 static assert( 6423 isSigned!int && 6424 isSigned!long 6425 ); 6426 6427 static assert( 6428 !isSigned!uint && 6429 !isSigned!ulong 6430 ); 6431 } 6432 6433 @safe unittest 6434 { 6435 enum E { e1 = 0 } 6436 static assert(isSigned!E); 6437 6438 enum Eubyte : ubyte { e1 = 0 } 6439 static assert(!isSigned!Eubyte); 6440 6441 static foreach (T; AliasSeq!(SignedIntTypeList)) 6442 { 6443 static foreach (Q; TypeQualifierList) 6444 { 6445 static assert( isSigned!(Q!T)); 6446 static assert(!isSigned!(SubTypeOf!(Q!T))); 6447 } 6448 } 6449 6450 static struct S(T) 6451 { 6452 T t; 6453 alias t this; 6454 } 6455 static assert(!isSigned!(S!uint)); 6456 } 6457 6458 // https://issues.dlang.org/show_bug.cgi?id=17196 6459 @safe unittest 6460 { 6461 static assert(isUnsigned!bool == false); 6462 static assert(isSigned!bool == false); 6463 } 6464 6465 /** 6466 * Detect whether `T` is one of the built-in character types. 6467 * 6468 * The built-in char types are any of `char`, `wchar` or `dchar`, with 6469 * or without qualifiers. 6470 */ 6471 enum bool isSomeChar(T) = __traits(isUnsigned, T) && is(CharTypeOf!T); 6472 6473 /// 6474 @safe unittest 6475 { 6476 //Char types 6477 static assert( isSomeChar!char); 6478 static assert( isSomeChar!wchar); 6479 static assert( isSomeChar!dchar); 6480 static assert( isSomeChar!(typeof('c'))); 6481 static assert( isSomeChar!(immutable char)); 6482 static assert( isSomeChar!(const dchar)); 6483 6484 //Non char types 6485 static assert(!isSomeChar!int); 6486 static assert(!isSomeChar!byte); 6487 static assert(!isSomeChar!string); 6488 static assert(!isSomeChar!wstring); 6489 static assert(!isSomeChar!dstring); 6490 static assert(!isSomeChar!(char[4])); 6491 } 6492 6493 @safe unittest 6494 { 6495 enum EC : char { a = 'x', b = 'y' } 6496 6497 static foreach (T; AliasSeq!(CharTypeList, EC)) 6498 { 6499 static foreach (Q; TypeQualifierList) 6500 { 6501 static assert( isSomeChar!( Q!T )); 6502 static assert(!isSomeChar!( SubTypeOf!(Q!T) )); 6503 } 6504 } 6505 6506 // alias-this types are not allowed 6507 static struct S(T) 6508 { 6509 T t; 6510 alias t this; 6511 } 6512 static assert(!isSomeChar!(S!char)); 6513 } 6514 6515 /** 6516 Detect whether `T` is one of the built-in string types. 6517 6518 The built-in string types are `Char[]`, where `Char` is any of `char`, 6519 `wchar` or `dchar`, with or without qualifiers. 6520 6521 Static arrays of characters (like `char[80]`) are not considered 6522 built-in string types. 6523 */ 6524 enum bool isSomeString(T) = is(StringTypeOf!T) && !isAggregateType!T && !isStaticArray!T && !is(T == enum); 6525 6526 /// 6527 @safe unittest 6528 { 6529 //String types 6530 static assert( isSomeString!string); 6531 static assert( isSomeString!(wchar[])); 6532 static assert( isSomeString!(dchar[])); 6533 static assert( isSomeString!(typeof("aaa"))); 6534 static assert( isSomeString!(const(char)[])); 6535 6536 //Non string types 6537 static assert(!isSomeString!int); 6538 static assert(!isSomeString!(int[])); 6539 static assert(!isSomeString!(byte[])); 6540 static assert(!isSomeString!(typeof(null))); 6541 static assert(!isSomeString!(char[4])); 6542 6543 enum ES : string { a = "aaa", b = "bbb" } 6544 static assert(!isSomeString!ES); 6545 6546 static struct Stringish 6547 { 6548 string str; 6549 alias str this; 6550 } 6551 static assert(!isSomeString!Stringish); 6552 } 6553 6554 @safe unittest 6555 { 6556 static foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring)) 6557 { 6558 static assert( isSomeString!( T )); 6559 static assert(!isSomeString!(SubTypeOf!(T))); 6560 } 6561 } 6562 6563 /** 6564 * Detect whether type `T` is a narrow string. 6565 * 6566 * All arrays that use char, wchar, and their qualified versions are narrow 6567 * strings. (Those include string and wstring). 6568 */ 6569 enum bool isNarrowString(T) = isSomeString!T && !is(T : const dchar[]); 6570 6571 /// 6572 @safe unittest 6573 { 6574 static assert(isNarrowString!string); 6575 static assert(isNarrowString!wstring); 6576 static assert(isNarrowString!(char[])); 6577 static assert(isNarrowString!(wchar[])); 6578 6579 static assert(!isNarrowString!dstring); 6580 static assert(!isNarrowString!(dchar[])); 6581 6582 static assert(!isNarrowString!(typeof(null))); 6583 static assert(!isNarrowString!(char[4])); 6584 6585 enum ES : string { a = "aaa", b = "bbb" } 6586 static assert(!isNarrowString!ES); 6587 6588 static struct Stringish 6589 { 6590 string str; 6591 alias str this; 6592 } 6593 static assert(!isNarrowString!Stringish); 6594 } 6595 6596 @safe unittest 6597 { 6598 static foreach (T; AliasSeq!(char[], string, wstring)) 6599 { 6600 static foreach (Q; AliasSeq!(MutableOf, ConstOf, ImmutableOf)/*TypeQualifierList*/) 6601 { 6602 static assert( isNarrowString!( Q!T )); 6603 static assert(!isNarrowString!( SubTypeOf!(Q!T) )); 6604 } 6605 } 6606 6607 static foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4])) 6608 { 6609 static foreach (Q; TypeQualifierList) 6610 { 6611 static assert(!isNarrowString!( Q!T )); 6612 static assert(!isNarrowString!( SubTypeOf!(Q!T) )); 6613 } 6614 } 6615 } 6616 6617 /** 6618 * Detects whether `T` is a comparable type. Basic types and structs and 6619 * classes that implement opCmp are ordering comparable. 6620 */ 6621 enum bool isOrderingComparable(T) = ifTestable!(T, unaryFun!"a < a"); 6622 6623 /// 6624 @safe unittest 6625 { 6626 static assert(isOrderingComparable!int); 6627 static assert(isOrderingComparable!string); 6628 static assert(!isOrderingComparable!creal); 6629 6630 static struct Foo {} 6631 static assert(!isOrderingComparable!Foo); 6632 6633 static struct Bar 6634 { 6635 int a; 6636 auto opCmp(Bar b1) const { return a - b1.a; } 6637 } 6638 6639 Bar b1 = Bar(5); 6640 Bar b2 = Bar(7); 6641 assert(isOrderingComparable!Bar && b2 > b1); 6642 } 6643 6644 /// ditto 6645 enum bool isEqualityComparable(T) = ifTestable!(T, unaryFun!"a == a"); 6646 6647 @safe unittest 6648 { 6649 static assert(isEqualityComparable!int); 6650 static assert(isEqualityComparable!string); 6651 static assert(!isEqualityComparable!void); 6652 6653 struct Foo {} 6654 static assert(isEqualityComparable!Foo); 6655 6656 struct Bar 6657 { 6658 int a; 6659 auto opEquals(Bar b1) const { return a == b1.a; } 6660 } 6661 6662 Bar b1 = Bar(5); 6663 Bar b2 = Bar(5); 6664 Bar b3 = Bar(7); 6665 static assert(isEqualityComparable!Bar); 6666 assert(b1 == b2); 6667 assert(b1 != b3); 6668 } 6669 6670 version (TestComplex) 6671 deprecated 6672 @safe unittest 6673 { 6674 static assert(isEqualityComparable!creal); 6675 } 6676 6677 /** 6678 $(RED Warning: This trait will be deprecated as soon as it is no longer used 6679 in Phobos. For a function parameter to safely accept a type 6680 that implicitly converts to string as a string, the conversion 6681 needs to happen at the callsite; otherwise, the conversion is 6682 done inside the function, and in many cases, that means that 6683 local memory is sliced (e.g. if a static array is passed to 6684 the function, then it's copied, and the resulting dynamic 6685 array will be a slice of a local variable). So, if the 6686 resulting string escapes the function, the string refers to 6687 invalid memory, and accessing it would mean accessing invalid 6688 memory. As such, the only safe way for a function to accept 6689 types that implicitly convert to string is for the implicit 6690 conversion to be done at the callsite, and that can only occur 6691 if the parameter is explicitly typed as an array, whereas 6692 using isConvertibleToString in a template constraint would 6693 result in the conversion being done inside the function. As 6694 such, isConvertibleToString is inherently unsafe and is going 6695 to be deprecated.) 6696 6697 Detect whether `T` is a struct, static array, or enum that is implicitly 6698 convertible to a string. 6699 */ 6700 template isConvertibleToString(T) 6701 { 6702 enum isConvertibleToString = 6703 (isAggregateType!T || isStaticArray!T || is(T == enum)) 6704 && is(StringTypeOf!T); 6705 } 6706 6707 /// 6708 @safe unittest 6709 { 6710 static struct AliasedString 6711 { 6712 string s; 6713 alias s this; 6714 } 6715 6716 enum StringEnum { a = "foo" } 6717 6718 assert(!isConvertibleToString!string); 6719 assert(isConvertibleToString!AliasedString); 6720 assert(isConvertibleToString!StringEnum); 6721 assert(isConvertibleToString!(char[25])); 6722 assert(!isConvertibleToString!(char[])); 6723 } 6724 6725 // https://issues.dlang.org/show_bug.cgi?id=16573 6726 @safe unittest 6727 { 6728 enum I : int { foo = 1 } 6729 enum S : string { foo = "foo" } 6730 assert(!isConvertibleToString!I); 6731 assert(isConvertibleToString!S); 6732 } 6733 6734 package template convertToString(T) 6735 { 6736 static if (isConvertibleToString!T) 6737 alias convertToString = StringTypeOf!T; 6738 else 6739 alias convertToString = T; 6740 } 6741 6742 /** 6743 * Detect whether type `T` is a string that will be autodecoded. 6744 * 6745 * Given a type `S` that is one of: 6746 * $(OL 6747 * $(LI `const(char)[]`) 6748 * $(LI `const(wchar)[]`) 6749 * ) 6750 * Type `T` can be one of: 6751 * $(OL 6752 * $(LI `S`) 6753 * $(LI implicitly convertible to `T`) 6754 * $(LI an enum with a base type `T`) 6755 * $(LI an aggregate with a base type `T`) 6756 * ) 6757 * with the proviso that `T` cannot be a static array. 6758 * 6759 * Params: 6760 * T = type to be tested 6761 * 6762 * Returns: 6763 * true if T represents a string that is subject to autodecoding 6764 * 6765 * See Also: 6766 * $(LREF isNarrowString) 6767 */ 6768 template isAutodecodableString(T) 6769 { 6770 import std.range.primitives : autodecodeStrings; 6771 6772 enum isAutodecodableString = autodecodeStrings && 6773 (is(T : const char[]) || is(T : const wchar[])) && !isStaticArray!T; 6774 } 6775 6776 /// 6777 @safe unittest 6778 { 6779 static struct Stringish 6780 { 6781 string s; 6782 alias s this; 6783 } 6784 static assert(isAutodecodableString!wstring); 6785 static assert(isAutodecodableString!Stringish); 6786 static assert(!isAutodecodableString!dstring); 6787 6788 enum E : const(char)[3] { X = "abc" } 6789 enum F : const(char)[] { X = "abc" } 6790 enum G : F { X = F.init } 6791 6792 static assert(isAutodecodableString!(char[])); 6793 static assert(!isAutodecodableString!(E)); 6794 static assert(isAutodecodableString!(F)); 6795 static assert(isAutodecodableString!(G)); 6796 6797 struct Stringish2 6798 { 6799 Stringish s; 6800 alias s this; 6801 } 6802 6803 enum H : Stringish { X = Stringish() } 6804 enum I : Stringish2 { X = Stringish2() } 6805 6806 static assert(isAutodecodableString!(H)); 6807 static assert(isAutodecodableString!(I)); 6808 } 6809 6810 /** 6811 * Detect whether type `T` is a static array. 6812 */ 6813 enum bool isStaticArray(T) = __traits(isStaticArray, T); 6814 6815 /// 6816 @safe unittest 6817 { 6818 static assert( isStaticArray!(int[3])); 6819 static assert( isStaticArray!(const(int)[5])); 6820 static assert( isStaticArray!(const(int)[][5])); 6821 6822 static assert(!isStaticArray!(const(int)[])); 6823 static assert(!isStaticArray!(immutable(int)[])); 6824 static assert(!isStaticArray!(const(int)[4][])); 6825 static assert(!isStaticArray!(int[])); 6826 static assert(!isStaticArray!(int[char])); 6827 static assert(!isStaticArray!(int[1][])); 6828 static assert(!isStaticArray!(int[int])); 6829 static assert(!isStaticArray!int); 6830 } 6831 6832 @safe unittest 6833 { 6834 static foreach (T; AliasSeq!(int[51], int[][2], 6835 char[][int][11], immutable char[13u], 6836 const(real)[1], const(real)[1][1], void[0])) 6837 { 6838 static foreach (Q; TypeQualifierList) 6839 { 6840 static assert( isStaticArray!( Q!T )); 6841 static assert(!isStaticArray!( SubTypeOf!(Q!T) )); 6842 } 6843 } 6844 6845 //enum ESA : int[1] { a = [1], b = [2] } 6846 //static assert( isStaticArray!ESA); 6847 } 6848 6849 /** 6850 * Detect whether type `T` is a dynamic array. 6851 */ 6852 enum bool isDynamicArray(T) = is(DynamicArrayTypeOf!T) && !isAggregateType!T; 6853 6854 /// 6855 @safe unittest 6856 { 6857 static assert( isDynamicArray!(int[])); 6858 static assert( isDynamicArray!(string)); 6859 static assert( isDynamicArray!(long[3][])); 6860 6861 static assert(!isDynamicArray!(int[5])); 6862 static assert(!isDynamicArray!(typeof(null))); 6863 } 6864 6865 @safe unittest 6866 { 6867 import std.meta : AliasSeq; 6868 static foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][])) 6869 { 6870 static foreach (Q; TypeQualifierList) 6871 { 6872 static assert( isDynamicArray!( Q!T )); 6873 static assert(!isDynamicArray!( SubTypeOf!(Q!T) )); 6874 } 6875 } 6876 } 6877 6878 /** 6879 * Detect whether type `T` is an array (static or dynamic; for associative 6880 * arrays see $(LREF isAssociativeArray)). 6881 */ 6882 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T; 6883 6884 /// 6885 @safe unittest 6886 { 6887 static assert( isArray!(int[])); 6888 static assert( isArray!(int[5])); 6889 static assert( isArray!(string)); 6890 6891 static assert(!isArray!uint); 6892 static assert(!isArray!(uint[uint])); 6893 static assert(!isArray!(typeof(null))); 6894 } 6895 6896 @safe unittest 6897 { 6898 import std.meta : AliasSeq; 6899 static foreach (T; AliasSeq!(int[], int[5], void[])) 6900 { 6901 static foreach (Q; TypeQualifierList) 6902 { 6903 static assert( isArray!(Q!T)); 6904 static assert(!isArray!(SubTypeOf!(Q!T))); 6905 } 6906 } 6907 } 6908 6909 /** 6910 * Detect whether `T` is an associative array type 6911 */ 6912 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T); 6913 6914 @safe unittest 6915 { 6916 struct Foo 6917 { 6918 @property uint[] keys() { return null; } 6919 @property uint[] values() { return null; } 6920 } 6921 6922 static foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int])) 6923 { 6924 static foreach (Q; TypeQualifierList) 6925 { 6926 static assert( isAssociativeArray!(Q!T)); 6927 static assert(!isAssociativeArray!(SubTypeOf!(Q!T))); 6928 } 6929 } 6930 6931 static assert(!isAssociativeArray!Foo); 6932 static assert(!isAssociativeArray!int); 6933 static assert(!isAssociativeArray!(int[])); 6934 static assert(!isAssociativeArray!(typeof(null))); 6935 6936 //enum EAA : int[int] { a = [1:1], b = [2:2] } 6937 //static assert( isAssociativeArray!EAA); 6938 } 6939 6940 /** 6941 * Detect whether type `T` is a builtin type. 6942 */ 6943 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T; 6944 6945 /// 6946 @safe unittest 6947 { 6948 class C; 6949 union U; 6950 struct S; 6951 interface I; 6952 6953 static assert( isBuiltinType!void); 6954 static assert( isBuiltinType!string); 6955 static assert( isBuiltinType!(int[])); 6956 static assert( isBuiltinType!(C[string])); 6957 static assert(!isBuiltinType!C); 6958 static assert(!isBuiltinType!U); 6959 static assert(!isBuiltinType!S); 6960 static assert(!isBuiltinType!I); 6961 static assert(!isBuiltinType!(void delegate(int))); 6962 } 6963 6964 /** 6965 * Detect whether type `T` is a SIMD vector type. 6966 */ 6967 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N); 6968 6969 @safe unittest 6970 { 6971 static if (is(__vector(float[4]))) 6972 { 6973 alias SimdVec = __vector(float[4]); 6974 static assert(isSIMDVector!(__vector(float[4]))); 6975 static assert(isSIMDVector!SimdVec); 6976 } 6977 static assert(!isSIMDVector!uint); 6978 static assert(!isSIMDVector!(float[4])); 6979 } 6980 6981 /** 6982 * Detect whether type `T` is a pointer. 6983 */ 6984 enum bool isPointer(T) = is(T == U*, U) && __traits(isScalar, T); 6985 6986 @safe unittest 6987 { 6988 static foreach (T; AliasSeq!(int*, void*, char[]*)) 6989 { 6990 static foreach (Q; TypeQualifierList) 6991 { 6992 static assert( isPointer!(Q!T)); 6993 static assert(!isPointer!(SubTypeOf!(Q!T))); 6994 } 6995 } 6996 6997 static assert(!isPointer!uint); 6998 static assert(!isPointer!(uint[uint])); 6999 static assert(!isPointer!(char[])); 7000 static assert(!isPointer!(typeof(null))); 7001 } 7002 7003 /** 7004 Returns the target type of a pointer. 7005 */ 7006 alias PointerTarget(T : T*) = T; 7007 7008 /// 7009 @safe unittest 7010 { 7011 static assert(is(PointerTarget!(int*) == int)); 7012 static assert(is(PointerTarget!(void*) == void)); 7013 } 7014 7015 /** 7016 * Detect whether type `T` is an aggregate type. 7017 */ 7018 enum bool isAggregateType(T) = is(T == struct) || is(T == union) || 7019 is(T == class) || is(T == interface); 7020 7021 /// 7022 @safe unittest 7023 { 7024 class C; 7025 union U; 7026 struct S; 7027 interface I; 7028 7029 static assert( isAggregateType!C); 7030 static assert( isAggregateType!U); 7031 static assert( isAggregateType!S); 7032 static assert( isAggregateType!I); 7033 static assert(!isAggregateType!void); 7034 static assert(!isAggregateType!string); 7035 static assert(!isAggregateType!(int[])); 7036 static assert(!isAggregateType!(C[string])); 7037 static assert(!isAggregateType!(void delegate(int))); 7038 } 7039 7040 /** 7041 * Returns `true` if T can be iterated over using a `foreach` loop with 7042 * a single loop variable of automatically inferred type, regardless of how 7043 * the `foreach` loop is implemented. This includes ranges, structs/classes 7044 * that define `opApply` with a single loop variable, and builtin dynamic, 7045 * static and associative arrays. 7046 */ 7047 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} })); 7048 7049 /// 7050 @safe unittest 7051 { 7052 struct OpApply 7053 { 7054 int opApply(scope int delegate(ref uint) dg) { assert(0); } 7055 } 7056 7057 struct Range 7058 { 7059 @property uint front() { assert(0); } 7060 void popFront() { assert(0); } 7061 enum bool empty = false; 7062 } 7063 7064 static assert( isIterable!(uint[])); 7065 static assert( isIterable!OpApply); 7066 static assert( isIterable!(uint[string])); 7067 static assert( isIterable!Range); 7068 7069 static assert(!isIterable!uint); 7070 } 7071 7072 /** 7073 * Returns true if T is not const or immutable. Note that isMutable is true for 7074 * string, or immutable(char)[], because the 'head' is mutable. 7075 */ 7076 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout); 7077 7078 /// 7079 @safe unittest 7080 { 7081 static assert( isMutable!int); 7082 static assert( isMutable!string); 7083 static assert( isMutable!(shared int)); 7084 static assert( isMutable!(shared const(int)[])); 7085 7086 static assert(!isMutable!(const int)); 7087 static assert(!isMutable!(inout int)); 7088 static assert(!isMutable!(shared(const int))); 7089 static assert(!isMutable!(shared(inout int))); 7090 static assert(!isMutable!(immutable string)); 7091 } 7092 7093 /** 7094 * Returns true if T is an instance of the template S. 7095 */ 7096 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...); 7097 /// ditto 7098 template isInstanceOf(alias S, alias T) 7099 { 7100 enum impl(alias T : S!Args, Args...) = true; 7101 enum impl(alias T) = false; 7102 enum isInstanceOf = impl!T; 7103 } 7104 7105 /// 7106 @safe unittest 7107 { 7108 static struct Foo(T...) { } 7109 static struct Bar(T...) { } 7110 static struct Doo(T) { } 7111 static struct ABC(int x) { } 7112 static void fun(T)() { } 7113 template templ(T) { } 7114 7115 static assert(isInstanceOf!(Foo, Foo!int)); 7116 static assert(!isInstanceOf!(Foo, Bar!int)); 7117 static assert(!isInstanceOf!(Foo, int)); 7118 static assert(isInstanceOf!(Doo, Doo!int)); 7119 static assert(isInstanceOf!(ABC, ABC!1)); 7120 static assert(!isInstanceOf!(Foo, Foo)); 7121 static assert(isInstanceOf!(fun, fun!int)); 7122 static assert(isInstanceOf!(templ, templ!int)); 7123 } 7124 7125 /** 7126 * To use `isInstanceOf` to check the identity of a template while inside of said 7127 * template, use $(LREF TemplateOf). 7128 */ 7129 @safe unittest 7130 { 7131 static struct A(T = void) 7132 { 7133 // doesn't work as expected, only accepts A when T = void 7134 void func(B)(B b) if (isInstanceOf!(A, B)) {} 7135 7136 // correct behavior 7137 void method(B)(B b) if (isInstanceOf!(TemplateOf!(A), B)) {} 7138 } 7139 7140 A!(void) a1; 7141 A!(void) a2; 7142 A!(int) a3; 7143 7144 static assert(!__traits(compiles, a1.func(a3))); 7145 static assert( __traits(compiles, a1.method(a2))); 7146 static assert( __traits(compiles, a1.method(a3))); 7147 } 7148 7149 @safe unittest 7150 { 7151 static void fun1(T)() { } 7152 static void fun2(T)() { } 7153 template templ1(T) { } 7154 template templ2(T) { } 7155 7156 static assert(!isInstanceOf!(fun1, fun2!int)); 7157 static assert(!isInstanceOf!(templ1, templ2!int)); 7158 } 7159 7160 /** 7161 * Check whether the tuple T is an expression tuple. 7162 * An expression tuple only contains expressions. 7163 * 7164 * See_Also: $(LREF isTypeTuple). 7165 */ 7166 template isExpressions(T...) 7167 { 7168 static foreach (Ti; T) 7169 { 7170 static if (!is(typeof(isExpressions) == bool) && // not yet defined 7171 (is(Ti) || !__traits(compiles, { auto ex = Ti; }))) 7172 { 7173 enum isExpressions = false; 7174 } 7175 } 7176 static if (!is(typeof(isExpressions) == bool)) // if not yet defined 7177 { 7178 enum isExpressions = true; 7179 } 7180 } 7181 7182 /// 7183 @safe unittest 7184 { 7185 static assert(isExpressions!(1, 2.0, "a")); 7186 static assert(!isExpressions!(int, double, string)); 7187 static assert(!isExpressions!(int, 2.0, "a")); 7188 } 7189 7190 /** 7191 * Alternate name for $(LREF isExpressions), kept for legacy compatibility. 7192 */ 7193 7194 alias isExpressionTuple = isExpressions; 7195 7196 @safe unittest 7197 { 7198 void foo(); 7199 static int bar() { return 42; } 7200 immutable aa = [ 1: -1 ]; 7201 alias myint = int; 7202 7203 static assert( isExpressionTuple!(42)); 7204 static assert( isExpressionTuple!aa); 7205 static assert( isExpressionTuple!("cattywampus", 2.7, aa)); 7206 static assert( isExpressionTuple!(bar())); 7207 7208 static assert(!isExpressionTuple!isExpressionTuple); 7209 static assert(!isExpressionTuple!foo); 7210 static assert(!isExpressionTuple!( (a) { } )); 7211 static assert(!isExpressionTuple!int); 7212 static assert(!isExpressionTuple!myint); 7213 } 7214 7215 7216 /** 7217 * Check whether the tuple `T` is a type tuple. 7218 * A type tuple only contains types. 7219 * 7220 * See_Also: $(LREF isExpressions). 7221 */ 7222 template isTypeTuple(T...) 7223 { 7224 static if (T.length >= 2) 7225 enum bool isTypeTuple = isTypeTuple!(T[0 .. $/2]) && isTypeTuple!(T[$/2 .. $]); 7226 else static if (T.length == 1) 7227 enum bool isTypeTuple = is(T[0]); 7228 else 7229 enum bool isTypeTuple = true; // default 7230 } 7231 7232 /// 7233 @safe unittest 7234 { 7235 static assert(isTypeTuple!(int, float, string)); 7236 static assert(!isTypeTuple!(1, 2.0, "a")); 7237 static assert(!isTypeTuple!(1, double, string)); 7238 } 7239 7240 @safe unittest 7241 { 7242 class C {} 7243 void func(int) {} 7244 auto c = new C; 7245 enum CONST = 42; 7246 7247 static assert( isTypeTuple!int); 7248 static assert( isTypeTuple!string); 7249 static assert( isTypeTuple!C); 7250 static assert( isTypeTuple!(typeof(func))); 7251 static assert( isTypeTuple!(int, char, double)); 7252 7253 static assert(!isTypeTuple!c); 7254 static assert(!isTypeTuple!isTypeTuple); 7255 static assert(!isTypeTuple!CONST); 7256 } 7257 7258 7259 /** 7260 Detect whether symbol or type `T` is a function pointer. 7261 */ 7262 template isFunctionPointer(T...) 7263 if (T.length == 1) 7264 { 7265 static if (is(T[0] U) || is(typeof(T[0]) U)) 7266 { 7267 static if (is(U F : F*) && is(F == function)) 7268 enum bool isFunctionPointer = true; 7269 else 7270 enum bool isFunctionPointer = false; 7271 } 7272 else 7273 enum bool isFunctionPointer = false; 7274 } 7275 7276 /// 7277 @safe unittest 7278 { 7279 static void foo() {} 7280 void bar() {} 7281 7282 auto fpfoo = &foo; 7283 static assert( isFunctionPointer!fpfoo); 7284 static assert( isFunctionPointer!(void function())); 7285 7286 auto dgbar = &bar; 7287 static assert(!isFunctionPointer!dgbar); 7288 static assert(!isFunctionPointer!(void delegate())); 7289 static assert(!isFunctionPointer!foo); 7290 static assert(!isFunctionPointer!bar); 7291 7292 static assert( isFunctionPointer!((int a) {})); 7293 } 7294 7295 /** 7296 Detect whether symbol or type `T` is a delegate. 7297 */ 7298 template isDelegate(T...) 7299 if (T.length == 1) 7300 { 7301 static if (is(typeof(& T[0]) U : U*) && is(typeof(& T[0]) U == delegate)) 7302 { 7303 // T is a (nested) function symbol. 7304 enum bool isDelegate = true; 7305 } 7306 else static if (is(T[0] W) || is(typeof(T[0]) W)) 7307 { 7308 // T is an expression or a type. Take the type of it and examine. 7309 enum bool isDelegate = is(W == delegate); 7310 } 7311 else 7312 enum bool isDelegate = false; 7313 } 7314 7315 /// 7316 @safe unittest 7317 { 7318 static void sfunc() { } 7319 int x; 7320 void func() { x++; } 7321 7322 int delegate() dg; 7323 assert(isDelegate!dg); 7324 assert(isDelegate!(int delegate())); 7325 assert(isDelegate!(typeof(&func))); 7326 7327 int function() fp; 7328 assert(!isDelegate!fp); 7329 assert(!isDelegate!(int function())); 7330 assert(!isDelegate!(typeof(&sfunc))); 7331 } 7332 7333 /** 7334 Detect whether symbol or type `T` is a function, a function pointer or a delegate. 7335 7336 Params: 7337 T = The type to check 7338 Returns: 7339 A `bool` 7340 */ 7341 template isSomeFunction(T...) 7342 if (T.length == 1) 7343 { 7344 static if (is(typeof(& T[0]) U : U*) && is(U == function) || is(typeof(& T[0]) U == delegate)) 7345 { 7346 // T is a (nested) function symbol. 7347 enum bool isSomeFunction = true; 7348 } 7349 else static if (is(T[0] W) || is(typeof(T[0]) W)) 7350 { 7351 // T is an expression or a type. Take the type of it and examine. 7352 static if (is(W F : F*) && is(F == function)) 7353 enum bool isSomeFunction = true; // function pointer 7354 else 7355 enum bool isSomeFunction = is(W == function) || is(W == delegate); 7356 } 7357 else 7358 enum bool isSomeFunction = false; 7359 } 7360 7361 /// 7362 @safe unittest 7363 { 7364 static real func(ref int) { return 0; } 7365 static void prop() @property { } 7366 class C 7367 { 7368 real method(ref int) { return 0; } 7369 real prop() @property { return 0; } 7370 } 7371 auto c = new C; 7372 auto fp = &func; 7373 auto dg = &c.method; 7374 real val; 7375 7376 static assert( isSomeFunction!func); 7377 static assert( isSomeFunction!prop); 7378 static assert( isSomeFunction!(C.method)); 7379 static assert( isSomeFunction!(C.prop)); 7380 static assert( isSomeFunction!(c.prop)); 7381 static assert( isSomeFunction!(c.prop)); 7382 static assert( isSomeFunction!fp); 7383 static assert( isSomeFunction!dg); 7384 7385 static assert(!isSomeFunction!int); 7386 static assert(!isSomeFunction!val); 7387 } 7388 7389 @safe unittest 7390 { 7391 void nestedFunc() { } 7392 void nestedProp() @property { } 7393 static assert(isSomeFunction!nestedFunc); 7394 static assert(isSomeFunction!nestedProp); 7395 static assert(isSomeFunction!(real function(ref int))); 7396 static assert(isSomeFunction!(real delegate(ref int))); 7397 static assert(isSomeFunction!((int a) { return a; })); 7398 static assert(!isSomeFunction!isSomeFunction); 7399 } 7400 7401 /** 7402 Detect whether `T` is a callable object, which can be called with the 7403 function call operator `$(LPAREN)...$(RPAREN)`. 7404 */ 7405 template isCallable(T...) 7406 if (T.length == 1) 7407 { 7408 static if (is(typeof(& T[0].opCall) == delegate)) 7409 // T is a object which has a member function opCall(). 7410 enum bool isCallable = true; 7411 else static if (is(typeof(& T[0].opCall) V : V*) && is(V == function)) 7412 // T is a type which has a static member function opCall(). 7413 enum bool isCallable = true; 7414 else 7415 enum bool isCallable = isSomeFunction!T; 7416 } 7417 7418 /// 7419 @safe unittest 7420 { 7421 interface I { real value() @property; } 7422 struct S { static int opCall(int) { return 0; } } 7423 class C { int opCall(int) { return 0; } } 7424 auto c = new C; 7425 7426 static assert( isCallable!c); 7427 static assert( isCallable!S); 7428 static assert( isCallable!(c.opCall)); 7429 static assert( isCallable!(I.value)); 7430 static assert( isCallable!((int a) { return a; })); 7431 7432 static assert(!isCallable!I); 7433 } 7434 7435 7436 /** 7437 Detect whether `T` is an abstract function. 7438 7439 Params: 7440 T = The type to check 7441 Returns: 7442 A `bool` 7443 */ 7444 template isAbstractFunction(T...) 7445 if (T.length == 1) 7446 { 7447 enum bool isAbstractFunction = __traits(isAbstractFunction, T[0]); 7448 } 7449 7450 /// 7451 @safe unittest 7452 { 7453 struct S { void foo() { } } 7454 class C { void foo() { } } 7455 class AC { abstract void foo(); } 7456 static assert(!isAbstractFunction!(int)); 7457 static assert(!isAbstractFunction!(S.foo)); 7458 static assert(!isAbstractFunction!(C.foo)); 7459 static assert( isAbstractFunction!(AC.foo)); 7460 } 7461 7462 /** 7463 * Detect whether `T` is a final function. 7464 */ 7465 template isFinalFunction(T...) 7466 if (T.length == 1) 7467 { 7468 enum bool isFinalFunction = __traits(isFinalFunction, T[0]); 7469 } 7470 7471 /// 7472 @safe unittest 7473 { 7474 struct S { void bar() { } } 7475 final class FC { void foo(); } 7476 class C 7477 { 7478 void bar() { } 7479 final void foo(); 7480 } 7481 static assert(!isFinalFunction!(int)); 7482 static assert(!isFinalFunction!(S.bar)); 7483 static assert( isFinalFunction!(FC.foo)); 7484 static assert(!isFinalFunction!(C.bar)); 7485 static assert( isFinalFunction!(C.foo)); 7486 } 7487 7488 /** 7489 Determines if `f` is a function that requires a context pointer. 7490 7491 Params: 7492 f = The type to check 7493 Returns 7494 A `bool` 7495 */ 7496 template isNestedFunction(alias f) 7497 { 7498 enum isNestedFunction = __traits(isNested, f) && isSomeFunction!(f); 7499 } 7500 7501 /// 7502 @safe unittest 7503 { 7504 static void f() {} 7505 static void fun() 7506 { 7507 int i; 7508 int f() { return i; } 7509 7510 static assert(isNestedFunction!(f)); 7511 } 7512 7513 static assert(!isNestedFunction!f); 7514 } 7515 7516 // https://issues.dlang.org/show_bug.cgi?id=18669 7517 @safe unittest 7518 { 7519 static class Outer 7520 { 7521 class Inner 7522 { 7523 } 7524 } 7525 int i; 7526 struct SS 7527 { 7528 int bar() { return i; } 7529 } 7530 static assert(!isNestedFunction!(Outer.Inner)); 7531 static assert(!isNestedFunction!(SS)); 7532 } 7533 7534 /** 7535 * Detect whether `T` is an abstract class. 7536 */ 7537 template isAbstractClass(T...) 7538 if (T.length == 1) 7539 { 7540 enum bool isAbstractClass = __traits(isAbstractClass, T[0]); 7541 } 7542 7543 /// 7544 @safe unittest 7545 { 7546 struct S { } 7547 class C { } 7548 abstract class AC { } 7549 static assert(!isAbstractClass!S); 7550 static assert(!isAbstractClass!C); 7551 static assert( isAbstractClass!AC); 7552 C c; 7553 static assert(!isAbstractClass!c); 7554 AC ac; 7555 static assert( isAbstractClass!ac); 7556 } 7557 7558 /** 7559 * Detect whether `T` is a final class. 7560 */ 7561 template isFinalClass(T...) 7562 if (T.length == 1) 7563 { 7564 enum bool isFinalClass = __traits(isFinalClass, T[0]); 7565 } 7566 7567 /// 7568 @safe unittest 7569 { 7570 class C { } 7571 abstract class AC { } 7572 final class FC1 : C { } 7573 final class FC2 { } 7574 static assert(!isFinalClass!C); 7575 static assert(!isFinalClass!AC); 7576 static assert( isFinalClass!FC1); 7577 static assert( isFinalClass!FC2); 7578 C c; 7579 static assert(!isFinalClass!c); 7580 FC1 fc1; 7581 static assert( isFinalClass!fc1); 7582 } 7583 7584 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 7585 // General Types 7586 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 7587 7588 /** 7589 Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`. 7590 */ 7591 template Unconst(T) 7592 { 7593 import core.internal.traits : CoreUnconst = Unconst; 7594 alias Unconst = CoreUnconst!(T); 7595 } 7596 7597 /// 7598 @safe unittest 7599 { 7600 static assert(is(Unconst!int == int)); 7601 static assert(is(Unconst!(const int) == int)); 7602 static assert(is(Unconst!(immutable int) == int)); 7603 static assert(is(Unconst!(shared int) == shared int)); 7604 static assert(is(Unconst!(shared(const int)) == shared int)); 7605 } 7606 7607 @safe unittest 7608 { 7609 static assert(is(Unconst!( int) == int)); 7610 static assert(is(Unconst!( const int) == int)); 7611 static assert(is(Unconst!( inout int) == int)); 7612 static assert(is(Unconst!( inout const int) == int)); 7613 static assert(is(Unconst!(shared int) == shared int)); 7614 static assert(is(Unconst!(shared const int) == shared int)); 7615 static assert(is(Unconst!(shared inout int) == shared int)); 7616 static assert(is(Unconst!(shared inout const int) == shared int)); 7617 static assert(is(Unconst!( immutable int) == int)); 7618 7619 alias ImmIntArr = immutable(int[]); 7620 static assert(is(Unconst!ImmIntArr == immutable(int)[])); 7621 } 7622 7623 /** 7624 Removes all qualifiers, if any, from type `T`. 7625 */ 7626 template Unqual(T) 7627 { 7628 import core.internal.traits : CoreUnqual = Unqual; 7629 alias Unqual = CoreUnqual!(T); 7630 } 7631 7632 /// 7633 @safe unittest 7634 { 7635 static assert(is(Unqual!int == int)); 7636 static assert(is(Unqual!(const int) == int)); 7637 static assert(is(Unqual!(immutable int) == int)); 7638 static assert(is(Unqual!(shared int) == int)); 7639 static assert(is(Unqual!(shared(const int)) == int)); 7640 } 7641 7642 @safe unittest 7643 { 7644 static assert(is(Unqual!( int) == int)); 7645 static assert(is(Unqual!( const int) == int)); 7646 static assert(is(Unqual!( inout int) == int)); 7647 static assert(is(Unqual!( inout const int) == int)); 7648 static assert(is(Unqual!(shared int) == int)); 7649 static assert(is(Unqual!(shared const int) == int)); 7650 static assert(is(Unqual!(shared inout int) == int)); 7651 static assert(is(Unqual!(shared inout const int) == int)); 7652 static assert(is(Unqual!( immutable int) == int)); 7653 7654 alias ImmIntArr = immutable(int[]); 7655 static assert(is(Unqual!ImmIntArr == immutable(int)[])); 7656 } 7657 7658 // [For internal use] 7659 package template ModifyTypePreservingTQ(alias Modifier, T) 7660 { 7661 static if (is(T U == immutable U)) alias ModifyTypePreservingTQ = immutable Modifier!U; 7662 else static if (is(T U == shared inout const U)) alias ModifyTypePreservingTQ = shared inout const Modifier!U; 7663 else static if (is(T U == shared inout U)) alias ModifyTypePreservingTQ = shared inout Modifier!U; 7664 else static if (is(T U == shared const U)) alias ModifyTypePreservingTQ = shared const Modifier!U; 7665 else static if (is(T U == shared U)) alias ModifyTypePreservingTQ = shared Modifier!U; 7666 else static if (is(T U == inout const U)) alias ModifyTypePreservingTQ = inout const Modifier!U; 7667 else static if (is(T U == inout U)) alias ModifyTypePreservingTQ = inout Modifier!U; 7668 else static if (is(T U == const U)) alias ModifyTypePreservingTQ = const Modifier!U; 7669 else alias ModifyTypePreservingTQ = Modifier!T; 7670 } 7671 7672 @safe unittest 7673 { 7674 alias Intify(T) = int; 7675 static assert(is(ModifyTypePreservingTQ!(Intify, real) == int)); 7676 static assert(is(ModifyTypePreservingTQ!(Intify, const real) == const int)); 7677 static assert(is(ModifyTypePreservingTQ!(Intify, inout real) == inout int)); 7678 static assert(is(ModifyTypePreservingTQ!(Intify, inout const real) == inout const int)); 7679 static assert(is(ModifyTypePreservingTQ!(Intify, shared real) == shared int)); 7680 static assert(is(ModifyTypePreservingTQ!(Intify, shared const real) == shared const int)); 7681 static assert(is(ModifyTypePreservingTQ!(Intify, shared inout real) == shared inout int)); 7682 static assert(is(ModifyTypePreservingTQ!(Intify, shared inout const real) == shared inout const int)); 7683 static assert(is(ModifyTypePreservingTQ!(Intify, immutable real) == immutable int)); 7684 } 7685 7686 /** 7687 * Copies type qualifiers from `FromType` to `ToType`. 7688 * 7689 * Supported type qualifiers: 7690 * $(UL 7691 * $(LI `const`) 7692 * $(LI `inout`) 7693 * $(LI `immutable`) 7694 * $(LI `shared`) 7695 * ) 7696 */ 7697 template CopyTypeQualifiers(FromType, ToType) 7698 { 7699 alias T(U) = ToType; 7700 alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType); 7701 } 7702 7703 /// 7704 @safe unittest 7705 { 7706 static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int)); 7707 } 7708 7709 @safe unittest 7710 { 7711 static assert(is(CopyTypeQualifiers!( real, int) == int)); 7712 static assert(is(CopyTypeQualifiers!( const real, int) == const int)); 7713 static assert(is(CopyTypeQualifiers!( inout real, int) == inout int)); 7714 static assert(is(CopyTypeQualifiers!( inout const real, int) == inout const int)); 7715 static assert(is(CopyTypeQualifiers!(shared real, int) == shared int)); 7716 static assert(is(CopyTypeQualifiers!(shared const real, int) == shared const int)); 7717 static assert(is(CopyTypeQualifiers!(shared inout real, int) == shared inout int)); 7718 static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int)); 7719 static assert(is(CopyTypeQualifiers!( immutable real, int) == immutable int)); 7720 } 7721 7722 /** 7723 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness) 7724 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the 7725 returned type will be the same as `ToType`. 7726 */ 7727 template CopyConstness(FromType, ToType) 7728 { 7729 alias Unshared(T) = T; 7730 alias Unshared(T: shared U, U) = U; 7731 7732 alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType)); 7733 } 7734 7735 /// 7736 @safe unittest 7737 { 7738 const(int) i; 7739 CopyConstness!(typeof(i), float) f; 7740 assert( is(typeof(f) == const float)); 7741 7742 CopyConstness!(char, uint) u; 7743 assert( is(typeof(u) == uint)); 7744 7745 //The 'shared' qualifier will not be copied 7746 assert(!is(CopyConstness!(shared bool, int) == shared int)); 7747 7748 //But the constness will be 7749 assert( is(CopyConstness!(shared const real, double) == const double)); 7750 7751 //Careful, const(int)[] is a mutable array of const(int) 7752 alias MutT = CopyConstness!(const(int)[], int); 7753 assert(!is(MutT == const(int))); 7754 7755 //Okay, const(int[]) applies to array and contained ints 7756 alias CstT = CopyConstness!(const(int[]), int); 7757 assert( is(CstT == const(int))); 7758 } 7759 7760 @safe unittest 7761 { 7762 struct Test 7763 { 7764 void method1() {} 7765 void method2() const {} 7766 void method3() immutable {} 7767 } 7768 7769 assert(is(CopyConstness!(typeof(Test.method1), real) == real)); 7770 7771 assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte))); 7772 7773 assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string))); 7774 } 7775 7776 @safe unittest 7777 { 7778 assert(is(CopyConstness!(inout(int)[], int[]) == int[])); 7779 assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[]))); 7780 } 7781 7782 @safe unittest 7783 { 7784 static assert(is(CopyConstness!( int, real) == real)); 7785 static assert(is(CopyConstness!(const int, real) == const real)); 7786 static assert(is(CopyConstness!(inout int, real) == inout real)); 7787 static assert(is(CopyConstness!(inout const int, real) == inout const real)); 7788 static assert(is(CopyConstness!(shared int, real) == real)); 7789 static assert(is(CopyConstness!(shared const int, real) == const real)); 7790 static assert(is(CopyConstness!(shared inout int, real) == inout real)); 7791 static assert(is(CopyConstness!(shared inout const int, real) == inout const real)); 7792 static assert(is(CopyConstness!(immutable int, real) == immutable real)); 7793 } 7794 7795 /** 7796 Returns the inferred type of the loop variable when a variable of type T 7797 is iterated over using a `foreach` loop with a single loop variable and 7798 automatically inferred return type. Note that this may not be the same as 7799 `std.range.ElementType!Range` in the case of narrow strings, or if T 7800 has both opApply and a range interface. 7801 */ 7802 template ForeachType(T) 7803 { 7804 alias ForeachType = ReturnType!(typeof( 7805 (inout int x = 0) 7806 { 7807 foreach (elem; T.init) 7808 { 7809 return elem; 7810 } 7811 assert(0); 7812 })); 7813 } 7814 7815 /// 7816 @safe unittest 7817 { 7818 static assert(is(ForeachType!(uint[]) == uint)); 7819 static assert(is(ForeachType!string == immutable(char))); 7820 static assert(is(ForeachType!(string[string]) == string)); 7821 static assert(is(ForeachType!(inout(int)[]) == inout(int))); 7822 } 7823 7824 7825 /** 7826 * Strips off all `enum`s from type `T`. 7827 */ 7828 template OriginalType(T) 7829 { 7830 template Impl(T) 7831 { 7832 static if (is(T U == enum)) alias Impl = OriginalType!U; 7833 else alias Impl = T; 7834 } 7835 7836 alias OriginalType = ModifyTypePreservingTQ!(Impl, T); 7837 } 7838 7839 /// 7840 @safe unittest 7841 { 7842 enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle 7843 enum F : E { a = E.a } 7844 alias G = const(F); 7845 static assert(is(OriginalType!E == real)); 7846 static assert(is(OriginalType!F == real)); 7847 static assert(is(OriginalType!G == const real)); 7848 } 7849 7850 /** 7851 * Get the Key type of an Associative Array. 7852 */ 7853 alias KeyType(V : V[K], K) = K; 7854 7855 /// 7856 @safe unittest 7857 { 7858 alias Hash = int[string]; 7859 static assert(is(KeyType!Hash == string)); 7860 static assert(is(ValueType!Hash == int)); 7861 KeyType!Hash str = "a"; // str is declared as string 7862 ValueType!Hash num = 1; // num is declared as int 7863 } 7864 7865 /** 7866 * Get the Value type of an Associative Array. 7867 */ 7868 alias ValueType(V : V[K], K) = V; 7869 7870 /// 7871 @safe unittest 7872 { 7873 alias Hash = int[string]; 7874 static assert(is(KeyType!Hash == string)); 7875 static assert(is(ValueType!Hash == int)); 7876 KeyType!Hash str = "a"; // str is declared as string 7877 ValueType!Hash num = 1; // num is declared as int 7878 } 7879 7880 /** 7881 Params: 7882 T = A built in integral or vector type. 7883 7884 Returns: 7885 The corresponding unsigned numeric type for `T` with the 7886 same type qualifiers. 7887 7888 If `T` is not a integral or vector, a compile-time error is given. 7889 */ 7890 template Unsigned(T) 7891 { 7892 template Impl(T) 7893 { 7894 static if (is(T : __vector(V[N]), V, size_t N)) 7895 alias Impl = __vector(Impl!V[N]); 7896 else static if (isUnsigned!T) 7897 alias Impl = T; 7898 else static if (isSigned!T && !isFloatingPoint!T) 7899 { 7900 static if (is(T == byte )) alias Impl = ubyte; 7901 static if (is(T == short)) alias Impl = ushort; 7902 static if (is(T == int )) alias Impl = uint; 7903 static if (is(T == long )) alias Impl = ulong; 7904 static if (is(ucent) && is(T == cent )) alias Impl = ucent; 7905 } 7906 else 7907 static assert(false, "Type " ~ T.stringof ~ 7908 " does not have an Unsigned counterpart"); 7909 } 7910 7911 alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T); 7912 } 7913 7914 /// 7915 @safe unittest 7916 { 7917 static assert(is(Unsigned!(int) == uint)); 7918 static assert(is(Unsigned!(long) == ulong)); 7919 static assert(is(Unsigned!(const short) == const ushort)); 7920 static assert(is(Unsigned!(immutable byte) == immutable ubyte)); 7921 static assert(is(Unsigned!(inout int) == inout uint)); 7922 } 7923 7924 7925 /// Unsigned types are forwarded 7926 @safe unittest 7927 { 7928 static assert(is(Unsigned!(uint) == uint)); 7929 static assert(is(Unsigned!(const uint) == const uint)); 7930 7931 static assert(is(Unsigned!(ubyte) == ubyte)); 7932 static assert(is(Unsigned!(immutable uint) == immutable uint)); 7933 } 7934 7935 @safe unittest 7936 { 7937 alias U1 = Unsigned!int; 7938 alias U2 = Unsigned!(const(int)); 7939 alias U3 = Unsigned!(immutable(int)); 7940 static assert(is(U1 == uint)); 7941 static assert(is(U2 == const(uint))); 7942 static assert(is(U3 == immutable(uint))); 7943 static if (is(__vector(int[4])) && is(__vector(uint[4]))) 7944 { 7945 alias UV1 = Unsigned!(__vector(int[4])); 7946 alias UV2 = Unsigned!(const(__vector(int[4]))); 7947 static assert(is(UV1 == __vector(uint[4]))); 7948 static assert(is(UV2 == const(__vector(uint[4])))); 7949 } 7950 //struct S {} 7951 //alias U2 = Unsigned!S; 7952 //alias U3 = Unsigned!double; 7953 static if (is(ucent)) 7954 { 7955 alias U4 = Unsigned!cent; 7956 alias U5 = Unsigned!(const(cent)); 7957 alias U6 = Unsigned!(immutable(cent)); 7958 static assert(is(U4 == ucent)); 7959 static assert(is(U5 == const(ucent))); 7960 static assert(is(U6 == immutable(ucent))); 7961 } 7962 } 7963 7964 /** 7965 Returns the largest type, i.e. T such that T.sizeof is the largest. If more 7966 than one type is of the same size, the leftmost argument of these in will be 7967 returned. 7968 */ 7969 template Largest(T...) 7970 if (T.length >= 1) 7971 { 7972 static if (T.length == 1) 7973 { 7974 alias Largest = T[0]; 7975 } 7976 else static if (T.length == 2) 7977 { 7978 static if (T[0].sizeof >= T[1].sizeof) 7979 { 7980 alias Largest = T[0]; 7981 } 7982 else 7983 { 7984 alias Largest = T[1]; 7985 } 7986 } 7987 else 7988 { 7989 alias Largest = Largest!(Largest!(T[0 .. $/2]), Largest!(T[$/2 .. $])); 7990 } 7991 } 7992 7993 /// 7994 @safe unittest 7995 { 7996 static assert(is(Largest!(uint, ubyte, ushort, real) == real)); 7997 static assert(is(Largest!(ulong, double) == ulong)); 7998 static assert(is(Largest!(double, ulong) == double)); 7999 static assert(is(Largest!(uint, byte, double, short) == double)); 8000 static if (is(ucent)) 8001 static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent)); 8002 } 8003 8004 /** 8005 Returns the corresponding signed type for T. T must be a numeric integral type, 8006 otherwise a compile-time error occurs. 8007 */ 8008 template Signed(T) 8009 { 8010 template Impl(T) 8011 { 8012 static if (is(T : __vector(V[N]), V, size_t N)) 8013 alias Impl = __vector(Impl!V[N]); 8014 else static if (isSigned!T) 8015 alias Impl = T; 8016 else static if (isUnsigned!T) 8017 { 8018 static if (is(T == ubyte )) alias Impl = byte; 8019 static if (is(T == ushort)) alias Impl = short; 8020 static if (is(T == uint )) alias Impl = int; 8021 static if (is(T == ulong )) alias Impl = long; 8022 static if (is(ucent) && is(T == ucent )) alias Impl = cent; 8023 } 8024 else 8025 static assert(false, "Type " ~ T.stringof ~ 8026 " does not have an Signed counterpart"); 8027 } 8028 8029 alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T); 8030 } 8031 8032 /// 8033 @safe unittest 8034 { 8035 alias S1 = Signed!uint; 8036 static assert(is(S1 == int)); 8037 alias S2 = Signed!(const(uint)); 8038 static assert(is(S2 == const(int))); 8039 alias S3 = Signed!(immutable(uint)); 8040 static assert(is(S3 == immutable(int))); 8041 static if (is(ucent)) 8042 { 8043 alias S4 = Signed!ucent; 8044 static assert(is(S4 == cent)); 8045 } 8046 } 8047 8048 @safe unittest 8049 { 8050 static assert(is(Signed!float == float)); 8051 static if (is(__vector(int[4])) && is(__vector(uint[4]))) 8052 { 8053 alias SV1 = Signed!(__vector(uint[4])); 8054 alias SV2 = Signed!(const(__vector(uint[4]))); 8055 static assert(is(SV1 == __vector(int[4]))); 8056 static assert(is(SV2 == const(__vector(int[4])))); 8057 } 8058 } 8059 8060 8061 /** 8062 Returns the most negative value of the numeric type T. 8063 */ 8064 template mostNegative(T) 8065 if (isNumeric!T || isSomeChar!T || isBoolean!T) 8066 { 8067 static if (is(typeof(T.min_normal))) 8068 enum mostNegative = -T.max; 8069 else static if (T.min == 0) 8070 enum byte mostNegative = 0; 8071 else 8072 enum mostNegative = T.min; 8073 } 8074 8075 /// 8076 @safe unittest 8077 { 8078 static assert(mostNegative!float == -float.max); 8079 static assert(mostNegative!double == -double.max); 8080 static assert(mostNegative!real == -real.max); 8081 static assert(mostNegative!bool == false); 8082 } 8083 8084 /// 8085 @safe unittest 8086 { 8087 import std.meta : AliasSeq; 8088 8089 static foreach (T; AliasSeq!(bool, byte, short, int, long)) 8090 static assert(mostNegative!T == T.min); 8091 8092 static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar)) 8093 static assert(mostNegative!T == 0); 8094 } 8095 8096 /** 8097 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote) 8098 to in multi-term arithmetic expressions. 8099 */ 8100 template Promoted(T) 8101 if (isScalarType!T) 8102 { 8103 alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init)); 8104 } 8105 8106 /// 8107 @safe unittest 8108 { 8109 ubyte a = 3, b = 5; 8110 static assert(is(typeof(a * b) == Promoted!ubyte)); 8111 static assert(is(Promoted!ubyte == int)); 8112 8113 static assert(is(Promoted!(shared(bool)) == shared(int))); 8114 static assert(is(Promoted!(const(int)) == const(int))); 8115 static assert(is(Promoted!double == double)); 8116 } 8117 8118 @safe unittest 8119 { 8120 // promote to int: 8121 static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar)) 8122 { 8123 static assert(is(Promoted!T == int)); 8124 static assert(is(Promoted!(shared(const T)) == shared(const int))); 8125 } 8126 8127 // already promoted: 8128 static foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real)) 8129 { 8130 static assert(is(Promoted!T == T)); 8131 static assert(is(Promoted!(immutable(T)) == immutable(T))); 8132 } 8133 } 8134 8135 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 8136 // Misc. 8137 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 8138 8139 /** 8140 Returns the mangled name of symbol or type `sth`. 8141 8142 `mangledName` is the same as builtin `.mangleof` property, but 8143 might be more convenient in generic code, e.g. as a template argument 8144 when invoking staticMap. 8145 */ 8146 template mangledName(sth...) 8147 if (sth.length == 1) 8148 { 8149 enum string mangledName = sth[0].mangleof; 8150 } 8151 8152 /// 8153 @safe unittest 8154 { 8155 import std.meta : AliasSeq; 8156 alias TL = staticMap!(mangledName, int, const int, immutable int); 8157 static assert(TL == AliasSeq!("i", "xi", "yi")); 8158 } 8159 8160 version (StdUnittest) private void freeFunc(string); 8161 8162 @safe unittest 8163 { 8164 class C { int value() @property { return 0; } } 8165 static assert(mangledName!int == int.mangleof); 8166 static assert(mangledName!C == C.mangleof); 8167 static assert(mangledName!(C.value) == C.value.mangleof); 8168 static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi"); 8169 static assert(mangledName!mangledName == "3std6traits11mangledName"); 8170 static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv"); 8171 int x; 8172 // https://issues.dlang.org/show_bug.cgi?id=9148 8173 static if (is(typeof({ return x; }) : int delegate() pure)) 8174 static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi"); // pure nothrow @safe @nogc 8175 else 8176 static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi"); // nothrow @safe @nnogc 8177 } 8178 8179 @system unittest 8180 { 8181 // @system due to demangle 8182 // Test for https://issues.dlang.org/show_bug.cgi?id=5718 8183 import std.demangle : demangle; 8184 int foo; 8185 auto foo_demangled = demangle(mangledName!foo); 8186 assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo", 8187 foo_demangled); 8188 8189 void bar(); 8190 auto bar_demangled = demangle(mangledName!bar); 8191 assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()"); 8192 } 8193 8194 8195 8196 // XXX Select & select should go to another module. (functional or algorithm?) 8197 8198 /** 8199 Aliases itself to `T[0]` if the boolean `condition` is `true` 8200 and to `T[1]` otherwise. 8201 */ 8202 template Select(bool condition, T...) 8203 if (T.length == 2) 8204 { 8205 import std.meta : Alias; 8206 alias Select = Alias!(T[!condition]); 8207 } 8208 8209 /// 8210 @safe unittest 8211 { 8212 // can select types 8213 static assert(is(Select!(true, int, long) == int)); 8214 static assert(is(Select!(false, int, long) == long)); 8215 static struct Foo {} 8216 static assert(is(Select!(false, const(int), const(Foo)) == const(Foo))); 8217 8218 // can select symbols 8219 int a = 1; 8220 int b = 2; 8221 alias selA = Select!(true, a, b); 8222 alias selB = Select!(false, a, b); 8223 assert(selA == 1); 8224 assert(selB == 2); 8225 8226 // can select (compile-time) expressions 8227 enum val = Select!(false, -4, 9 - 6); 8228 static assert(val == 3); 8229 } 8230 8231 /** 8232 Select one of two functions to run via template parameter. 8233 8234 Params: 8235 cond = A `bool` which determines which function is run 8236 a = The first function 8237 b = The second function 8238 8239 Returns: 8240 `a` without evaluating `b` if `cond` is `true`. 8241 Otherwise, returns `b` without evaluating `a`. 8242 */ 8243 A select(bool cond : true, A, B)(A a, lazy B b) { return a; } 8244 /// Ditto 8245 B select(bool cond : false, A, B)(lazy A a, B b) { return b; } 8246 8247 /// 8248 @safe unittest 8249 { 8250 real run() { return 0; } 8251 int fail() { assert(0); } 8252 auto a = select!true(run(), fail()); 8253 auto b = select!false(fail(), run()); 8254 static assert(is(typeof(a) == real)); 8255 static assert(is(typeof(b) == real)); 8256 } 8257 8258 /++ 8259 Determine if a symbol has a given 8260 $(DDSUBLINK spec/attribute, uda, user-defined attribute). 8261 8262 See_Also: 8263 $(LREF getUDAs) 8264 +/ 8265 template hasUDA(alias symbol, alias attribute) 8266 { 8267 enum hasUDA = getUDAs!(symbol, attribute).length != 0; 8268 } 8269 8270 /// 8271 @safe unittest 8272 { 8273 enum E; 8274 struct S {} 8275 8276 @("alpha") int a; 8277 static assert(hasUDA!(a, "alpha")); 8278 static assert(!hasUDA!(a, S)); 8279 static assert(!hasUDA!(a, E)); 8280 8281 @(E) int b; 8282 static assert(!hasUDA!(b, "alpha")); 8283 static assert(!hasUDA!(b, S)); 8284 static assert(hasUDA!(b, E)); 8285 8286 @E int c; 8287 static assert(!hasUDA!(c, "alpha")); 8288 static assert(!hasUDA!(c, S)); 8289 static assert(hasUDA!(c, E)); 8290 8291 @(S, E) int d; 8292 static assert(!hasUDA!(d, "alpha")); 8293 static assert(hasUDA!(d, S)); 8294 static assert(hasUDA!(d, E)); 8295 8296 @S int e; 8297 static assert(!hasUDA!(e, "alpha")); 8298 static assert(hasUDA!(e, S)); 8299 static assert(!hasUDA!(e, S())); 8300 static assert(!hasUDA!(e, E)); 8301 8302 @S() int f; 8303 static assert(!hasUDA!(f, "alpha")); 8304 static assert(hasUDA!(f, S)); 8305 static assert(hasUDA!(f, S())); 8306 static assert(!hasUDA!(f, E)); 8307 8308 @(S, E, "alpha") int g; 8309 static assert(hasUDA!(g, "alpha")); 8310 static assert(hasUDA!(g, S)); 8311 static assert(hasUDA!(g, E)); 8312 8313 @(100) int h; 8314 static assert(hasUDA!(h, 100)); 8315 8316 struct Named { string name; } 8317 8318 @Named("abc") int i; 8319 static assert(hasUDA!(i, Named)); 8320 static assert(hasUDA!(i, Named("abc"))); 8321 static assert(!hasUDA!(i, Named("def"))); 8322 8323 struct AttrT(T) 8324 { 8325 string name; 8326 T value; 8327 } 8328 8329 @AttrT!int("answer", 42) int j; 8330 static assert(hasUDA!(j, AttrT)); 8331 static assert(hasUDA!(j, AttrT!int)); 8332 static assert(!hasUDA!(j, AttrT!string)); 8333 8334 @AttrT!string("hello", "world") int k; 8335 static assert(hasUDA!(k, AttrT)); 8336 static assert(!hasUDA!(k, AttrT!int)); 8337 static assert(hasUDA!(k, AttrT!string)); 8338 8339 struct FuncAttr(alias f) { alias func = f; } 8340 static int fourtyTwo() { return 42; } 8341 static size_t getLen(string s) { return s.length; } 8342 8343 @FuncAttr!getLen int l; 8344 static assert(hasUDA!(l, FuncAttr)); 8345 static assert(!hasUDA!(l, FuncAttr!fourtyTwo)); 8346 static assert(hasUDA!(l, FuncAttr!getLen)); 8347 static assert(!hasUDA!(l, FuncAttr!fourtyTwo())); 8348 static assert(!hasUDA!(l, FuncAttr!getLen())); 8349 8350 @FuncAttr!getLen() int m; 8351 static assert(hasUDA!(m, FuncAttr)); 8352 static assert(!hasUDA!(m, FuncAttr!fourtyTwo)); 8353 static assert(hasUDA!(m, FuncAttr!getLen)); 8354 static assert(!hasUDA!(m, FuncAttr!fourtyTwo())); 8355 static assert(hasUDA!(m, FuncAttr!getLen())); 8356 } 8357 8358 /++ 8359 Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes) 8360 from the given symbol. 8361 8362 If the UDA is a type, then any UDAs of the same type on the symbol will 8363 match. If the UDA is a template for a type, then any UDA which is an 8364 instantiation of that template will match. And if the UDA is a value, 8365 then any UDAs on the symbol which are equal to that value will match. 8366 8367 See_Also: 8368 $(LREF hasUDA) 8369 +/ 8370 template getUDAs(alias symbol, alias attribute) 8371 { 8372 import std.meta : Filter; 8373 8374 alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, symbol)); 8375 } 8376 8377 /// 8378 @safe unittest 8379 { 8380 struct Attr 8381 { 8382 string name; 8383 int value; 8384 } 8385 8386 @Attr("Answer", 42) int a; 8387 static assert(getUDAs!(a, Attr).length == 1); 8388 static assert(getUDAs!(a, Attr)[0].name == "Answer"); 8389 static assert(getUDAs!(a, Attr)[0].value == 42); 8390 8391 @(Attr("Answer", 42), "string", 9999) int b; 8392 static assert(getUDAs!(b, Attr).length == 1); 8393 static assert(getUDAs!(b, Attr)[0].name == "Answer"); 8394 static assert(getUDAs!(b, Attr)[0].value == 42); 8395 8396 @Attr("Answer", 42) @Attr("Pi", 3) int c; 8397 static assert(getUDAs!(c, Attr).length == 2); 8398 static assert(getUDAs!(c, Attr)[0].name == "Answer"); 8399 static assert(getUDAs!(c, Attr)[0].value == 42); 8400 static assert(getUDAs!(c, Attr)[1].name == "Pi"); 8401 static assert(getUDAs!(c, Attr)[1].value == 3); 8402 8403 static assert(getUDAs!(c, Attr("Answer", 42)).length == 1); 8404 static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer"); 8405 static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42); 8406 8407 static assert(getUDAs!(c, Attr("Answer", 99)).length == 0); 8408 8409 struct AttrT(T) 8410 { 8411 string name; 8412 T value; 8413 } 8414 8415 @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d; 8416 static assert(getUDAs!(d, AttrT).length == 2); 8417 static assert(getUDAs!(d, AttrT)[0].name == "Answer"); 8418 static assert(getUDAs!(d, AttrT)[0].value == 42); 8419 static assert(getUDAs!(d, AttrT)[1].name == "Pi"); 8420 static assert(getUDAs!(d, AttrT)[1].value == 3); 8421 8422 static assert(getUDAs!(d, AttrT!uint).length == 1); 8423 static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer"); 8424 static assert(getUDAs!(d, AttrT!uint)[0].value == 42); 8425 8426 static assert(getUDAs!(d, AttrT!int).length == 1); 8427 static assert(getUDAs!(d, AttrT!int)[0].name == "Pi"); 8428 static assert(getUDAs!(d, AttrT!int)[0].value == 3); 8429 8430 struct SimpleAttr {} 8431 8432 @SimpleAttr int e; 8433 static assert(getUDAs!(e, SimpleAttr).length == 1); 8434 static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr)); 8435 8436 @SimpleAttr() int f; 8437 static assert(getUDAs!(f, SimpleAttr).length == 1); 8438 static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr)); 8439 8440 struct FuncAttr(alias f) { alias func = f; } 8441 static int add42(int v) { return v + 42; } 8442 static string concat(string l, string r) { return l ~ r; } 8443 8444 @FuncAttr!add42 int g; 8445 static assert(getUDAs!(g, FuncAttr).length == 1); 8446 static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47); 8447 8448 static assert(getUDAs!(g, FuncAttr!add42).length == 1); 8449 static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47); 8450 8451 static assert(getUDAs!(g, FuncAttr!add42()).length == 0); 8452 8453 static assert(getUDAs!(g, FuncAttr!concat).length == 0); 8454 static assert(getUDAs!(g, FuncAttr!concat()).length == 0); 8455 8456 @FuncAttr!add42() int h; 8457 static assert(getUDAs!(h, FuncAttr).length == 1); 8458 static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47); 8459 8460 static assert(getUDAs!(h, FuncAttr!add42).length == 1); 8461 static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47); 8462 8463 static assert(getUDAs!(h, FuncAttr!add42()).length == 1); 8464 static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47); 8465 8466 static assert(getUDAs!(h, FuncAttr!concat).length == 0); 8467 static assert(getUDAs!(h, FuncAttr!concat()).length == 0); 8468 8469 @("alpha") @(42) int i; 8470 static assert(getUDAs!(i, "alpha").length == 1); 8471 static assert(getUDAs!(i, "alpha")[0] == "alpha"); 8472 8473 static assert(getUDAs!(i, 42).length == 1); 8474 static assert(getUDAs!(i, 42)[0] == 42); 8475 8476 static assert(getUDAs!(i, 'c').length == 0); 8477 } 8478 8479 private template isDesiredUDA(alias attribute) 8480 { 8481 template isDesiredUDA(alias toCheck) 8482 { 8483 static if (is(typeof(attribute)) && !__traits(isTemplate, attribute)) 8484 { 8485 static if (__traits(compiles, toCheck == attribute)) 8486 enum isDesiredUDA = toCheck == attribute; 8487 else 8488 enum isDesiredUDA = false; 8489 } 8490 else static if (is(typeof(toCheck))) 8491 { 8492 static if (__traits(isTemplate, attribute)) 8493 enum isDesiredUDA = isInstanceOf!(attribute, typeof(toCheck)); 8494 else 8495 enum isDesiredUDA = is(typeof(toCheck) == attribute); 8496 } 8497 else static if (__traits(isTemplate, attribute)) 8498 enum isDesiredUDA = isInstanceOf!(attribute, toCheck); 8499 else 8500 enum isDesiredUDA = is(toCheck == attribute); 8501 } 8502 } 8503 8504 /** 8505 Params: 8506 symbol = The aggregate type or module to search 8507 attribute = The user-defined attribute to search for 8508 8509 Returns: 8510 All symbols within `symbol` that have the given UDA `attribute`. 8511 8512 Note: 8513 This is not recursive; it will not search for symbols within symbols such as 8514 nested structs or unions. 8515 */ 8516 template getSymbolsByUDA(alias symbol, alias attribute) 8517 { 8518 alias membersWithUDA = getSymbolsByUDAImpl!(symbol, attribute, __traits(allMembers, symbol)); 8519 8520 // if the symbol itself has the UDA, tack it on to the front of the list 8521 static if (hasUDA!(symbol, attribute)) 8522 alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA); 8523 else 8524 alias getSymbolsByUDA = membersWithUDA; 8525 } 8526 8527 /// 8528 @safe unittest 8529 { 8530 enum Attr; 8531 struct A 8532 { 8533 @Attr int a; 8534 int b; 8535 } 8536 8537 static assert(getSymbolsByUDA!(A, Attr).length == 1); 8538 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr)); 8539 } 8540 8541 /// 8542 @safe unittest 8543 { 8544 enum Attr; 8545 8546 static struct A 8547 { 8548 @Attr int a; 8549 int b; 8550 @Attr void doStuff() {} 8551 void doOtherStuff() {} 8552 static struct Inner 8553 { 8554 // Not found by getSymbolsByUDA 8555 @Attr int c; 8556 } 8557 } 8558 8559 // Finds both variables and functions with the attribute, but 8560 // doesn't include the variables and functions without it. 8561 static assert(getSymbolsByUDA!(A, Attr).length == 2); 8562 // Can access attributes on the symbols returned by getSymbolsByUDA. 8563 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr)); 8564 static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr)); 8565 } 8566 8567 /// Finds multiple attributes 8568 @safe unittest 8569 { 8570 static struct UDA { string name; } 8571 8572 static struct B 8573 { 8574 @UDA("X") 8575 int x; 8576 @UDA("Y") 8577 int y; 8578 @(100) 8579 int z; 8580 } 8581 8582 // Finds both UDA attributes. 8583 static assert(getSymbolsByUDA!(B, UDA).length == 2); 8584 // Finds one `100` attribute. 8585 static assert(getSymbolsByUDA!(B, 100).length == 1); 8586 // Can get the value of the UDA from the return value 8587 static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X"); 8588 } 8589 8590 /// Checks for UDAs on the aggregate symbol itself 8591 @safe unittest 8592 { 8593 static struct UDA { string name; } 8594 8595 @UDA("A") 8596 static struct C 8597 { 8598 @UDA("B") 8599 int d; 8600 } 8601 8602 static assert(getSymbolsByUDA!(C, UDA).length == 2); 8603 static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C"); 8604 static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d"); 8605 } 8606 8607 /// Finds nothing if there is no member with specific UDA 8608 @safe unittest 8609 { 8610 static struct UDA { string name; } 8611 8612 static struct D 8613 { 8614 int x; 8615 } 8616 8617 static assert(getSymbolsByUDA!(D, UDA).length == 0); 8618 } 8619 8620 // https://issues.dlang.org/show_bug.cgi?id=18314 8621 @safe unittest 8622 { 8623 enum attr1; 8624 enum attr2; 8625 8626 struct A 8627 { 8628 @attr1 8629 int n; 8630 // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206 8631 //@attr1 8632 //void foo()(string){} 8633 @attr1 8634 void foo(); 8635 @attr2 8636 void foo(int a); 8637 } 8638 8639 static assert(getSymbolsByUDA!(A, attr1).length == 2); 8640 static assert(getSymbolsByUDA!(A, attr2).length == 1); 8641 } 8642 8643 // getSymbolsByUDA fails if type has private members 8644 // https://issues.dlang.org/show_bug.cgi?id=15335 8645 @safe unittest 8646 { 8647 // HasPrivateMembers has, well, private members, one of which has a UDA. 8648 import std.internal.test.uda : Attr, HasPrivateMembers; 8649 // Trying access to private member from another file therefore we do not have access 8650 // for this otherwise we get deprecation warning - not visible from module 8651 // This line is commented because `__traits(getMember)` should also consider 8652 // private members; this is not currently the case, but the PR that 8653 // fixes `__traits(getMember)` is blocked by this specific test. 8654 //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1); 8655 static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr)); 8656 } 8657 8658 // getSymbolsByUDA works with structs but fails with classes 8659 // https://issues.dlang.org/show_bug.cgi?id=16387 8660 @safe unittest 8661 { 8662 enum Attr; 8663 class A 8664 { 8665 @Attr uint a; 8666 } 8667 8668 alias res = getSymbolsByUDA!(A, Attr); 8669 static assert(res.length == 1); 8670 static assert(res[0].stringof == "a"); 8671 } 8672 8673 // getSymbolsByUDA fails on AliasSeq members 8674 // https://issues.dlang.org/show_bug.cgi?id=18884 8675 @safe unittest 8676 { 8677 struct X 8678 { 8679 alias A = AliasSeq!(ulong, uint); 8680 } 8681 8682 static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!())); 8683 } 8684 8685 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function 8686 // https://issues.dlang.org/show_bug.cgi?id=18624 8687 @safe unittest 8688 { 8689 enum Attr; 8690 struct A 8691 { 8692 @Attr void a(); 8693 @Attr void a(int n); 8694 void b(); 8695 @Attr void c(); 8696 } 8697 8698 static assert(getSymbolsByUDA!(A, Attr).stringof == "tuple(a, a, c)"); 8699 } 8700 8701 // getSymbolsByUDA no longer works on modules 8702 // https://issues.dlang.org/show_bug.cgi?id=20054 8703 version (StdUnittest) 8704 { 8705 @("Issue20054") 8706 void issue20054() {} 8707 static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054"))); 8708 } 8709 8710 private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...) 8711 { 8712 import std.meta : Alias, AliasSeq, Filter; 8713 static if (names.length == 0) 8714 { 8715 alias getSymbolsByUDAImpl = AliasSeq!(); 8716 } 8717 else 8718 { 8719 alias tail = getSymbolsByUDAImpl!(symbol, attribute, names[1 .. $]); 8720 8721 // Filtering inaccessible members. 8722 static if (!__traits(compiles, __traits(getMember, symbol, names[0]))) 8723 { 8724 alias getSymbolsByUDAImpl = tail; 8725 } 8726 else 8727 { 8728 alias member = __traits(getMember, symbol, names[0]); 8729 8730 // Filtering not compiled members such as alias of basic types. 8731 static if (!__traits(compiles, hasUDA!(member, attribute))) 8732 { 8733 alias getSymbolsByUDAImpl = tail; 8734 } 8735 // Get overloads for functions, in case different overloads have different sets of UDAs. 8736 else static if (isFunction!member) 8737 { 8738 enum hasSpecificUDA(alias member) = hasUDA!(member, attribute); 8739 alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0])); 8740 alias getSymbolsByUDAImpl = AliasSeq!(overloadsWithUDA, tail); 8741 } 8742 else static if (hasUDA!(member, attribute)) 8743 { 8744 alias getSymbolsByUDAImpl = AliasSeq!(member, tail); 8745 } 8746 else 8747 { 8748 alias getSymbolsByUDAImpl = tail; 8749 } 8750 } 8751 } 8752 } 8753 8754 /** 8755 Returns: `true` iff all types `T` are the same. 8756 */ 8757 template allSameType(T...) 8758 { 8759 static foreach (idx, Ti; T) 8760 { 8761 static if (idx + 1 < T.length && 8762 !is(typeof(allSameType) == bool) && 8763 !is(T[idx] == T[idx + 1])) 8764 { 8765 enum bool allSameType = false; 8766 } 8767 } 8768 static if (!is(typeof(allSameType) == bool)) 8769 { 8770 enum bool allSameType = true; 8771 } 8772 } 8773 8774 /// 8775 @safe unittest 8776 { 8777 static assert(allSameType!(int, int)); 8778 static assert(allSameType!(int, int, int)); 8779 static assert(allSameType!(float, float, float)); 8780 static assert(!allSameType!(int, double)); 8781 static assert(!allSameType!(int, float, double)); 8782 static assert(!allSameType!(int, float, double, real)); 8783 static assert(!allSameType!(short, int, float, double, real)); 8784 } 8785 8786 /** 8787 Returns: `true` iff the type `T` can be tested in an $(D 8788 if)-expression, that is if $(D if (pred(T.init)) {}) is compilable. 8789 */ 8790 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} }); 8791 8792 @safe unittest 8793 { 8794 import std.meta : AliasSeq, allSatisfy; 8795 static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string))); 8796 struct BoolWrapper { bool value; } 8797 static assert(!ifTestable!(bool, a => BoolWrapper(a))); 8798 } 8799 8800 /** 8801 * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used 8802 * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`. 8803 * 8804 * Returns: 8805 * `true` if `X` is a type, `false` otherwise 8806 */ 8807 template isType(X...) 8808 if (X.length == 1) 8809 { 8810 enum isType = is(X[0]); 8811 } 8812 8813 /// 8814 @safe unittest 8815 { 8816 struct S { 8817 template Test() {} 8818 } 8819 class C {} 8820 interface I {} 8821 union U {} 8822 static assert(isType!int); 8823 static assert(isType!string); 8824 static assert(isType!(int[int])); 8825 static assert(isType!S); 8826 static assert(isType!C); 8827 static assert(isType!I); 8828 static assert(isType!U); 8829 8830 int n; 8831 void func(){} 8832 static assert(!isType!n); 8833 static assert(!isType!func); 8834 static assert(!isType!(S.Test)); 8835 static assert(!isType!(S.Test!())); 8836 } 8837 8838 /** 8839 * Detect whether symbol or type `X` is a function. This is different that finding 8840 * if a symbol is callable or satisfying `is(X == function)`, it finds 8841 * specifically if the symbol represents a normal function declaration, i.e. 8842 * not a delegate or a function pointer. 8843 * 8844 * Returns: 8845 * `true` if `X` is a function, `false` otherwise 8846 * 8847 * See_Also: 8848 * Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types 8849 * respectively. 8850 */ 8851 template isFunction(X...) 8852 if (X.length == 1) 8853 { 8854 static if (is(typeof(&X[0]) U : U*) && is(U == function) || 8855 is(typeof(&X[0]) U == delegate)) 8856 { 8857 // x is a (nested) function symbol. 8858 enum isFunction = true; 8859 } 8860 else static if (is(X[0] T)) 8861 { 8862 // x is a type. Take the type of it and examine. 8863 enum isFunction = is(T == function); 8864 } 8865 else 8866 enum isFunction = false; 8867 } 8868 8869 /// 8870 @safe unittest 8871 { 8872 static void func(){} 8873 static assert(isFunction!func); 8874 8875 struct S 8876 { 8877 void func(){} 8878 } 8879 static assert(isFunction!(S.func)); 8880 } 8881 8882 /** 8883 * Detect whether `X` is a final method or class. 8884 * 8885 * Returns: 8886 * `true` if `X` is final, `false` otherwise 8887 */ 8888 template isFinal(X...) 8889 if (X.length == 1) 8890 { 8891 static if (is(X[0] == class)) 8892 enum isFinal = __traits(isFinalClass, X[0]); 8893 else static if (isFunction!X) 8894 enum isFinal = __traits(isFinalFunction, X[0]); 8895 else 8896 enum isFinal = false; 8897 } 8898 8899 /// 8900 @safe unittest 8901 { 8902 class C 8903 { 8904 void nf() {} 8905 static void sf() {} 8906 final void ff() {} 8907 } 8908 final class FC { } 8909 8910 static assert(!isFinal!(C)); 8911 static assert( isFinal!(FC)); 8912 8913 static assert(!isFinal!(C.nf)); 8914 static assert(!isFinal!(C.sf)); 8915 static assert( isFinal!(C.ff)); 8916 } 8917 8918 /++ 8919 + Determines whether the type `S` can be copied. 8920 + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile. 8921 + Copying for structs can be disabled by using `@disable this(this)`. 8922 + 8923 + Params: 8924 + S = The type to check. 8925 + 8926 + Returns: 8927 + `true` if `S` can be copied. `false` otherwise. 8928 + ++/ 8929 enum isCopyable(S) = __traits(isCopyable, S); 8930 8931 /// 8932 @safe unittest 8933 { 8934 struct S1 {} // Fine. Can be copied 8935 struct S2 { this(this) {}} // Fine. Can be copied 8936 struct S3 {@disable this(this); } // Not fine. Copying is disabled. 8937 struct S4 {S3 s;} // Not fine. A field has copying disabled. 8938 8939 class C1 {} 8940 8941 static assert( isCopyable!S1); 8942 static assert( isCopyable!S2); 8943 static assert(!isCopyable!S3); 8944 static assert(!isCopyable!S4); 8945 8946 static assert(isCopyable!C1); 8947 static assert(isCopyable!int); 8948 static assert(isCopyable!(int[])); 8949 }