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