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