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