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 */ 166 module std.traits; 167 168 import std.meta : AliasSeq, allSatisfy; 169 import std.functional : unaryFun; 170 171 // Legacy inheritance from std.typetuple 172 // See also: https://github.com/dlang/phobos/pull/5484#discussion_r122602797 173 import 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") 176 alias 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) 185 private 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 284 package 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. 291 template InoutOf(T) { alias InoutOf = inout(T) ; } 292 /// Add the const qualifier to the given type T. 293 template ConstOf(T) { alias ConstOf = const(T) ; } 294 /// Add the shared qualifier to the given type T. 295 template SharedOf(T) { alias SharedOf = shared(T) ; } 296 /// Add the shared and inout qualifiers to the given type T. 297 template SharedInoutOf(T) { alias SharedInoutOf = shared(inout(T)); } 298 /// Add the shared and const qualifiers to the given type T. 299 template SharedConstOf(T) { alias SharedConstOf = shared(const(T)); } 300 /// Add the immutable qualifier to the given type T. 301 template 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 315 template 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 337 version (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 348 private alias parentOf(alias sym) = Identity!(__traits(parent, sym)); 349 private 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 */ 354 template 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 397 version (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 */ 408 template 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 453 version (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 464 Example: 465 ----------------- 466 module myModule; 467 struct MyStruct {} 468 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])"); 469 ----------------- 470 */ 471 template 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 487 version (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 531 private 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 553 private 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 607 private 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 */ 896 template 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 /*** 951 Get, as a tuple, the types of the parameters to a function, a pointer 952 to function, a delegate, a struct with an $(D opCall), a pointer to a 953 struct with an $(D opCall), or a class with an $(D opCall). 954 */ 955 template 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 */ 975 alias 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 /** 1002 Returns the number of arguments of function $(D func). 1003 arity is undefined for variadic functions. 1004 */ 1005 template 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 /** 1023 Get tuple, one per function parameter, of the storage classes of the parameters. 1024 Params: 1025 func = function symbol or type of function, delegate, or pointer to function 1026 Returns: 1027 A tuple of ParameterStorageClass bits 1028 */ 1029 enum 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 1044 template 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 */ 1093 template 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 /** 1174 Get, as a tuple, the identifiers of the parameters to a function symbol. 1175 */ 1176 template 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 /** 1260 Get, as a tuple, the default value of the parameters to a function symbol. 1261 If a parameter doesn't have the default value, $(D void) is returned instead. 1262 */ 1263 template 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 */ 1343 alias 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 /** 1383 Returns the FunctionAttribute mask for function $(D func). 1384 1385 See_Also: 1386 $(LREF hasFunctionAttributes) 1387 */ 1388 enum 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 1411 template 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 1547 private 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 /** 1577 Checks whether a function has the given attributes attached. 1578 1579 Params: 1580 args = Function to check, followed by a 1581 variadic number of function attributes as strings 1582 1583 Returns: 1584 `true`, if the function has the list of attributes attached and `false` otherwise. 1585 1586 See_Also: 1587 $(LREF functionAttributes) 1588 */ 1589 template 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 */ 1773 template 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 */ 1852 template 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 /** 1926 Determine the linkage attribute of the function. 1927 Params: 1928 func = the function symbol, or the type of a function, delegate, or pointer to function 1929 Returns: 1930 one of the strings "D", "C", "Windows", "Pascal", or "Objective-C" 1931 */ 1932 template 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 /** 1969 Determines what kind of variadic parameters function has. 1970 Params: 1971 func = function symbol or type of function, delegate, or pointer to function 1972 Returns: 1973 enum Variadic 1974 */ 1975 enum 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 1986 template 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 /** 2026 Get the function type from a callable object $(D func). 2027 2028 Using builtin $(D typeof) on a property function yields the types of the 2029 property value, not of the property function itself. Still, 2030 $(D FunctionTypeOf) is able to obtain function types of properties. 2031 2032 Note: 2033 Do not confuse function types with function pointer types; function types are 2034 usually used for compile-time reflection purposes. 2035 */ 2036 template 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 */ 2141 template 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 2216 template 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 2238 version (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 /** 2300 Determines whether `T` is a class nested inside another class 2301 and 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 2304 Params: 2305 T = type to test 2306 2307 Returns: 2308 `true` if `T` is a class nested inside another, with the conditions described above; 2309 `false` otherwise 2310 */ 2311 template 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 /** 2354 Determines whether $(D T) has its own context pointer. 2355 $(D T) must be either $(D class), $(D struct), or $(D union). 2356 */ 2357 template 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 /** 2375 Determines whether $(D T) or any of its representation types 2376 have a context pointer. 2377 */ 2378 template 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 */ 2473 template 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 */ 2493 alias 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 2519 private 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 */ 2528 template 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 /*** 2571 Get the primitive types of the fields of a struct or class, in 2572 topological order. 2573 */ 2574 template 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 /* 2657 Statically evaluates to $(D true) if and only if $(D T)'s 2658 representation contains at least one field of pointer or array type. 2659 Members of class types are not considered raw pointers. Pointers to 2660 immutable objects are not considered raw aliasing. 2661 */ 2662 private 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 /* 2753 Statically evaluates to $(D true) if and only if $(D T)'s 2754 representation contains at least one non-shared field of pointer or 2755 array type. Members of class types are not considered raw pointers. 2756 Pointers to immutable objects are not considered raw aliasing. 2757 */ 2758 private 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 /* 2935 Statically evaluates to $(D true) if and only if $(D T)'s 2936 representation includes at least one non-immutable object reference. 2937 */ 2938 2939 private 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 /* 2958 Statically evaluates to $(D true) if and only if $(D T)'s 2959 representation includes at least one non-immutable non-shared object 2960 reference. 2961 */ 2962 private 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 /** 2982 Returns $(D true) if and only if $(D T)'s representation includes at 2983 least one of the following: $(OL $(LI a raw pointer $(D U*) and $(D U) 2984 is not immutable;) $(LI an array $(D U[]) and $(D U) is not 2985 immutable;) $(LI a reference to a class or interface type $(D C) and $(D C) is 2986 not immutable.) $(LI an associative array that is not immutable.) 2987 $(LI a delegate.)) 2988 */ 2989 template 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 /** 3088 Returns $(D true) if and only if $(D T)'s representation includes at 3089 least one of the following: $(OL $(LI a raw pointer $(D U*);) $(LI an 3090 array $(D U[]);) $(LI a reference to a class type $(D C).) 3091 $(LI an associative array.) $(LI a delegate.)) 3092 */ 3093 template 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 /** 3196 Returns $(D true) if and only if $(D T)'s representation includes at 3197 least one of the following: $(OL $(LI a raw pointer $(D U*) and $(D U) 3198 is not immutable or shared;) $(LI an array $(D U[]) and $(D U) is not 3199 immutable 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 3201 immutable or shared.) $(LI a delegate that is not shared.)) 3202 */ 3203 3204 template 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 */ 3380 template 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 */ 3437 template 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 */ 3524 template 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 3566 package 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 */ 3572 enum 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 */ 3639 template 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 /** 3806 Retrieves the members of an enumerated type $(D enum E). 3807 3808 Params: 3809 E = An enumerated type. $(D E) may have duplicated values. 3810 3811 Returns: 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 3815 Note: 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 3821 Note: 3822 Returned values are strictly typed with $(D E). Thus, the following code 3823 does not work without the explicit cast: 3824 -------------------- 3825 enum E : int { a, b, c } 3826 int[] 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 3831 Example: 3832 Creating an array of enumerated values: 3833 -------------------- 3834 enum Sqrts : real 3835 { 3836 one = 1, 3837 two = 1.41421, 3838 three = 1.73205, 3839 } 3840 auto sqrts = [ EnumMembers!Sqrts ]; 3841 assert(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. 3848 size_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 3859 enum Mode 3860 { 3861 read = 1, 3862 write = 2, 3863 map = 4, 3864 } 3865 assert(rank(Mode.read ) == 0); 3866 assert(rank(Mode.write) == 1); 3867 assert(rank(Mode.map ) == 2); 3868 -------------------- 3869 */ 3870 template 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 */ 3994 template 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 */ 4036 template 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 */ 4084 template 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 */ 4145 template 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 /** 4175 Returns a tuple of non-static functions with the name $(D name) declared in the 4176 class or interface $(D C). Covariant duplicates are shrunk into the most 4177 derived one. 4178 */ 4179 template 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 /** 4357 Returns an alias to the template that $(D T) is an instance of. 4358 */ 4359 template TemplateOf(alias T : Base!Args, alias Base, Args...) 4360 { 4361 alias TemplateOf = Base; 4362 } 4363 4364 /// ditto 4365 template 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 /** 4402 Returns a $(D AliasSeq) of the template arguments used to instantiate $(D T). 4403 */ 4404 template TemplateArgsOf(alias T : Base!Args, alias Base, Args...) 4405 { 4406 alias TemplateArgsOf = Args; 4407 } 4408 4409 /// ditto 4410 template 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 4448 private 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 /** 4464 Returns class instance alignment. 4465 */ 4466 template 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 /** 4488 Get the type that all types can be implicitly converted to. Useful 4489 e.g. in figuring out an array type from a bunch of initializing 4490 values. Returns $(D_PARAM void) if passed an empty list, or if the 4491 types have no common type. 4492 */ 4493 template 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 */ 4546 template 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 /** 4615 Is $(D From) implicitly convertible to $(D To)? 4616 */ 4617 template 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 /** 4645 Returns $(D true) iff a value of type $(D Rhs) can be assigned to a variable of 4646 type $(D Lhs). 4647 4648 $(D isAssignable) returns whether both an lvalue and rvalue can be assigned. 4649 4650 If you omit $(D Rhs), $(D isAssignable) will check identity assignable of $(D Lhs). 4651 */ 4652 enum 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 4670 private enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, lvalueOf!Lhs = rvalueOf!Rhs); 4671 4672 // ditto 4673 private 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. 4718 package 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 /* 4838 Works like $(D isImplicitlyConvertible), except this cares only about storage 4839 classes of the arguments. 4840 */ 4841 private 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 /** 4863 Determines whether the function type $(D F) is covariant with $(D G), i.e., 4864 functions of the type $(D F) can override ones of the type $(D G). 4865 */ 4866 template 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" 5058 private struct __InoutWorkaroundStruct{} 5059 5060 /** 5061 Creates an lvalue or rvalue of type $(D T) for $(D typeof(...)) and 5062 $(D __traits(compiles, ...)) purposes. No actual value is returned. 5063 5064 Note: Trying to use returned value will result in a 5065 "Symbol Undefined" error at link time. 5066 5067 Example: 5068 --- 5069 // Note that `f` doesn't have to be implemented 5070 // as is isn't called. 5071 int f(int); 5072 bool f(ref int); 5073 static assert(is(typeof(f(rvalueOf!int)) == int)); 5074 static assert(is(typeof(f(lvalueOf!int)) == bool)); 5075 5076 int 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 5111 private 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 */ 5125 template 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 */ 5176 template 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 */ 5211 template 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 */ 5246 template 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 */ 5275 template 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 */ 5287 template 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 */ 5301 template 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 */ 5343 template 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 */ 5378 template 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 */ 5415 template 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 /* 5426 Always returns the Dynamic Array version. 5427 */ 5428 template 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 */ 5479 template 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 */ 5516 template 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 */ 5537 enum 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 */ 5562 enum 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 */ 5614 enum 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 */ 5687 enum 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 */ 5748 enum 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 */ 5780 enum 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 */ 5803 enum 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 */ 5848 enum 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 */ 5902 enum 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 /** 5947 Detect whether $(D T) is one of the built-in string types. 5948 5949 The 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 5952 Static arrays of characters (like $(D char[80])) are not considered 5953 built-in string types. 5954 */ 5955 enum 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 */ 5993 enum 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 */ 6032 enum 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 6056 enum 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 */ 6086 template 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 6119 package 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 */ 6143 enum 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 */ 6161 enum 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 */ 6200 enum 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 */ 6230 enum 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 */ 6260 enum 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 */ 6291 enum 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 */ 6315 enum 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 */ 6332 enum 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 /** 6352 Returns the target type of a pointer. 6353 */ 6354 alias 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 */ 6366 enum 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 */ 6395 enum 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 */ 6424 enum 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 */ 6444 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...); 6445 /// ditto 6446 template 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 */ 6490 template 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 6515 alias 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 */ 6543 template 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 /** 6581 Detect whether symbol or type $(D T) is a function pointer. 6582 */ 6583 template 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 /** 6617 Detect whether symbol or type $(D T) is a delegate. 6618 */ 6619 template 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 /** 6655 Detect whether symbol or type $(D T) is a function, a function pointer or a delegate. 6656 */ 6657 template 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 /** 6715 Detect whether $(D T) is a callable object, which can be called with the 6716 function call operator $(D $(LPAREN)...$(RPAREN)). 6717 */ 6718 template 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 */ 6752 template 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 */ 6772 template 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 /** 6796 Determines whether function $(D f) requires a context pointer. 6797 */ 6798 template 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 */ 6814 template 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 */ 6838 template 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 /** 6866 Removes all qualifiers, if any, from type $(D T). 6867 */ 6868 template 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] 6919 package 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 */ 6957 template 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 /** 6983 Returns the type of `Target` with the "constness" of `Source`. A type's $(B constness) 6984 refers to whether it is `const`, `immutable`, or `inout`. If `source` has no constness, the 6985 returned type will be the same as `Target`. 6986 */ 6987 template 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 /** 7056 Returns the inferred type of the loop variable when a variable of type T 7057 is iterated over using a $(D foreach) loop with a single loop variable and 7058 automatically 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 7060 has both opApply and a range interface. 7061 */ 7062 template 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 */ 7088 template 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 */ 7113 alias 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 */ 7129 alias 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 */ 7146 template 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 /** 7200 Returns the largest type, i.e. T such that T.sizeof is the largest. If more 7201 than one type is of the same size, the leftmost argument of these in will be 7202 returned. 7203 */ 7204 template 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 /** 7239 Returns the corresponding signed type for T. T must be a numeric integral type, 7240 otherwise a compile-time error occurs. 7241 */ 7242 template 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 /** 7296 Returns the most negative value of the numeric type T. 7297 */ 7298 template 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 /** 7329 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote) 7330 to in multi-term arithmetic expressions. 7331 */ 7332 template 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 /** 7372 Returns the mangled name of symbol or type $(D sth). 7373 7374 $(D mangledName) is the same as builtin $(D .mangleof) property, but 7375 might be more convenient in generic code, e.g. as a template argument 7376 when invoking staticMap. 7377 */ 7378 template 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 7391 version (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 /** 7429 Aliases itself to $(D T[0]) if the boolean $(D condition) is $(D true) 7430 and to $(D T[1]) otherwise. 7431 */ 7432 template 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 /** 7461 If $(D cond) is $(D true), returns $(D a) without evaluating $(D 7462 b). Otherwise, returns $(D b) without evaluating $(D a). 7463 */ 7464 A select(bool cond : true, A, B)(A a, lazy B b) { return a; } 7465 /// Ditto 7466 B 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 +/ 7485 template 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 +/ 7590 template 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 */ 7725 template 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 */ 7872 template 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 */ 7900 enum 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 */ 7917 template 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 */ 7960 template 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 */ 7996 template 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 + ++/ 8036 enum 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