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