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