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