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