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