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 {
Demangle(T)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.
MutableOf(T)287     template MutableOf(T)     { alias MutableOf     =              T  ; }
288 }
289 
290 /// Add the inout qualifier to the given type T.
InoutOf(T)291 template InoutOf(T)       { alias InoutOf       =        inout(T) ; }
292 /// Add the const qualifier to the given type T.
ConstOf(T)293 template ConstOf(T)       { alias ConstOf       =        const(T) ; }
294 /// Add the shared qualifier to the given type T.
SharedOf(T)295 template SharedOf(T)      { alias SharedOf      =       shared(T) ; }
296 /// Add the shared and inout qualifiers to the given type T.
SharedInoutOf(T)297 template SharedInoutOf(T) { alias SharedInoutOf = shared(inout(T)); }
298 /// Add the shared and const qualifiers to the given type T.
SharedConstOf(T)299 template SharedConstOf(T) { alias SharedConstOf = shared(const(T)); }
300 /// Add the immutable qualifier to the given type T.
ImmutableOf(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
QualifierOf(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 
version(unittest)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  */
packageName(alias T)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 
X12287(T)393     struct X12287(T) { T i; }
394     static assert(packageName!(X12287!int.i) == "std");
395 }
396 
version(unittest)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  */
moduleName(alias T)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 
X12287(T)449     struct X12287(T) { T i; }
450     static assert(moduleName!(X12287!int.i) == "std.traits");
451 }
452 
version(unittest)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 
version(unittest)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 {
fqnTuple(T...)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 
fqnSym(alias T)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 {
TemplatedStruct()599     struct TemplatedStruct()
600     {
601         enum foo = 0;
602     }
603     alias TemplatedStructAlias = TemplatedStruct;
604     assert("TemplatedStruct.foo" == fullyQualifiedName!(TemplatedStructAlias!().foo));
605 }
606 
fqnType(T,bool alreadyConst,bool alreadyImmutable,bool alreadyShared,bool alreadyInout)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";
with(QualifiedNameTests)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     {
opCallG916         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     {
opCall(int i)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     {
prop()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 {
foo(int i,bool b)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 
opCallS983     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     {
prop()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 {
foo()1014     void foo(){}
1015     static assert(arity!foo == 0);
bar(uint)1016     void bar(uint){}
1017     static assert(arity!bar == 1);
variadicFoo(uint...)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
ParameterStorageClassTuple(func...)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 
func(ref int ctx,out real result,real param)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  */
extractParameterStorageClassFlags(Attribs...)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 
noparam()1125     void noparam() {}
1126     static assert(ParameterStorageClassTuple!noparam.length == 0);
1127 
test(scope int *,ref int,out int,lazy int,int,return ref int i)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
func(inout int param)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", 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", "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", "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