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(alias T) = void;
4732 
4733 ///
4734 @safe unittest
4735 {
4736     struct Foo(T, U) {}
4737     static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
4738 }
4739 
4740 @safe unittest
4741 {
4742     template Foo1(A) {}
4743     template Foo2(A, B) {}
4744     template Foo3(alias A) {}
4745     template Foo4(string A) {}
4746     struct Foo5(A) {}
4747     struct Foo6(A, B) {}
4748     struct Foo7(alias A) {}
4749     template Foo8(A) { template Foo9(B) {} }
4750     template Foo10() {}
4751 
4752     static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1));
4753     static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2));
4754     static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3));
4755     static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4));
4756     static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5));
4757     static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6));
4758     static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7));
4759     static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9));
4760     static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10));
4761 }
4762 
4763 // https://issues.dlang.org/show_bug.cgi?id=18214
4764 @safe unittest
4765 {
4766     static assert(is(TemplateOf!(int[]) == void));
4767     static assert(is(TemplateOf!bool == void));
4768 
4769     // https://github.com/dlang/phobos/issues/10527
4770     static void foo() {}
4771     static assert(is(TemplateOf!foo == void));
4772 }
4773 
4774 /**
4775 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
4776  */
4777 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
4778 
4779 /// ditto
4780 alias TemplateArgsOf(T : Base!Args, alias Base, Args...) = Args;
4781 
4782 ///
4783 @safe unittest
4784 {
4785     import std.meta : AliasSeq;
4786 
4787     struct Foo(T, U) {}
4788     static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));
4789 }
4790 
4791 @safe unittest
4792 {
4793     template Foo1(A) {}
4794     template Foo2(A, B) {}
4795     template Foo3(alias A) {}
4796     template Foo4(string A) {}
4797     struct Foo5(A) {}
4798     struct Foo6(A, B) {}
4799     struct Foo7(alias A) {}
4800     template Foo8(A) { template Foo9(B) {} }
4801     template Foo10() {}
4802 
4803     enum x = 123;
4804     enum y = "123";
4805     static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int)));
4806     static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int)));
4807     static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x)));
4808     static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y));
4809     static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int)));
4810     static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int)));
4811     static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x)));
4812     static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real)));
4813     static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
4814 }
4815 
4816 // Returns the largest alignment in a type tuple.
4817 package enum maxAlignment(U...) =
4818 {
4819     size_t result = U[0].alignof;
4820     static foreach (T; U[1 .. $])
4821         if (result < T.alignof)
4822             result = T.alignof;
4823     return result;
4824 }();
4825 
4826 /**
4827 Returns class instance alignment.
4828 
4829 See also: $(DDSUBLINK spec/traits, classInstanceAlignment, `__traits(classInstanceAlignment, T)`)
4830  */
4831 template classInstanceAlignment(T)
4832 if (is(T == class))
4833 {
4834     enum classInstanceAlignment = __traits(classInstanceAlignment, T);
4835 }
4836 
4837 ///
4838 @safe unittest
4839 {
4840     class A { byte b; }
4841     class B { long l; }
4842 
4843     // As class instance always has a hidden pointer
4844     static assert(classInstanceAlignment!A == (void*).alignof);
4845     static assert(classInstanceAlignment!B == long.alignof);
4846 }
4847 
4848 
4849 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4850 // Type Conversion
4851 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4852 
4853 /**
4854 Get the type that all types can be implicitly converted to. Useful
4855 e.g. in figuring out an array type from a bunch of initializing
4856 values. Returns $(D_PARAM void) if passed an empty list, or if the
4857 types have no common type.
4858  */
4859 template CommonType(T...)
4860 {
4861     static if (T.length == 1)
4862         alias CommonType = typeof(T[0].init);
4863     else static if (is(typeof(true ? T[0].init : T[1].init) U))
4864         alias CommonType = CommonType!(U, T[2 .. $]);
4865     else
4866         alias CommonType = void;
4867 }
4868 
4869 ///
4870 @safe unittest
4871 {
4872     alias X = CommonType!(int, long, short);
4873     assert(is(X == long));
4874     alias Y = CommonType!(int, char[], short);
4875     assert(is(Y == void));
4876 }
4877 
4878 ///
4879 @safe unittest
4880 {
4881     static assert(is(CommonType!(3) == int));
4882     static assert(is(CommonType!(double, 4, float) == double));
4883     static assert(is(CommonType!(string, char[]) == const(char)[]));
4884     static assert(is(CommonType!(3, 3U) == uint));
4885     static assert(is(CommonType!(double, int) == double));
4886 }
4887 
4888 
4889 /**
4890 Params:
4891     T = The type to check
4892 
4893 Returns:
4894     An $(REF AliasSeq,std,meta) with all possible target types of an implicit
4895     conversion `T`.
4896 
4897     If `T` is a class derived from `Object`, the result of
4898     $(LREF TransitiveBaseTypeTuple) is returned.
4899 
4900     If the type is not a built-in value type or a class derived from
4901     `Object`, an empty $(REF AliasSeq,std,meta) is returned.
4902 
4903 See_Also:
4904     $(LREF isImplicitlyConvertible)
4905  */
4906 template AllImplicitConversionTargets(T)
4907 {
4908     static if (is(T == bool))
4909         alias AllImplicitConversionTargets =
4910             AliasSeq!(byte, AllImplicitConversionTargets!byte);
4911     else static if (is(T == byte))
4912         alias AllImplicitConversionTargets =
4913             AliasSeq!(char, ubyte, short, AllImplicitConversionTargets!short);
4914     else static if (is(T == ubyte))
4915         alias AllImplicitConversionTargets =
4916             AliasSeq!(byte, char, short, AllImplicitConversionTargets!short);
4917     else static if (is(T == short))
4918         alias AllImplicitConversionTargets =
4919             AliasSeq!(ushort, wchar, int, AllImplicitConversionTargets!int);
4920     else static if (is(T == ushort))
4921         alias AllImplicitConversionTargets =
4922             AliasSeq!(short, wchar, dchar, AllImplicitConversionTargets!dchar);
4923     else static if (is(T == int))
4924         alias AllImplicitConversionTargets =
4925             AliasSeq!(dchar, uint, long, AllImplicitConversionTargets!long);
4926     else static if (is(T == uint))
4927         alias AllImplicitConversionTargets =
4928             AliasSeq!(dchar, int, long, AllImplicitConversionTargets!long);
4929     else static if (is(T == long))
4930         alias AllImplicitConversionTargets = AliasSeq!(ulong, CentTypeList, float, double, real);
4931     else static if (is(T == ulong))
4932         alias AllImplicitConversionTargets = AliasSeq!(long, CentTypeList, float, double, real);
4933     else static if (is(T == float))
4934         alias AllImplicitConversionTargets = AliasSeq!(double, real);
4935     else static if (is(T == double))
4936         alias AllImplicitConversionTargets = AliasSeq!(float, real);
4937     else static if (is(T == real))
4938         alias AllImplicitConversionTargets = AliasSeq!(float, double);
4939     else static if (is(T == char))
4940         alias AllImplicitConversionTargets =
4941             AliasSeq!(byte, ubyte, short, AllImplicitConversionTargets!short);
4942     else static if (is(T == wchar))
4943         alias AllImplicitConversionTargets =
4944             AliasSeq!(short, ushort, dchar, AllImplicitConversionTargets!dchar);
4945     else static if (is(T == dchar))
4946         alias AllImplicitConversionTargets =
4947             AliasSeq!(int, uint, long, AllImplicitConversionTargets!long);
4948     else static if (is(T == class))
4949         alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!T);
4950     else static if (is(T == interface))
4951         alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!T);
4952     else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
4953     {
4954        static if (is(typeof(T.init[0]) == shared))
4955            alias AllImplicitConversionTargets =
4956            AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
4957        else
4958            alias AllImplicitConversionTargets =
4959            AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
4960     }
4961     else static if (is(T : void*) && !is(T == void*))
4962         alias AllImplicitConversionTargets = AliasSeq!(void*);
4963     else static if (is(cent) && is(T == cent))
4964         alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
4965     else static if (is(ucent) && is(T == ucent))
4966         alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
4967     else
4968         alias AllImplicitConversionTargets = AliasSeq!();
4969 }
4970 
4971 ///
4972 @safe unittest
4973 {
4974     import std.meta : AliasSeq;
4975 
4976     static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
4977     static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
4978     static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
4979     static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));
4980 
4981     static assert(is(AllImplicitConversionTargets!(char) ==
4982         AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
4983             ulong, float, double, real)
4984     ));
4985     static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
4986         short, ushort, dchar, int, uint, long, ulong, float, double, real
4987     )));
4988     static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
4989         int, uint, long, ulong, float, double, real
4990     )));
4991 
4992     static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
4993     static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));
4994 
4995     interface A {}
4996     interface B {}
4997     class C : A, B {}
4998 
4999     static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5000     static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5001     static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!(
5002         immutable Object, immutable A, immutable B
5003     )));
5004 
5005     interface I : A, B {}
5006 
5007     static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B)));
5008     static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B)));
5009     static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!(
5010         immutable A, immutable B
5011     )));
5012 }
5013 
5014 @safe unittest
5015 {
5016     static assert(is(AllImplicitConversionTargets!(double)[0] == float));
5017     static assert(is(AllImplicitConversionTargets!(double)[1] == real));
5018     static assert(is(AllImplicitConversionTargets!(string)[0] == const(char)[]));
5019 }
5020 
5021 
5022 /**
5023 Params:
5024     T = The type to check
5025 
5026 Warning:
5027     This template is considered out-dated. It will be removed from
5028     Phobos in 2.107.0. Please use $(LREF AllImplicitConversionTargets) instead.
5029 
5030 Returns:
5031     An $(REF AliasSeq,std,meta) with all possible target types of an implicit
5032     conversion `T`.
5033 
5034     If `T` is a class derived from `Object`, the result of
5035     $(LREF TransitiveBaseTypeTuple) is returned.
5036 
5037     If the type is not a built-in value type or a class derived from
5038     `Object`, an empty $(REF AliasSeq,std,meta) is returned.
5039 
5040 Note:
5041     The possible targets are computed more conservatively than the
5042     language allows, eliminating all dangerous conversions. For example,
5043     `ImplicitConversionTargets!double` does not include `float`.
5044 
5045 See_Also:
5046     $(LREF isImplicitlyConvertible)
5047  */
5048 // @@@DEPRECATED_[2.107.0]@@@
5049 deprecated("ImplicitConversionTargets has been deprecated in favour of AllImplicitConversionTargets "
5050    ~ "and will be removed in 2.107.0")
5051 template ImplicitConversionTargets(T)
5052 {
5053     static if (is(T == bool))
5054         alias ImplicitConversionTargets =
5055             AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
5056                        float, double, real, char, wchar, dchar);
5057     else static if (is(T == byte))
5058         alias ImplicitConversionTargets =
5059             AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5060                        float, double, real, char, wchar, dchar);
5061     else static if (is(T == ubyte))
5062         alias ImplicitConversionTargets =
5063             AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5064                        float, double, real, char, wchar, dchar);
5065     else static if (is(T == short))
5066         alias ImplicitConversionTargets =
5067             AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5068     else static if (is(T == ushort))
5069         alias ImplicitConversionTargets =
5070             AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5071     else static if (is(T == int))
5072         alias ImplicitConversionTargets =
5073             AliasSeq!(long, ulong, CentTypeList, float, double, real);
5074     else static if (is(T == uint))
5075         alias ImplicitConversionTargets =
5076             AliasSeq!(long, ulong, CentTypeList, float, double, real);
5077     else static if (is(T == long))
5078         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5079     else static if (is(T == ulong))
5080         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5081     else static if (is(cent) && is(T == cent))
5082         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5083     else static if (is(ucent) && is(T == ucent))
5084         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5085     else static if (is(T == float))
5086         alias ImplicitConversionTargets = AliasSeq!(double, real);
5087     else static if (is(T == double))
5088         alias ImplicitConversionTargets = AliasSeq!real;
5089     else static if (is(T == char))
5090         alias ImplicitConversionTargets =
5091             AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
5092                        int, uint, long, ulong, CentTypeList, float, double, real);
5093     else static if (is(T == wchar))
5094         alias ImplicitConversionTargets =
5095             AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
5096                        float, double, real);
5097     else static if (is(T == dchar))
5098         alias ImplicitConversionTargets =
5099             AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5100     else static if (is(T : typeof(null)))
5101         alias ImplicitConversionTargets = AliasSeq!(typeof(null));
5102     else static if (is(T == class))
5103         alias ImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T));
5104     else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
5105     {
5106        static if (is(typeof(T.init[0]) == shared))
5107            alias ImplicitConversionTargets =
5108            AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
5109        else
5110            alias ImplicitConversionTargets =
5111            AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
5112     }
5113     else static if (is(T : void*))
5114         alias ImplicitConversionTargets = AliasSeq!(void*);
5115     else
5116         alias ImplicitConversionTargets = AliasSeq!();
5117 }
5118 
5119 deprecated @safe unittest
5120 {
5121     import std.meta : AliasSeq;
5122 
5123     static assert(is(ImplicitConversionTargets!(ulong) == AliasSeq!(float, double, real)));
5124     static assert(is(ImplicitConversionTargets!(int) == AliasSeq!(long, ulong, float, double, real)));
5125     static assert(is(ImplicitConversionTargets!(float) == AliasSeq!(double, real)));
5126     static assert(is(ImplicitConversionTargets!(double) == AliasSeq!(real)));
5127 
5128     static assert(is(ImplicitConversionTargets!(char) == AliasSeq!(
5129         wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
5130     )));
5131     static assert(is(ImplicitConversionTargets!(wchar) == AliasSeq!(
5132         dchar, short, ushort, int, uint, long, ulong, float, double, real
5133     )));
5134     static assert(is(ImplicitConversionTargets!(dchar) == AliasSeq!(
5135         int, uint, long, ulong, float, double, real
5136     )));
5137 
5138     static assert(is(ImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
5139     static assert(is(ImplicitConversionTargets!(void*) == AliasSeq!(void*)));
5140 
5141     interface A {}
5142     interface B {}
5143     class C : A, B {}
5144 
5145     static assert(is(ImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5146     static assert(is(ImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5147     static assert(is(ImplicitConversionTargets!(immutable C) == AliasSeq!(
5148         immutable Object, immutable A, immutable B
5149     )));
5150 }
5151 
5152 deprecated @safe unittest
5153 {
5154     static assert(is(ImplicitConversionTargets!(double)[0] == real));
5155     static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[]));
5156 }
5157 
5158 /**
5159 Is `From` implicitly convertible to `To`?
5160  */
5161 enum bool isImplicitlyConvertible(From, To) = is(From : To);
5162 
5163 ///
5164 @safe unittest
5165 {
5166     static assert( isImplicitlyConvertible!(immutable(char), char));
5167     static assert( isImplicitlyConvertible!(const(char), char));
5168     static assert( isImplicitlyConvertible!(char, wchar));
5169     static assert(!isImplicitlyConvertible!(wchar, char));
5170 
5171     static assert(!isImplicitlyConvertible!(const(ushort), ubyte));
5172     static assert(!isImplicitlyConvertible!(const(uint), ubyte));
5173     static assert(!isImplicitlyConvertible!(const(ulong), ubyte));
5174 
5175     static assert(!isImplicitlyConvertible!(const(char)[], string));
5176     static assert( isImplicitlyConvertible!(string, const(char)[]));
5177 }
5178 
5179 /**
5180 Is `From` $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) to `To`?
5181 */
5182 enum bool isQualifierConvertible(From, To) =
5183     is(immutable From == immutable To) && is(From* : To*);
5184 
5185 ///
5186 @safe unittest
5187 {
5188     // Mutable and immmutable both convert to const...
5189     static assert( isQualifierConvertible!(char, const(char)));
5190     static assert( isQualifierConvertible!(immutable(char), const(char)));
5191     // ...but const does not convert back to mutable or immutable
5192     static assert(!isQualifierConvertible!(const(char), char));
5193     static assert(!isQualifierConvertible!(const(char), immutable(char)));
5194 }
5195 
5196 @safe unittest
5197 {
5198     import std.meta : AliasSeq;
5199 
5200     alias Ts = AliasSeq!(int, const int, shared int, inout int, const shared int,
5201         const inout int, inout shared int, const inout shared int, immutable int);
5202 
5203     // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
5204     enum _ = 0;
5205     static immutable bool[Ts.length][Ts.length] conversions = [
5206     //   m   c   s   i   cs  ci  is  cis im
5207         [1,  1,  _,  _,  _,  _,  _,  _,  _],  // mutable
5208         [_,  1,  _,  _,  _,  _,  _,  _,  _],  // const
5209         [_,  _,  1,  _,  1,  _,  _,  _,  _],  // shared
5210         [_,  1,  _,  1,  _,  1,  _,  _,  _],  // inout
5211         [_,  _,  _,  _,  1,  _,  _,  _,  _],  // const shared
5212         [_,  1,  _,  _,  _,  1,  _,  _,  _],  // const inout
5213         [_,  _,  _,  _,  1,  _,  1,  1,  _],  // inout shared
5214         [_,  _,  _,  _,  1,  _,  _,  1,  _],  // const inout shared
5215         [_,  1,  _,  _,  1,  1,  _,  1,  1],  // immutable
5216     ];
5217 
5218     static foreach (i, From; Ts)
5219     {
5220         static foreach (j, To; Ts)
5221         {
5222             static assert(isQualifierConvertible!(From, To) == conversions[i][j],
5223                 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`"
5224                 ~ " should be `" ~ (conversions[i][j] ? "true" : "false") ~ "`");
5225         }
5226     }
5227 }
5228 
5229 @safe unittest
5230 {
5231     // int* -> void* is not a qualifier conversion
5232     static assert(!isQualifierConvertible!(int, void));
5233 }
5234 
5235 /**
5236 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
5237 type `Lhs`.
5238 
5239 `isAssignable` returns whether both an lvalue and rvalue can be assigned.
5240 
5241 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`.
5242 */
5243 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
5244 
5245 ///
5246 @safe unittest
5247 {
5248     static assert( isAssignable!(long, int));
5249     static assert(!isAssignable!(int, long));
5250     static assert( isAssignable!(const(char)[], string));
5251     static assert(!isAssignable!(string, char[]));
5252 
5253     // int is assignable to int
5254     static assert( isAssignable!int);
5255 
5256     // immutable int is not assignable to immutable int
5257     static assert(!isAssignable!(immutable int));
5258 }
5259 
5260 /**
5261 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
5262 type `Lhs`.
5263 */
5264 enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
5265 
5266 ///
5267 @safe unittest
5268 {
5269     struct S1
5270     {
5271         void opAssign(S1);
5272     }
5273 
5274     struct S2
5275     {
5276         void opAssign(ref S2);
5277     }
5278 
5279     static assert( isRvalueAssignable!(long, int));
5280     static assert(!isRvalueAssignable!(int, long));
5281     static assert( isRvalueAssignable!S1);
5282     static assert(!isRvalueAssignable!S2);
5283 }
5284 
5285 /**
5286 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
5287 type `Lhs`.
5288 */
5289 enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
5290 
5291 ///
5292 @safe unittest
5293 {
5294     struct S1
5295     {
5296         void opAssign(S1);
5297     }
5298 
5299     struct S2
5300     {
5301         void opAssign(ref S2);
5302     }
5303 
5304     static assert( isLvalueAssignable!(long, int));
5305     static assert(!isLvalueAssignable!(int, long));
5306     static assert( isLvalueAssignable!S1);
5307     static assert( isLvalueAssignable!S2);
5308 }
5309 
5310 @safe unittest
5311 {
5312     static assert(!isAssignable!(immutable int, int));
5313     static assert( isAssignable!(int, immutable int));
5314 
5315     static assert(!isAssignable!(inout int, int));
5316     static assert( isAssignable!(int, inout int));
5317     static assert(!isAssignable!(inout int));
5318 
5319     static assert( isAssignable!(shared int, int));
5320     static assert( isAssignable!(int, shared int));
5321     static assert( isAssignable!(shared int));
5322 
5323     static assert( isAssignable!(void[1], void[1]));
5324 
5325     struct S { @disable this(); this(int n){} }
5326     static assert( isAssignable!(S, S));
5327 
5328     struct S2 { this(int n){} }
5329     static assert( isAssignable!(S2, S2));
5330     static assert(!isAssignable!(S2, int));
5331 
5332     struct S3 { @disable void opAssign(); }
5333     static assert( isAssignable!(S3, S3));
5334 
5335     struct S3X { @disable void opAssign(S3X); }
5336     static assert(!isAssignable!(S3X, S3X));
5337 
5338     struct S4 { void opAssign(int); }
5339     static assert( isAssignable!(S4, S4));
5340     static assert( isAssignable!(S4, int));
5341     static assert( isAssignable!(S4, immutable int));
5342 
5343     struct S5 { @disable this(); @disable this(this); }
5344     // https://issues.dlang.org/show_bug.cgi?id=21210
5345     static assert(!isAssignable!S5);
5346 
5347     // `-preview=in` is enabled
5348     alias DScannerBug895 = int[256];
5349     static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init))
5350     {
5351         struct S6 { void opAssign(in S5); }
5352 
5353         static assert(isRvalueAssignable!(S6, S5));
5354         static assert(isLvalueAssignable!(S6, S5));
5355         static assert(isAssignable!(S6, S5));
5356         static assert(isAssignable!(S6, immutable S5));
5357     }
5358     else
5359     {
5360         mixin(q{ struct S6 { void opAssign(scope const ref S5); } });
5361 
5362         static assert(!isRvalueAssignable!(S6, S5));
5363         static assert( isLvalueAssignable!(S6, S5));
5364         static assert(!isAssignable!(S6, S5));
5365         static assert( isLvalueAssignable!(S6, immutable S5));
5366     }
5367 }
5368 
5369 
5370 // Equivalent with TypeStruct::isAssignable in compiler code.
5371 package template isBlitAssignable(T)
5372 {
5373     static if (is(T == enum))
5374     {
5375         enum isBlitAssignable = isBlitAssignable!(OriginalType!T);
5376     }
5377     else static if (isStaticArray!T && is(T == E[n], E, size_t n))
5378     // Workaround for https://issues.dlang.org/show_bug.cgi?id=11499 : isStaticArray!T should not be necessary.
5379     {
5380         enum isBlitAssignable = isBlitAssignable!E;
5381     }
5382     else static if (is(T == struct) || is(T == union))
5383     {
5384         enum isBlitAssignable = isMutable!T &&
5385         {
5386             size_t offset = 0;
5387             bool assignable = true;
5388             foreach (i, F; FieldTypeTuple!T)
5389             {
5390                 static if (i == 0)
5391                 {
5392                 }
5393                 else
5394                 {
5395                     if (T.tupleof[i].offsetof == offset)
5396                     {
5397                         if (assignable)
5398                             continue;
5399                     }
5400                     else
5401                     {
5402                         if (!assignable)
5403                             return false;
5404                     }
5405                 }
5406                 assignable = isBlitAssignable!(typeof(T.tupleof[i]));
5407                 offset = T.tupleof[i].offsetof;
5408             }
5409             return assignable;
5410         }();
5411     }
5412     else
5413         enum isBlitAssignable = isMutable!T;
5414 }
5415 
5416 @safe unittest
5417 {
5418     static assert( isBlitAssignable!int);
5419     static assert(!isBlitAssignable!(const int));
5420 
5421     class C{ const int i; }
5422     static assert( isBlitAssignable!C);
5423 
5424     struct S1{ int i; }
5425     struct S2{ const int i; }
5426     static assert( isBlitAssignable!S1);
5427     static assert(!isBlitAssignable!S2);
5428 
5429     struct S3X { union {       int x;       int y; } }
5430     struct S3Y { union {       int x; const int y; } }
5431     struct S3Z { union { const int x; const int y; } }
5432     static assert( isBlitAssignable!(S3X));
5433     static assert( isBlitAssignable!(S3Y));
5434     static assert(!isBlitAssignable!(S3Z));
5435     static assert(!isBlitAssignable!(const S3X));
5436     static assert(!isBlitAssignable!(inout S3Y));
5437     static assert(!isBlitAssignable!(immutable S3Z));
5438     static assert( isBlitAssignable!(S3X[3]));
5439     static assert( isBlitAssignable!(S3Y[3]));
5440     static assert(!isBlitAssignable!(S3Z[3]));
5441     enum ES3X : S3X { a = S3X() }
5442     enum ES3Y : S3Y { a = S3Y() }
5443     enum ES3Z : S3Z { a = S3Z() }
5444     static assert( isBlitAssignable!(ES3X));
5445     static assert( isBlitAssignable!(ES3Y));
5446     static assert(!isBlitAssignable!(ES3Z));
5447     static assert(!isBlitAssignable!(const ES3X));
5448     static assert(!isBlitAssignable!(inout ES3Y));
5449     static assert(!isBlitAssignable!(immutable ES3Z));
5450     static assert( isBlitAssignable!(ES3X[3]));
5451     static assert( isBlitAssignable!(ES3Y[3]));
5452     static assert(!isBlitAssignable!(ES3Z[3]));
5453 
5454     union U1X {       int x;       int y; }
5455     union U1Y {       int x; const int y; }
5456     union U1Z { const int x; const int y; }
5457     static assert( isBlitAssignable!(U1X));
5458     static assert( isBlitAssignable!(U1Y));
5459     static assert(!isBlitAssignable!(U1Z));
5460     static assert(!isBlitAssignable!(const U1X));
5461     static assert(!isBlitAssignable!(inout U1Y));
5462     static assert(!isBlitAssignable!(immutable U1Z));
5463     static assert( isBlitAssignable!(U1X[3]));
5464     static assert( isBlitAssignable!(U1Y[3]));
5465     static assert(!isBlitAssignable!(U1Z[3]));
5466     enum EU1X : U1X { a = U1X() }
5467     enum EU1Y : U1Y { a = U1Y() }
5468     enum EU1Z : U1Z { a = U1Z() }
5469     static assert( isBlitAssignable!(EU1X));
5470     static assert( isBlitAssignable!(EU1Y));
5471     static assert(!isBlitAssignable!(EU1Z));
5472     static assert(!isBlitAssignable!(const EU1X));
5473     static assert(!isBlitAssignable!(inout EU1Y));
5474     static assert(!isBlitAssignable!(immutable EU1Z));
5475     static assert( isBlitAssignable!(EU1X[3]));
5476     static assert( isBlitAssignable!(EU1Y[3]));
5477     static assert(!isBlitAssignable!(EU1Z[3]));
5478 
5479     struct SA
5480     {
5481         @property int[3] foo() { return [1,2,3]; }
5482         alias foo this;
5483         const int x;    // SA is not blit assignable
5484     }
5485     static assert(!isStaticArray!SA);
5486     static assert(!isBlitAssignable!(SA[3]));
5487 }
5488 
5489 
5490 /*
5491 Works like `isImplicitlyConvertible`, except this cares only about storage
5492 classes of the arguments.
5493  */
5494 private template isStorageClassImplicitlyConvertible(From, To)
5495 {
5496     alias Pointify(T) = void*;
5497 
5498     enum isStorageClassImplicitlyConvertible = is(
5499             ModifyTypePreservingTQ!(Pointify, From) :
5500             ModifyTypePreservingTQ!(Pointify,   To) );
5501 }
5502 
5503 @safe unittest
5504 {
5505     static assert( isStorageClassImplicitlyConvertible!(          int, const int));
5506     static assert( isStorageClassImplicitlyConvertible!(immutable int, const int));
5507 
5508     static assert(!isStorageClassImplicitlyConvertible!(const int,           int));
5509     static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int));
5510     static assert(!isStorageClassImplicitlyConvertible!(int, shared int));
5511     static assert(!isStorageClassImplicitlyConvertible!(shared int, int));
5512 }
5513 
5514 
5515 /**
5516 Determines whether the function type `F` is covariant with `G`, i.e.,
5517 functions of the type `F` can override ones of the type `G`.
5518  */
5519 template isCovariantWith(F, G)
5520 if (is(F == function) && is(G == function) ||
5521     is(F == delegate) && is(G == delegate) ||
5522     isFunctionPointer!F && isFunctionPointer!G)
5523 {
5524     static if (is(F : G))
5525         enum isCovariantWith = true;
5526     else
5527     {
5528         alias Upr = F;
5529         alias Lwr = G;
5530 
5531         /*
5532          * Check for calling convention: require exact match.
5533          */
5534         template checkLinkage()
5535         {
5536             enum ok = functionLinkage!Upr == functionLinkage!Lwr;
5537         }
5538         /*
5539          * Check for variadic parameter: require exact match.
5540          */
5541         template checkVariadicity()
5542         {
5543             enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr;
5544         }
5545         /*
5546          * Check for function storage class:
5547          *  - overrider can have narrower storage class than base
5548          */
5549         template checkSTC()
5550         {
5551             // Note the order of arguments.  The convertion order Lwr -> Upr is
5552             // correct since Upr should be semantically 'narrower' than Lwr.
5553             enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr);
5554         }
5555         /*
5556          * Check for function attributes:
5557          *  - require exact match for ref and @property
5558          *  - overrider can add pure and nothrow, but can't remove them
5559          *  - @safe and @trusted are covariant with each other, unremovable
5560          */
5561         template checkAttributes()
5562         {
5563             alias FA = FunctionAttribute;
5564             enum uprAtts = functionAttributes!Upr;
5565             enum lwrAtts = functionAttributes!Lwr;
5566             //
5567             enum wantExact = FA.ref_ | FA.property;
5568             enum safety = FA.safe | FA.trusted;
5569             enum ok =
5570                 (  (uprAtts & wantExact)   == (lwrAtts & wantExact)) &&
5571                 (  (uprAtts & FA.pure_   ) >= (lwrAtts & FA.pure_   )) &&
5572                 (  (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) &&
5573                 (!!(uprAtts & safety    )  >= !!(lwrAtts & safety    )) ;
5574         }
5575         /*
5576          * Check for return type: usual implicit convertion.
5577          */
5578         template checkReturnType()
5579         {
5580             enum ok = is(ReturnType!Upr : ReturnType!Lwr);
5581         }
5582         /*
5583          * Check for parameters:
5584          *  - require exact match for types
5585          *    (cf. https://issues.dlang.org/show_bug.cgi?id=3075)
5586          *  - require exact match for in, out, ref and lazy
5587          *  - overrider can add scope, but can't remove
5588          */
5589         template checkParameters()
5590         {
5591             alias STC = ParameterStorageClass;
5592             alias UprParams = Parameters!Upr;
5593             alias LwrParams = Parameters!Lwr;
5594             alias UprPSTCs  = ParameterStorageClassTuple!Upr;
5595             alias LwrPSTCs  = ParameterStorageClassTuple!Lwr;
5596             //
5597             template checkNext(size_t i)
5598             {
5599                 static if (i < UprParams.length)
5600                 {
5601                     enum uprStc = UprPSTCs[i];
5602                     enum lwrStc = LwrPSTCs[i];
5603                     //
5604                     enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_;
5605                     enum ok =
5606                         ((uprStc & wantExact )  == (lwrStc & wantExact )) &&
5607                         ((uprStc & STC.scope_)  >= (lwrStc & STC.scope_)) &&
5608                         checkNext!(i + 1).ok;
5609                 }
5610                 else
5611                     enum ok = true; // done
5612             }
5613             static if (UprParams.length == LwrParams.length)
5614                 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok;
5615             else
5616                 enum ok = false;
5617         }
5618 
5619         /* run all the checks */
5620         enum isCovariantWith =
5621             checkLinkage    !().ok &&
5622             checkVariadicity!().ok &&
5623             checkSTC        !().ok &&
5624             checkAttributes !().ok &&
5625             checkReturnType !().ok &&
5626             checkParameters !().ok ;
5627     }
5628 }
5629 
5630 ///
5631 @safe unittest
5632 {
5633     interface I { I clone(); }
5634     interface J { J clone(); }
5635     class C : I
5636     {
5637         override C clone()   // covariant overriding of I.clone()
5638         {
5639             return new C;
5640         }
5641     }
5642 
5643     // C.clone() can override I.clone(), indeed.
5644     static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
5645 
5646     // C.clone() can't override J.clone(); the return type C is not implicitly
5647     // convertible to J.
5648     static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
5649 }
5650 
5651 @safe unittest
5652 {
5653     enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g));
5654 
5655     // covariant return type
5656     interface I     {}
5657     interface J : I {}
5658     interface BaseA            {          const(I) test(int); }
5659     interface DerivA_1 : BaseA { override const(J) test(int); }
5660     interface DerivA_2 : BaseA { override       J  test(int); }
5661     static assert( isCovariantWith!(DerivA_1.test, BaseA.test));
5662     static assert( isCovariantWith!(DerivA_2.test, BaseA.test));
5663     static assert(!isCovariantWith!(BaseA.test, DerivA_1.test));
5664     static assert(!isCovariantWith!(BaseA.test, DerivA_2.test));
5665     static assert( isCovariantWith!(BaseA.test, BaseA.test));
5666     static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test));
5667     static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test));
5668 
5669      // function, function pointer and delegate
5670      J function() derived_function;
5671      I function() base_function;
5672      J delegate() derived_delegate;
5673      I delegate() base_delegate;
5674      static assert(.isCovariantWith!(typeof(derived_function), typeof(base_function)));
5675      static assert(.isCovariantWith!(typeof(*derived_function), typeof(*base_function)));
5676      static assert(.isCovariantWith!(typeof(derived_delegate), typeof(base_delegate)));
5677 
5678     // scope parameter
5679     interface BaseB            {          void test(      int*,       int*); }
5680     interface DerivB_1 : BaseB { override void test(scope int*,       int*); }
5681     interface DerivB_2 : BaseB { override void test(      int*, scope int*); }
5682     interface DerivB_3 : BaseB { override void test(scope int*, scope int*); }
5683     static assert( isCovariantWith!(DerivB_1.test, BaseB.test));
5684     static assert( isCovariantWith!(DerivB_2.test, BaseB.test));
5685     static assert( isCovariantWith!(DerivB_3.test, BaseB.test));
5686     static assert(!isCovariantWith!(BaseB.test, DerivB_1.test));
5687     static assert(!isCovariantWith!(BaseB.test, DerivB_2.test));
5688     static assert(!isCovariantWith!(BaseB.test, DerivB_3.test));
5689 
5690     // function storage class
5691     interface BaseC            {          void test()      ; }
5692     interface DerivC_1 : BaseC { override void test() const; }
5693     static assert( isCovariantWith!(DerivC_1.test, BaseC.test));
5694     static assert(!isCovariantWith!(BaseC.test, DerivC_1.test));
5695 
5696     // increasing safety
5697     interface BaseE            {          void test()         ; }
5698     interface DerivE_1 : BaseE { override void test() @safe   ; }
5699     interface DerivE_2 : BaseE { override void test() @trusted; }
5700     static assert( isCovariantWith!(DerivE_1.test, BaseE.test));
5701     static assert( isCovariantWith!(DerivE_2.test, BaseE.test));
5702     static assert(!isCovariantWith!(BaseE.test, DerivE_1.test));
5703     static assert(!isCovariantWith!(BaseE.test, DerivE_2.test));
5704 
5705     // @safe and @trusted
5706     interface BaseF
5707     {
5708         void test1() @safe;
5709         void test2() @trusted;
5710     }
5711     interface DerivF : BaseF
5712     {
5713         override void test1() @trusted;
5714         override void test2() @safe;
5715     }
5716     static assert( isCovariantWith!(DerivF.test1, BaseF.test1));
5717     static assert( isCovariantWith!(DerivF.test2, BaseF.test2));
5718 }
5719 
5720 
5721 // Needed for rvalueOf/lvalueOf because "inout on return means
5722 // inout must be on a parameter as well"
5723 private struct __InoutWorkaroundStruct{}
5724 
5725 /**
5726 Creates an lvalue or rvalue of type `T` for `typeof(...)` and
5727 $(DDSUBLINK spec/traits, compiles, `__traits(compiles, ...)`) purposes. No actual value is returned.
5728 
5729 Params:
5730     T = The type to transform
5731 
5732 Note: Trying to use returned value will result in a
5733 "Symbol Undefined" error at link time.
5734 */
5735 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5736 
5737 /// ditto
5738 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5739 
5740 // Note: can't put these unittests together as function overloads
5741 // aren't allowed inside functions.
5742 ///
5743 @system unittest
5744 {
5745     static int f(int);
5746     static assert(is(typeof(f(rvalueOf!int)) == int));
5747 }
5748 
5749 ///
5750 @system unittest
5751 {
5752     static bool f(ref int);
5753     static assert(is(typeof(f(lvalueOf!int)) == bool));
5754 }
5755 
5756 @system unittest
5757 {
5758     void needLvalue(T)(ref T);
5759     static struct S { }
5760     int i;
5761     struct Nested { void f() { ++i; } }
5762     static foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object))
5763     {
5764         static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
5765         static assert( __traits(compiles, needLvalue(lvalueOf!T)));
5766         static assert(is(typeof(rvalueOf!T) == T));
5767         static assert(is(typeof(lvalueOf!T) == T));
5768     }
5769 
5770     static assert(!__traits(compiles, rvalueOf!int = 1));
5771     static assert( __traits(compiles, lvalueOf!byte = 127));
5772     static assert(!__traits(compiles, lvalueOf!byte = 128));
5773 }
5774 
5775 
5776 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5777 // SomethingTypeOf
5778 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5779 
5780 /*
5781  */
5782 template BooleanTypeOf(T)
5783 {
5784     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5785         alias X = BooleanTypeOf!AT;
5786     else
5787         alias X = OriginalType!T;
5788 
5789     static if (is(immutable X == immutable bool))
5790     {
5791         alias BooleanTypeOf = X;
5792     }
5793     else
5794         static assert(0, T.stringof~" is not boolean type");
5795 }
5796 
5797 @safe unittest
5798 {
5799     // unexpected failure, maybe dmd type-merging bug
5800     static foreach (T; AliasSeq!bool)
5801         static foreach (Q; TypeQualifierList)
5802         {
5803             static assert( is(Q!T == BooleanTypeOf!(            Q!T  )));
5804             static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) )));
5805         }
5806 
5807     static foreach (T; AliasSeq!(void, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5808         static foreach (Q; TypeQualifierList)
5809         {
5810             static assert(!is(BooleanTypeOf!(            Q!T  )), Q!T.stringof);
5811             static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) )));
5812         }
5813 }
5814 
5815 @safe unittest
5816 {
5817     struct B
5818     {
5819         bool val;
5820         alias val this;
5821     }
5822     struct S
5823     {
5824         B b;
5825         alias b this;
5826     }
5827     static assert(is(BooleanTypeOf!B == bool));
5828     static assert(is(BooleanTypeOf!S == bool));
5829 }
5830 
5831 /*
5832  */
5833 template IntegralTypeOf(T)
5834 {
5835     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5836         alias X = IntegralTypeOf!AT;
5837     else
5838         alias X = OriginalType!T;
5839 
5840     static if (__traits(isIntegral, X) && __traits(isZeroInit, X) // Not char, wchar, or dchar.
5841         && !is(immutable X == immutable bool) && !is(X == __vector))
5842     {
5843         alias IntegralTypeOf = X;
5844     }
5845     else
5846         static assert(0, T.stringof~" is not an integral type");
5847 }
5848 
5849 @safe unittest
5850 {
5851     static foreach (T; IntegralTypeList)
5852         static foreach (Q; TypeQualifierList)
5853         {
5854             static assert( is(Q!T == IntegralTypeOf!(            Q!T  )));
5855             static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) )));
5856         }
5857 
5858     static foreach (T; AliasSeq!(void, bool, FloatingPointTypeList,
5859                 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5860         static foreach (Q; TypeQualifierList)
5861         {
5862             static assert(!is(IntegralTypeOf!(            Q!T  )));
5863             static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) )));
5864         }
5865 }
5866 
5867 /*
5868  */
5869 template FloatingPointTypeOf(T)
5870 {
5871     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5872         alias X = FloatingPointTypeOf!AT;
5873     else
5874         alias X = OriginalType!T;
5875 
5876     static if (is(immutable X == immutable U, U) && is(U == float) || is(U == double) || is(U == real))
5877     {
5878         alias FloatingPointTypeOf = X;
5879     }
5880     else
5881         static assert(0, T.stringof~" is not a floating point type");
5882 }
5883 
5884 @safe unittest
5885 {
5886     static foreach (T; FloatingPointTypeList)
5887         static foreach (Q; TypeQualifierList)
5888         {
5889             static assert( is(Q!T == FloatingPointTypeOf!(            Q!T  )));
5890             static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5891         }
5892 
5893     static foreach (T; AliasSeq!(void, bool, IntegralTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5894         static foreach (Q; TypeQualifierList)
5895         {
5896             static assert(!is(FloatingPointTypeOf!(            Q!T  )));
5897             static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5898         }
5899 }
5900 
5901 /*
5902  */
5903 template NumericTypeOf(T)
5904 {
5905     static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X))
5906     {
5907         alias NumericTypeOf = X;
5908     }
5909     else
5910         static assert(0, T.stringof~" is not a numeric type");
5911 }
5912 
5913 @safe unittest
5914 {
5915     static foreach (T; NumericTypeList)
5916         static foreach (Q; TypeQualifierList)
5917         {
5918             static assert( is(Q!T == NumericTypeOf!(            Q!T  )));
5919             static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) )));
5920         }
5921 
5922     static foreach (T; AliasSeq!(void, bool, CharTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5923         static foreach (Q; TypeQualifierList)
5924         {
5925             static assert(!is(NumericTypeOf!(            Q!T  )));
5926             static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) )));
5927         }
5928 }
5929 
5930 /*
5931  */
5932 template UnsignedTypeOf(T)
5933 {
5934     static if (is(IntegralTypeOf!T X) && __traits(isUnsigned, X))
5935         alias UnsignedTypeOf = X;
5936     else
5937         static assert(0, T.stringof~" is not an unsigned type.");
5938 }
5939 
5940 /*
5941  */
5942 template SignedTypeOf(T)
5943 {
5944     static if (is(IntegralTypeOf!T X) && !__traits(isUnsigned, X))
5945         alias SignedTypeOf = X;
5946     else static if (is(FloatingPointTypeOf!T X))
5947         alias SignedTypeOf = X;
5948     else
5949         static assert(0, T.stringof~" is not an signed type.");
5950 }
5951 
5952 /*
5953  */
5954 template CharTypeOf(T)
5955 {
5956     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5957         alias X = CharTypeOf!AT;
5958     else
5959         alias X = OriginalType!T;
5960 
5961     static if (is(immutable X == immutable U, U) && is(U == char) || is(U == wchar) || is(U == dchar))
5962     {
5963         alias CharTypeOf = X;
5964     }
5965     else
5966         static assert(0, T.stringof~" is not a character type");
5967 }
5968 
5969 @safe unittest
5970 {
5971     static foreach (T; CharTypeList)
5972         static foreach (Q; TypeQualifierList)
5973         {
5974             static assert( is(CharTypeOf!(            Q!T  )));
5975             static assert( is(CharTypeOf!( SubTypeOf!(Q!T) )));
5976         }
5977 
5978     static foreach (T; AliasSeq!(void, bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5979         static foreach (Q; TypeQualifierList)
5980         {
5981             static assert(!is(CharTypeOf!(            Q!T  )));
5982             static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5983         }
5984 
5985     static foreach (T; AliasSeq!(string, wstring, dstring, char[4]))
5986         static foreach (Q; TypeQualifierList)
5987         {
5988             static assert(!is(CharTypeOf!(            Q!T  )));
5989             static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5990         }
5991 }
5992 
5993 /*
5994  */
5995 template StaticArrayTypeOf(T)
5996 {
5997     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5998         alias X = StaticArrayTypeOf!AT;
5999     else
6000         alias X = OriginalType!T;
6001 
6002     static if (__traits(isStaticArray, X))
6003         alias StaticArrayTypeOf = X;
6004     else
6005         static assert(0, T.stringof~" is not a static array type");
6006 }
6007 
6008 @safe unittest
6009 {
6010     static foreach (T; AliasSeq!(bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6011         static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6012         {
6013             static assert(is( Q!(   T[1] ) == StaticArrayTypeOf!( Q!(              T[1]  ) ) ));
6014 
6015             static foreach (P; TypeQualifierList)
6016             { // SubTypeOf cannot have inout type
6017                 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) ));
6018             }
6019         }
6020 
6021     static foreach (T; AliasSeq!void)
6022         static foreach (Q; AliasSeq!TypeQualifierList)
6023         {
6024             static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) ));
6025         }
6026 }
6027 
6028 /*
6029  */
6030 template DynamicArrayTypeOf(T)
6031 {
6032     import core.internal.traits : _DynamicArrayTypeOf = DynamicArrayTypeOf;
6033     alias DynamicArrayTypeOf = _DynamicArrayTypeOf!T;
6034 }
6035 
6036 @safe unittest
6037 {
6038     import std.meta : Alias;
6039     static foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6040         static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6041         {
6042             static assert(is( Q!T[]  == DynamicArrayTypeOf!( Q!T[] ) ));
6043             static assert(is( Q!(T[])  == DynamicArrayTypeOf!( Q!(T[]) ) ));
6044 
6045             static foreach (P; AliasSeq!(Alias, ConstOf, ImmutableOf))
6046             {
6047                 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) ));
6048                 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) ));
6049             }
6050         }
6051 
6052     static assert(!is(DynamicArrayTypeOf!(int[3])));
6053     static assert(!is(DynamicArrayTypeOf!(void[3])));
6054     static assert(!is(DynamicArrayTypeOf!(typeof(null))));
6055 }
6056 
6057 /*
6058  */
6059 template ArrayTypeOf(T)
6060 {
6061     static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X))
6062     {
6063         alias ArrayTypeOf = X;
6064     }
6065     else
6066         static assert(0, T.stringof~" is not an array type");
6067 }
6068 
6069 /*
6070  * Converts strings and string-like types to the corresponding dynamic array of characters.
6071  * Params:
6072  * T = one of the following:
6073  * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6074  *    (`shared` is rejected)
6075  * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6076  *    (`shared` is rejected)
6077  * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3)
6078  *
6079  * Other cases are rejected with a compile time error.
6080  * `typeof(null)` is rejected.
6081  *
6082  * Returns:
6083  *  The result of `[]` applied to the qualified character type.
6084  */
6085 template StringTypeOf(T)
6086 {
6087     static if (is(T == typeof(null)))
6088     {
6089         // It is impossible to determine exact string type from typeof(null) -
6090         // it means that StringTypeOf!(typeof(null)) is undefined.
6091         // Then this behavior is convenient for template constraint.
6092         static assert(0, T.stringof~" is not a string type");
6093     }
6094     else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[]))
6095     {
6096         static if (is(T : U[], U))
6097             alias StringTypeOf = U[];
6098         else
6099             static assert(0);
6100     }
6101     else
6102         static assert(0, T.stringof~" is not a string type");
6103 }
6104 
6105 @safe unittest
6106 {
6107     import std.meta : Alias;
6108     static foreach (T; CharTypeList)
6109         static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, InoutOf))
6110         {
6111             static assert(is(Q!T[] == StringTypeOf!( Q!T[] )));
6112 
6113             static if (!__traits(isSame, Q, InoutOf))
6114             {{
6115                 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
6116 
6117                 alias Str = Q!T[];
6118                 struct C(S) { S val;  alias val this; }
6119                 static assert(is(StringTypeOf!(C!Str) == Str));
6120             }}
6121         }
6122 
6123     static foreach (T; CharTypeList)
6124         static foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf))
6125         {
6126             static assert(!is(StringTypeOf!( Q!T[] )));
6127         }
6128 }
6129 
6130 @safe unittest
6131 {
6132     static assert(is(StringTypeOf!(char[4]) == char[]));
6133 
6134     struct S
6135     {
6136         string s;
6137         alias s this;
6138     }
6139 
6140     struct T
6141     {
6142         S s;
6143         alias s this;
6144     }
6145 
6146     static assert(is(StringTypeOf!S == string));
6147     static assert(is(StringTypeOf!T == string));
6148 }
6149 
6150 /*
6151  */
6152 template AssocArrayTypeOf(T)
6153 {
6154     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6155         alias X = AssocArrayTypeOf!AT;
6156     else
6157         alias X = OriginalType!T;
6158 
6159     static if (__traits(isAssociativeArray, X))
6160     {
6161         alias AssocArrayTypeOf = X;
6162     }
6163     else
6164         static assert(0, T.stringof~" is not an associative array type");
6165 }
6166 
6167 @safe unittest
6168 {
6169     static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6170         static foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6171             static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6172                 static foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6173                 {
6174                     static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!(            P!(Q!T[R!T])  ) ));
6175                 }
6176 
6177     static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6178         static foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6179             static foreach (P; AliasSeq!TypeQualifierList)
6180                 static foreach (Q; AliasSeq!TypeQualifierList)
6181                     static foreach (R; AliasSeq!TypeQualifierList)
6182                     {
6183                         static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) ));
6184                     }
6185 }
6186 
6187 /*
6188  */
6189 template BuiltinTypeOf(T)
6190 {
6191     static if (is(T : void))
6192         alias BuiltinTypeOf = void;
6193     else
6194     {
6195         static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6196             alias X = BuiltinTypeOf!AT;
6197         else
6198             alias X = OriginalType!T;
6199         static if (__traits(isArithmetic, X) && !is(X == __vector) ||
6200                 __traits(isStaticArray, X) || is(X == E[], E) ||
6201                 __traits(isAssociativeArray, X) || is(X == typeof(null)))
6202             alias BuiltinTypeOf = X;
6203         else
6204             static assert(0);
6205     }
6206 }
6207 
6208 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6209 // isSomething
6210 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6211 
6212 /**
6213  * Detect whether `T` is a built-in boolean type or enum of boolean base type.
6214  */
6215 enum bool isBoolean(T) = __traits(isUnsigned, T) && is(T : bool);
6216 
6217 ///
6218 @safe unittest
6219 {
6220     static assert( isBoolean!bool);
6221     enum EB : bool { a = true }
6222     static assert( isBoolean!EB);
6223 
6224     struct SubTypeOfBool
6225     {
6226         bool val;
6227         alias val this;
6228     }
6229     static assert(!isBoolean!(SubTypeOfBool));
6230 }
6231 
6232 @safe unittest
6233 {
6234     static struct S(T)
6235     {
6236         T t;
6237         alias t this;
6238     }
6239     static assert(!isIntegral!(S!bool));
6240 }
6241 
6242 /**
6243  * Detect whether `T` is a built-in integral type.
6244  * Integral types are `byte`, `ubyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `cent`, `ucent`,
6245  * and enums with an integral type as its base type.
6246  * Params:
6247  *      T = type to test
6248  * Returns:
6249  *      `true` if `T` is an integral type
6250  * Note:
6251  *      this is not the same as $(LINK2 https://dlang.org/spec/traits.html#isIntegral, `__traits(isIntegral)`)
6252  */
6253 template isIntegral(T)
6254 {
6255     static if (!__traits(isIntegral, T))
6256         enum isIntegral = false;
6257     else static if (is(T U == enum))
6258         enum isIntegral = isIntegral!U;
6259     else
6260         enum isIntegral = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6261             && !is(immutable T == immutable bool) && !is(T == __vector);
6262 }
6263 
6264 ///
6265 @safe unittest
6266 {
6267     static assert(
6268         isIntegral!byte &&
6269         isIntegral!short &&
6270         isIntegral!int &&
6271         isIntegral!long &&
6272         isIntegral!(const(long)) &&
6273         isIntegral!(immutable(long))
6274     );
6275 
6276     static assert(
6277         !isIntegral!bool &&
6278         !isIntegral!char &&
6279         !isIntegral!double
6280     );
6281 
6282     // types which act as integral values do not pass
6283     struct S
6284     {
6285         int val;
6286         alias val this;
6287     }
6288 
6289     static assert(!isIntegral!S);
6290 }
6291 
6292 @safe unittest
6293 {
6294     static foreach (T; IntegralTypeList)
6295     {
6296         static foreach (Q; TypeQualifierList)
6297         {
6298             static assert( isIntegral!(Q!T));
6299             static assert(!isIntegral!(SubTypeOf!(Q!T)));
6300         }
6301     }
6302 
6303     static assert(!isIntegral!float);
6304 
6305     enum EU : uint { a = 0, b = 1, c = 2 }  // base type is unsigned
6306     // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909)
6307     enum EI : int { a = -1, b = 0, c = 1 }
6308     static assert(isIntegral!EU &&  isUnsigned!EU && !isSigned!EU);
6309     static assert(isIntegral!EI && !isUnsigned!EI &&  isSigned!EI);
6310 }
6311 
6312 /**
6313  * Detect whether `T` is a built-in floating point type.
6314  *
6315  * See also: $(DDSUBLINK spec/traits, isFloating, `__traits(isFloating, T)`)
6316  */
6317 // is(T : real) to discount complex types
6318 enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real);
6319 
6320 ///
6321 @safe unittest
6322 {
6323     static assert(
6324         isFloatingPoint!float &&
6325         isFloatingPoint!double &&
6326         isFloatingPoint!real &&
6327         isFloatingPoint!(const(real)) &&
6328         isFloatingPoint!(immutable(real))
6329     );
6330 
6331     static assert(!isFloatingPoint!int);
6332 
6333     // types which act as floating point values do not pass
6334     struct S
6335     {
6336         float val;
6337         alias val this;
6338     }
6339 
6340     static assert(!isFloatingPoint!S);
6341 }
6342 
6343 @safe unittest
6344 {
6345     enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
6346 
6347     static foreach (T; AliasSeq!(FloatingPointTypeList, EF))
6348     {
6349         static foreach (Q; TypeQualifierList)
6350         {
6351             static assert( isFloatingPoint!(Q!T));
6352             static assert(!isFloatingPoint!(SubTypeOf!(Q!T)));
6353         }
6354     }
6355     static foreach (T; IntegralTypeList)
6356     {
6357         static foreach (Q; TypeQualifierList)
6358         {
6359             static assert(!isFloatingPoint!(Q!T));
6360         }
6361     }
6362     static if (is(__vector(float[4])))
6363     {
6364         static assert(!isFloatingPoint!(__vector(float[4])));
6365     }
6366 }
6367 
6368 /**
6369  * Detect whether `T` is a built-in numeric type (integral or floating
6370  * point).
6371  */
6372 template isNumeric(T)
6373 {
6374     static if (!__traits(isArithmetic, T))
6375         enum isNumeric = false;
6376     else static if (__traits(isFloating, T))
6377         enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
6378     else static if (is(T U == enum))
6379         enum isNumeric = isNumeric!U;
6380     else
6381         enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6382             && !is(immutable T == immutable bool) && !is(T == __vector);
6383 }
6384 
6385 ///
6386 @safe unittest
6387 {
6388     static assert(
6389         isNumeric!byte &&
6390         isNumeric!short &&
6391         isNumeric!int &&
6392         isNumeric!long &&
6393         isNumeric!float &&
6394         isNumeric!double &&
6395         isNumeric!real &&
6396         isNumeric!(const(real)) &&
6397         isNumeric!(immutable(real))
6398     );
6399 
6400     static assert(
6401         !isNumeric!void &&
6402         !isNumeric!bool &&
6403         !isNumeric!char &&
6404         !isNumeric!wchar &&
6405         !isNumeric!dchar
6406     );
6407 
6408     // types which act as numeric values do not pass
6409     struct S
6410     {
6411         int val;
6412         alias val this;
6413     }
6414 
6415     static assert(!isNumeric!S);
6416 }
6417 
6418 @safe unittest
6419 {
6420     static foreach (T; AliasSeq!(NumericTypeList))
6421     {
6422         static foreach (Q; TypeQualifierList)
6423         {
6424             static assert( isNumeric!(Q!T));
6425             static assert(!isNumeric!(SubTypeOf!(Q!T)));
6426         }
6427     }
6428 
6429     static struct S(T)
6430     {
6431         T t;
6432         alias t this;
6433     }
6434     static assert(!isNumeric!(S!int));
6435 
6436     enum EChar : char { a = 0, }
6437     static assert(!isNumeric!EChar);
6438 
6439     static if (is(__vector(float[4])))
6440     {
6441         static assert(!isNumeric!(__vector(float[4])));
6442     }
6443     static if (is(__vector(int[4])))
6444     {
6445         static assert(!isNumeric!(__vector(int[4])));
6446     }
6447 
6448     static assert(!isNumeric!ifloat);
6449     static assert(!isNumeric!cfloat);
6450 }
6451 
6452 /**
6453  * Detect whether `T` is a scalar type (a built-in numeric, character or
6454  * boolean type).
6455  *
6456  * See also: $(DDSUBLINK spec/traits, isScalar, `__traits(isScalar, T)`)
6457  */
6458 // is(T : real) to discount complex types
6459 enum bool isScalarType(T) = __traits(isScalar, T) && is(T : real);
6460 
6461 ///
6462 @safe unittest
6463 {
6464     static assert(!isScalarType!void);
6465     static assert( isScalarType!(immutable(byte)));
6466     static assert( isScalarType!(immutable(ushort)));
6467     static assert( isScalarType!(immutable(int)));
6468     static assert( isScalarType!(ulong));
6469     static assert( isScalarType!(shared(float)));
6470     static assert( isScalarType!(shared(const bool)));
6471     static assert( isScalarType!(const(char)));
6472     static assert( isScalarType!(wchar));
6473     static assert( isScalarType!(const(dchar)));
6474     static assert( isScalarType!(const(double)));
6475     static assert( isScalarType!(const(real)));
6476 }
6477 
6478 @safe unittest
6479 {
6480     static struct S(T)
6481     {
6482         T t;
6483         alias t this;
6484     }
6485     static assert(!isScalarType!(S!int));
6486 }
6487 
6488 /**
6489  * Detect whether `T` is a basic type (scalar type or void).
6490  */
6491 enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void);
6492 
6493 ///
6494 @safe unittest
6495 {
6496     static assert(isBasicType!void);
6497     static assert(isBasicType!(const(void)));
6498     static assert(isBasicType!(shared(void)));
6499     static assert(isBasicType!(immutable(void)));
6500     static assert(isBasicType!(shared const(void)));
6501     static assert(isBasicType!(shared inout(void)));
6502     static assert(isBasicType!(shared inout const(void)));
6503     static assert(isBasicType!(inout(void)));
6504     static assert(isBasicType!(inout const(void)));
6505     static assert(isBasicType!(immutable(int)));
6506     static assert(isBasicType!(shared(float)));
6507     static assert(isBasicType!(shared(const bool)));
6508     static assert(isBasicType!(const(dchar)));
6509 }
6510 
6511 /**
6512  * Detect whether `T` is a built-in unsigned numeric type.
6513  */
6514 template isUnsigned(T)
6515 {
6516     static if (!__traits(isUnsigned, T))
6517         enum isUnsigned = false;
6518     else static if (is(T U == enum))
6519         enum isUnsigned = isUnsigned!U;
6520     else
6521         enum isUnsigned = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6522             && !is(immutable T == immutable bool) && !is(T == __vector);
6523 }
6524 
6525 ///
6526 @safe unittest
6527 {
6528     static assert(
6529         isUnsigned!uint &&
6530         isUnsigned!ulong
6531     );
6532 
6533     static assert(
6534         !isUnsigned!char &&
6535         !isUnsigned!int &&
6536         !isUnsigned!long &&
6537         !isUnsigned!char &&
6538         !isUnsigned!wchar &&
6539         !isUnsigned!dchar
6540     );
6541 }
6542 
6543 @safe unittest
6544 {
6545     static foreach (T; AliasSeq!(UnsignedIntTypeList))
6546     {
6547         static foreach (Q; TypeQualifierList)
6548         {
6549             static assert( isUnsigned!(Q!T));
6550             static assert(!isUnsigned!(SubTypeOf!(Q!T)));
6551         }
6552     }
6553 
6554     static struct S(T)
6555     {
6556         T t;
6557         alias t this;
6558     }
6559     static assert(!isUnsigned!(S!uint));
6560 
6561     enum EChar : char { a = 0, }
6562     static assert(!isUnsigned!EChar);
6563 
6564     static if (is(__vector(uint[4])))
6565     {
6566         static assert(!isUnsigned!(__vector(uint[4])));
6567     }
6568 }
6569 
6570 /**
6571  * Detect whether `T` is a built-in signed numeric type.
6572  */
6573 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T)
6574                                                   && is(T : real);
6575 
6576 ///
6577 @safe unittest
6578 {
6579     static assert(
6580         isSigned!int &&
6581         isSigned!long
6582     );
6583 
6584     static assert(
6585         !isSigned!uint &&
6586         !isSigned!ulong
6587     );
6588 }
6589 
6590 @safe unittest
6591 {
6592     enum E { e1 = 0 }
6593     static assert(isSigned!E);
6594 
6595     enum Eubyte : ubyte { e1 = 0 }
6596     static assert(!isSigned!Eubyte);
6597 
6598     static foreach (T; AliasSeq!(SignedIntTypeList))
6599     {
6600         static foreach (Q; TypeQualifierList)
6601         {
6602             static assert( isSigned!(Q!T));
6603             static assert(!isSigned!(SubTypeOf!(Q!T)));
6604         }
6605     }
6606 
6607     static struct S(T)
6608     {
6609         T t;
6610         alias t this;
6611     }
6612     static assert(!isSigned!(S!uint));
6613 
6614     static if (is(__vector(int[4])))
6615     {
6616         static assert(!isSigned!(__vector(int[4])));
6617     }
6618 
6619     static assert(!isSigned!ifloat);
6620     static assert(!isSigned!cfloat);
6621 }
6622 
6623 // https://issues.dlang.org/show_bug.cgi?id=17196
6624 @safe unittest
6625 {
6626     static assert(isUnsigned!bool == false);
6627     static assert(isSigned!bool == false);
6628 }
6629 
6630 /**
6631  * Detect whether `T` is one of the built-in character types.
6632  *
6633  * The built-in char types are any of `char`, `wchar` or `dchar`, with
6634  * or without qualifiers.
6635  */
6636 template isSomeChar(T)
6637 {
6638     static if (!__traits(isUnsigned, T))
6639         enum isSomeChar = false;
6640     else static if (is(T U == enum))
6641         enum isSomeChar = isSomeChar!U;
6642     else
6643         enum isSomeChar = !__traits(isZeroInit, T);
6644 }
6645 
6646 ///
6647 @safe unittest
6648 {
6649     //Char types
6650     static assert( isSomeChar!char);
6651     static assert( isSomeChar!wchar);
6652     static assert( isSomeChar!dchar);
6653     static assert( isSomeChar!(typeof('c')));
6654     static assert( isSomeChar!(immutable char));
6655     static assert( isSomeChar!(const dchar));
6656 
6657     //Non char types
6658     static assert(!isSomeChar!int);
6659     static assert(!isSomeChar!byte);
6660     static assert(!isSomeChar!string);
6661     static assert(!isSomeChar!wstring);
6662     static assert(!isSomeChar!dstring);
6663     static assert(!isSomeChar!(char[4]));
6664 }
6665 
6666 @safe unittest
6667 {
6668     enum EC : char { a = 'x', b = 'y' }
6669 
6670     static foreach (T; AliasSeq!(CharTypeList, EC))
6671     {
6672         static foreach (Q; TypeQualifierList)
6673         {
6674             static assert( isSomeChar!(            Q!T  ));
6675             static assert(!isSomeChar!( SubTypeOf!(Q!T) ));
6676         }
6677     }
6678 
6679     // alias-this types are not allowed
6680     static struct S(T)
6681     {
6682         T t;
6683         alias t this;
6684     }
6685     static assert(!isSomeChar!(S!char));
6686 }
6687 
6688 /**
6689 Detect whether `T` is one of the built-in string types.
6690 
6691 The built-in string types are `Char[]`, where `Char` is any of `char`,
6692 `wchar` or `dchar`, with or without qualifiers.
6693 
6694 Static arrays of characters (like `char[80]`) are not considered
6695 built-in string types.
6696  */
6697 enum bool isSomeString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar) || is(C == dchar));
6698 
6699 ///
6700 @safe unittest
6701 {
6702     //String types
6703     static assert( isSomeString!string);
6704     static assert( isSomeString!(wchar[]));
6705     static assert( isSomeString!(dchar[]));
6706     static assert( isSomeString!(typeof("aaa")));
6707     static assert( isSomeString!(const(char)[]));
6708 
6709     //Non string types
6710     static assert(!isSomeString!int);
6711     static assert(!isSomeString!(int[]));
6712     static assert(!isSomeString!(byte[]));
6713     static assert(!isSomeString!(typeof(null)));
6714     static assert(!isSomeString!(char[4]));
6715 
6716     enum ES : string { a = "aaa", b = "bbb" }
6717     static assert(!isSomeString!ES);
6718 
6719     static struct Stringish
6720     {
6721         string str;
6722         alias str this;
6723     }
6724     static assert(!isSomeString!Stringish);
6725 }
6726 
6727 @safe unittest
6728 {
6729     static foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring))
6730     {
6731         static assert( isSomeString!(           T ));
6732         static assert(!isSomeString!(SubTypeOf!(T)));
6733     }
6734     enum C : char { _ = 0 }
6735     static assert(!isSomeString!(C[]));
6736 }
6737 
6738 /**
6739  * Detect whether type `T` is a narrow string.
6740  *
6741  * All arrays that use char, wchar, and their qualified versions are narrow
6742  * strings. (Those include string and wstring).
6743  */
6744 enum bool isNarrowString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar));
6745 
6746 ///
6747 @safe unittest
6748 {
6749     static assert(isNarrowString!string);
6750     static assert(isNarrowString!wstring);
6751     static assert(isNarrowString!(char[]));
6752     static assert(isNarrowString!(wchar[]));
6753 
6754     static assert(!isNarrowString!dstring);
6755     static assert(!isNarrowString!(dchar[]));
6756 
6757     static assert(!isNarrowString!(typeof(null)));
6758     static assert(!isNarrowString!(char[4]));
6759 
6760     enum ES : string { a = "aaa", b = "bbb" }
6761     static assert(!isNarrowString!ES);
6762 
6763     static struct Stringish
6764     {
6765         string str;
6766         alias str this;
6767     }
6768     static assert(!isNarrowString!Stringish);
6769 }
6770 
6771 @safe unittest
6772 {
6773     import std.meta : Alias;
6774     static foreach (T; AliasSeq!(char[], string, wstring))
6775     {
6776         static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf)/*TypeQualifierList*/)
6777         {
6778             static assert( isNarrowString!(            Q!T  ));
6779             static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6780         }
6781     }
6782 
6783     static foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4]))
6784     {
6785         static foreach (Q; TypeQualifierList)
6786         {
6787             static assert(!isNarrowString!(            Q!T  ));
6788             static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6789         }
6790     }
6791     enum C : char { _ = 0 }
6792     static assert(!isNarrowString!(C[]));
6793 }
6794 
6795 /**
6796  * Detects whether `T` is a comparable type. Basic types and structs and
6797  * classes that implement opCmp are ordering comparable.
6798  */
6799 enum bool isOrderingComparable(T) = is(typeof((ref T a) => a < a ? 1 : 0));
6800 
6801 ///
6802 @safe unittest
6803 {
6804     static assert(isOrderingComparable!int);
6805     static assert(isOrderingComparable!string);
6806 
6807     static struct Foo {}
6808     static assert(!isOrderingComparable!Foo);
6809 
6810     static struct Bar
6811     {
6812         int a;
6813         auto opCmp(Bar b1) const { return a - b1.a; }
6814     }
6815 
6816     Bar b1 = Bar(5);
6817     Bar b2 = Bar(7);
6818     assert(isOrderingComparable!Bar && b2 > b1);
6819 }
6820 
6821 /// ditto
6822 enum bool isEqualityComparable(T) = is(typeof((ref T a) => a == a ? 1 : 0));
6823 
6824 @safe unittest
6825 {
6826     static assert(isEqualityComparable!int);
6827     static assert(isEqualityComparable!string);
6828     static assert(!isEqualityComparable!void);
6829 
6830     struct Foo {}
6831     static assert(isEqualityComparable!Foo);
6832 
6833     struct Bar
6834     {
6835         int a;
6836         auto opEquals(Bar b1) const { return a == b1.a; }
6837     }
6838 
6839     Bar b1 = Bar(5);
6840     Bar b2 = Bar(5);
6841     Bar b3 = Bar(7);
6842     static assert(isEqualityComparable!Bar);
6843     assert(b1 == b2);
6844     assert(b1 != b3);
6845 }
6846 
6847 /**
6848   $(RED Warning: This trait will be deprecated as soon as it is no longer used
6849                  in Phobos. For a function parameter to safely accept a type
6850                  that implicitly converts to string as a string, the conversion
6851                  needs to happen at the callsite; otherwise, the conversion is
6852                  done inside the function, and in many cases, that means that
6853                  local memory is sliced (e.g. if a static array is passed to
6854                  the function, then it's copied, and the resulting dynamic
6855                  array will be a slice of a local variable). So, if the
6856                  resulting string escapes the function, the string refers to
6857                  invalid memory, and accessing it would mean accessing invalid
6858                  memory. As such, the only safe way for a function to accept
6859                  types that implicitly convert to string is for the implicit
6860                  conversion to be done at the callsite, and that can only occur
6861                  if the parameter is explicitly typed as an array, whereas
6862                  using isConvertibleToString in a template constraint would
6863                  result in the conversion being done inside the function. As
6864                  such, isConvertibleToString is inherently unsafe and is going
6865                  to be deprecated.)
6866 
6867    Detect whether `T` is a struct, static array, or enum that is implicitly
6868    convertible to a string.
6869  */
6870 template isConvertibleToString(T)
6871 {
6872     enum isConvertibleToString =
6873         (isAggregateType!T || isStaticArray!T || is(T == enum))
6874         && is(StringTypeOf!T);
6875 }
6876 
6877 ///
6878 @safe unittest
6879 {
6880     static struct AliasedString
6881     {
6882         string s;
6883         alias s this;
6884     }
6885 
6886     enum StringEnum { a = "foo" }
6887 
6888     assert(!isConvertibleToString!string);
6889     assert(isConvertibleToString!AliasedString);
6890     assert(isConvertibleToString!StringEnum);
6891     assert(isConvertibleToString!(char[25]));
6892     assert(!isConvertibleToString!(char[]));
6893 }
6894 
6895 // https://issues.dlang.org/show_bug.cgi?id=16573
6896 @safe unittest
6897 {
6898     enum I : int { foo = 1 }
6899     enum S : string { foo = "foo" }
6900     assert(!isConvertibleToString!I);
6901     assert(isConvertibleToString!S);
6902 }
6903 
6904 package template convertToString(T)
6905 {
6906     static if (isConvertibleToString!T)
6907         alias convertToString = StringTypeOf!T;
6908     else
6909         alias convertToString = T;
6910 }
6911 
6912 /**
6913  * Detect whether type `T` is a string that will be autodecoded.
6914  *
6915  * Given a type `S` that is one of:
6916  * $(OL
6917  *  $(LI `const(char)[]`)
6918  *  $(LI `const(wchar)[]`)
6919  * )
6920  * Type `T` can be one of:
6921  * $(OL
6922  *    $(LI `S`)
6923  *    $(LI implicitly convertible to `T`)
6924  *    $(LI an enum with a base type `T`)
6925  *    $(LI an aggregate with a base type `T`)
6926  * )
6927  * with the proviso that `T` cannot be a static array.
6928  *
6929  * Params:
6930  *      T = type to be tested
6931  *
6932  * Returns:
6933  *      true if T represents a string that is subject to autodecoding
6934  *
6935  * See Also:
6936  *      $(LREF isNarrowString)
6937  */
6938 template isAutodecodableString(T)
6939 {
6940     import std.range.primitives : autodecodeStrings;
6941 
6942     enum isAutodecodableString = autodecodeStrings &&
6943         (is(T : const char[]) || is(T : const wchar[]))
6944         && !is(T : U[n], U, size_t n)
6945         && !is(immutable T : immutable noreturn[]);
6946 }
6947 
6948 ///
6949 @safe unittest
6950 {
6951     static struct Stringish
6952     {
6953         string s;
6954         alias s this;
6955     }
6956     static assert(isAutodecodableString!wstring);
6957     static assert(isAutodecodableString!Stringish);
6958     static assert(!isAutodecodableString!dstring);
6959 
6960     enum E : const(char)[3] { X = "abc" }
6961     enum F : const(char)[] { X = "abc" }
6962     enum G : F { X = F.init }
6963 
6964     static assert(isAutodecodableString!(char[]));
6965     static assert(!isAutodecodableString!(E));
6966     static assert(isAutodecodableString!(F));
6967     static assert(isAutodecodableString!(G));
6968 
6969     struct Stringish2
6970     {
6971         Stringish s;
6972         alias s this;
6973     }
6974 
6975     enum H : Stringish { X = Stringish() }
6976     enum I : Stringish2 { X = Stringish2() }
6977 
6978     static assert(isAutodecodableString!(H));
6979     static assert(isAutodecodableString!(I));
6980 
6981     static assert(!isAutodecodableString!(noreturn[]));
6982     static assert(!isAutodecodableString!(immutable(noreturn)[]));
6983 }
6984 
6985 /**
6986  * Detect whether type `T` is a static array.
6987  *
6988  * See also: $(DDSUBLINK spec/traits, isStaticArray, `__traits(isStaticArray, T)`)
6989  */
6990 enum bool isStaticArray(T) = __traits(isStaticArray, T);
6991 
6992 ///
6993 @safe unittest
6994 {
6995     static assert( isStaticArray!(int[3]));
6996     static assert( isStaticArray!(const(int)[5]));
6997     static assert( isStaticArray!(const(int)[][5]));
6998 
6999     static assert(!isStaticArray!(const(int)[]));
7000     static assert(!isStaticArray!(immutable(int)[]));
7001     static assert(!isStaticArray!(const(int)[4][]));
7002     static assert(!isStaticArray!(int[]));
7003     static assert(!isStaticArray!(int[char]));
7004     static assert(!isStaticArray!(int[1][]));
7005     static assert(!isStaticArray!(int[int]));
7006     static assert(!isStaticArray!int);
7007 }
7008 
7009 @safe unittest
7010 {
7011     static foreach (T; AliasSeq!(int[51], int[][2],
7012                            char[][int][11], immutable char[13u],
7013                            const(real)[1], const(real)[1][1], void[0]))
7014     {
7015         static foreach (Q; TypeQualifierList)
7016         {
7017             static assert( isStaticArray!(            Q!T  ));
7018             static assert(!isStaticArray!( SubTypeOf!(Q!T) ));
7019         }
7020     }
7021 
7022     //enum ESA : int[1] { a = [1], b = [2] }
7023     //static assert( isStaticArray!ESA);
7024 }
7025 
7026 /**
7027  * Detect whether type `T` is a dynamic array.
7028  */
7029 template isDynamicArray(T)
7030 {
7031     static if (is(T == U[], U))
7032         enum bool isDynamicArray = true;
7033     else static if (is(T U == enum))
7034         // BUG: isDynamicArray / isStaticArray considers enums
7035         // with appropriate base types as dynamic/static arrays
7036         // Retain old behaviour for now, see
7037         // https://github.com/dlang/phobos/pull/7574
7038         enum bool isDynamicArray = isDynamicArray!U;
7039     else
7040         enum bool isDynamicArray = false;
7041 }
7042 
7043 ///
7044 @safe unittest
7045 {
7046     static assert( isDynamicArray!(int[]));
7047     static assert( isDynamicArray!(string));
7048     static assert( isDynamicArray!(long[3][]));
7049 
7050     static assert(!isDynamicArray!(int[5]));
7051     static assert(!isDynamicArray!(typeof(null)));
7052 }
7053 
7054 @safe unittest
7055 {
7056     import std.meta : AliasSeq;
7057     static foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
7058     {
7059         static foreach (Q; TypeQualifierList)
7060         {
7061             static assert( isDynamicArray!(            Q!T  ));
7062             static assert(!isDynamicArray!( SubTypeOf!(Q!T) ));
7063         }
7064     }
7065 
7066     static assert(!isDynamicArray!(int[5]));
7067 
7068     static struct AliasThis
7069     {
7070         int[] values;
7071         alias values this;
7072     }
7073 
7074     static assert(!isDynamicArray!AliasThis);
7075 
7076     // https://github.com/dlang/phobos/pull/7574/files#r464115492
7077     enum E : string
7078     {
7079         a = "a",
7080         b = "b",
7081     }
7082     static assert( isDynamicArray!E);
7083 }
7084 
7085 /**
7086  * Detect whether type `T` is an array (static or dynamic; for associative
7087  *  arrays see $(LREF isAssociativeArray)).
7088  */
7089 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;
7090 
7091 ///
7092 @safe unittest
7093 {
7094     static assert( isArray!(int[]));
7095     static assert( isArray!(int[5]));
7096     static assert( isArray!(string));
7097 
7098     static assert(!isArray!uint);
7099     static assert(!isArray!(uint[uint]));
7100     static assert(!isArray!(typeof(null)));
7101 }
7102 
7103 @safe unittest
7104 {
7105     import std.meta : AliasSeq;
7106     static foreach (T; AliasSeq!(int[], int[5], void[]))
7107     {
7108         static foreach (Q; TypeQualifierList)
7109         {
7110             static assert( isArray!(Q!T));
7111             static assert(!isArray!(SubTypeOf!(Q!T)));
7112         }
7113     }
7114 }
7115 
7116 /**
7117  * Detect whether `T` is an associative array type
7118  *
7119  * See also: $(DDSUBLINK spec/traits, isAssociativeArray, `__traits(isAssociativeArray, T)`)
7120  */
7121 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
7122 
7123 ///
7124 @safe unittest
7125 {
7126     struct S;
7127 
7128     static assert( isAssociativeArray!(int[string]));
7129     static assert( isAssociativeArray!(S[S]));
7130     static assert(!isAssociativeArray!(string[]));
7131     static assert(!isAssociativeArray!S);
7132     static assert(!isAssociativeArray!(int[4]));
7133 }
7134 
7135 @safe unittest
7136 {
7137     struct Foo
7138     {
7139         @property uint[] keys()   { return null; }
7140         @property uint[] values() { return null; }
7141     }
7142 
7143     static foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int]))
7144     {
7145         static foreach (Q; TypeQualifierList)
7146         {
7147             static assert( isAssociativeArray!(Q!T));
7148             static assert(!isAssociativeArray!(SubTypeOf!(Q!T)));
7149         }
7150     }
7151 
7152     static assert(!isAssociativeArray!Foo);
7153     static assert(!isAssociativeArray!int);
7154     static assert(!isAssociativeArray!(int[]));
7155     static assert(!isAssociativeArray!(typeof(null)));
7156 
7157     //enum EAA : int[int] { a = [1:1], b = [2:2] }
7158     //static assert( isAssociativeArray!EAA);
7159 }
7160 
7161 /**
7162  * Detect whether type `T` is a builtin type.
7163  */
7164 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T;
7165 
7166 ///
7167 @safe unittest
7168 {
7169     class C;
7170     union U;
7171     struct S;
7172     interface I;
7173 
7174     static assert( isBuiltinType!void);
7175     static assert( isBuiltinType!string);
7176     static assert( isBuiltinType!(int[]));
7177     static assert( isBuiltinType!(C[string]));
7178     static assert( isBuiltinType!(typeof(null)));
7179     static assert(!isBuiltinType!C);
7180     static assert(!isBuiltinType!U);
7181     static assert(!isBuiltinType!S);
7182     static assert(!isBuiltinType!I);
7183     static assert(!isBuiltinType!(void delegate(int)));
7184 }
7185 
7186 /**
7187  * Detect whether type `T` is a SIMD vector type.
7188  */
7189 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
7190 
7191 ///
7192 @safe unittest
7193 {
7194     static if (is(__vector(float[4])))
7195     {
7196         alias SimdVec = __vector(float[4]);
7197         static assert(isSIMDVector!(__vector(float[4])));
7198         static assert(isSIMDVector!SimdVec);
7199     }
7200     static assert(!isSIMDVector!uint);
7201     static assert(!isSIMDVector!(float[4]));
7202 }
7203 
7204 /**
7205  * Detect whether type `T` is a pointer.
7206  */
7207 enum bool isPointer(T) = is(T == U*, U);
7208 
7209 ///
7210 @safe unittest
7211 {
7212     void fun();
7213 
7214     static assert( isPointer!(int*));
7215     static assert( isPointer!(int function()));
7216     static assert(!isPointer!int);
7217     static assert(!isPointer!string);
7218     static assert(!isPointer!(typeof(null)));
7219     static assert(!isPointer!(typeof(fun)));
7220     static assert(!isPointer!(int delegate()));
7221 }
7222 
7223 @safe unittest
7224 {
7225     static foreach (T; AliasSeq!(int*, void*, char[]*))
7226     {
7227         static foreach (Q; TypeQualifierList)
7228         {
7229             static assert( isPointer!(Q!T));
7230             static assert(!isPointer!(SubTypeOf!(Q!T)));
7231         }
7232     }
7233 
7234     static assert(!isPointer!uint);
7235     static assert(!isPointer!(uint[uint]));
7236     static assert(!isPointer!(char[]));
7237     static assert(!isPointer!(typeof(null)));
7238 }
7239 
7240 /**
7241 Returns the target type of a pointer.
7242 */
7243 alias PointerTarget(T : T*) = T;
7244 
7245 ///
7246 @safe unittest
7247 {
7248     static assert(is(PointerTarget!(int*) == int));
7249     static assert(is(PointerTarget!(void*) == void));
7250 }
7251 
7252 /**
7253  * Detect whether type `T` is an aggregate type.
7254  */
7255 template isAggregateType(T)
7256 {
7257     static if (is(T == enum))
7258         enum isAggregateType = isAggregateType!(OriginalType!T);
7259     else
7260         enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union);
7261 }
7262 
7263 ///
7264 @safe unittest
7265 {
7266     class C {}
7267     union U {}
7268     struct S {}
7269     interface I {}
7270 
7271     static assert( isAggregateType!C);
7272     static assert( isAggregateType!U);
7273     static assert( isAggregateType!S);
7274     static assert( isAggregateType!I);
7275     static assert(!isAggregateType!void);
7276     static assert(!isAggregateType!string);
7277     static assert(!isAggregateType!(int[]));
7278     static assert(!isAggregateType!(C[string]));
7279     static assert(!isAggregateType!(void delegate(int)));
7280 
7281     enum ES : S { a = S.init }
7282     enum EC : C { a = C.init }
7283     enum EI : I { a = I.init }
7284     enum EU : U { a = U.init }
7285 
7286     static assert( isAggregateType!ES);
7287     static assert( isAggregateType!EC);
7288     static assert( isAggregateType!EI);
7289     static assert( isAggregateType!EU);
7290 }
7291 
7292 /**
7293  * Returns `true` if T can be iterated over using a `foreach` loop with
7294  * a single loop variable of automatically inferred type, regardless of how
7295  * the `foreach` loop is implemented.  This includes ranges, structs/classes
7296  * that define `opApply` with a single loop variable, and builtin dynamic,
7297  * static and associative arrays.
7298  */
7299 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} }));
7300 
7301 ///
7302 @safe unittest
7303 {
7304     struct OpApply
7305     {
7306         int opApply(scope int delegate(ref uint) dg) { assert(0); }
7307     }
7308 
7309     struct Range
7310     {
7311         @property uint front() { assert(0); }
7312         void popFront() { assert(0); }
7313         enum bool empty = false;
7314     }
7315 
7316     static assert( isIterable!(uint[]));
7317     static assert( isIterable!OpApply);
7318     static assert( isIterable!(uint[string]));
7319     static assert( isIterable!Range);
7320 
7321     static assert(!isIterable!uint);
7322 }
7323 
7324 /**
7325  * Returns true if T is not const or immutable.  Note that isMutable is true for
7326  * string, or immutable(char)[], because the 'head' is mutable.
7327  */
7328 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout);
7329 
7330 ///
7331 @safe unittest
7332 {
7333     static assert( isMutable!int);
7334     static assert( isMutable!string);
7335     static assert( isMutable!(shared int));
7336     static assert( isMutable!(shared const(int)[]));
7337 
7338     static assert(!isMutable!(const int));
7339     static assert(!isMutable!(inout int));
7340     static assert(!isMutable!(shared(const int)));
7341     static assert(!isMutable!(shared(inout int)));
7342     static assert(!isMutable!(immutable string));
7343 }
7344 
7345 /**
7346  * Returns true if T is an instance of the template S.
7347  */
7348 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
7349 /// ditto
7350 template isInstanceOf(alias S, alias T)
7351 {
7352     enum impl(alias T : S!Args, Args...) = true;
7353     enum impl(alias T) = false;
7354     enum isInstanceOf = impl!T;
7355 }
7356 
7357 ///
7358 @safe unittest
7359 {
7360     static struct Foo(T...) { }
7361     static struct Bar(T...) { }
7362     static struct Doo(T) { }
7363     static struct ABC(int x) { }
7364     static void fun(T)() { }
7365     template templ(T) { }
7366 
7367     static assert(isInstanceOf!(Foo, Foo!int));
7368     static assert(!isInstanceOf!(Foo, Bar!int));
7369     static assert(!isInstanceOf!(Foo, int));
7370     static assert(isInstanceOf!(Doo, Doo!int));
7371     static assert(isInstanceOf!(ABC, ABC!1));
7372     static assert(!isInstanceOf!(Foo, Foo));
7373     static assert(isInstanceOf!(fun, fun!int));
7374     static assert(isInstanceOf!(templ, templ!int));
7375 }
7376 
7377 /**
7378  * To use `isInstanceOf` to check the identity of a template while inside of said
7379  * template, use $(LREF TemplateOf).
7380  */
7381 @safe unittest
7382 {
7383     static struct A(T = void)
7384     {
7385         // doesn't work as expected, only accepts A when T = void
7386         void func(B)(B b)
7387         if (isInstanceOf!(A, B)) {}
7388 
7389         // correct behavior
7390         void method(B)(B b)
7391         if (isInstanceOf!(TemplateOf!(A), B)) {}
7392     }
7393 
7394     A!(void) a1;
7395     A!(void) a2;
7396     A!(int) a3;
7397 
7398     static assert(!__traits(compiles, a1.func(a3)));
7399     static assert( __traits(compiles, a1.method(a2)));
7400     static assert( __traits(compiles, a1.method(a3)));
7401 }
7402 
7403 @safe unittest
7404 {
7405     static void fun1(T)() { }
7406     static void fun2(T)() { }
7407     template templ1(T) { }
7408     template templ2(T) { }
7409 
7410     static assert(!isInstanceOf!(fun1, fun2!int));
7411     static assert(!isInstanceOf!(templ1, templ2!int));
7412 }
7413 
7414 /**
7415  * Check whether the tuple T is an expression tuple.
7416  * An expression tuple only contains expressions.
7417  *
7418  * See_Also: $(LREF isTypeTuple).
7419  */
7420 template isExpressions(T...)
7421 {
7422     static foreach (Ti; T)
7423     {
7424         static if (!is(typeof(isExpressions) == bool) && // not yet defined
7425                    (is(Ti) || !__traits(compiles, { auto ex = Ti; })))
7426         {
7427             enum isExpressions = false;
7428         }
7429     }
7430     static if (!is(typeof(isExpressions) == bool)) // if not yet defined
7431     {
7432         enum isExpressions = true;
7433     }
7434 }
7435 
7436 ///
7437 @safe unittest
7438 {
7439     static assert(isExpressions!(1, 2.0, "a"));
7440     static assert(!isExpressions!(int, double, string));
7441     static assert(!isExpressions!(int, 2.0, "a"));
7442 }
7443 
7444 /**
7445  * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
7446  */
7447 
7448 alias isExpressionTuple = isExpressions;
7449 
7450 @safe unittest
7451 {
7452     void foo();
7453     static int bar() { return 42; }
7454     immutable aa = [ 1: -1 ];
7455     alias myint = int;
7456 
7457     static assert( isExpressionTuple!(42));
7458     static assert( isExpressionTuple!aa);
7459     static assert( isExpressionTuple!("cattywampus", 2.7, aa));
7460     static assert( isExpressionTuple!(bar()));
7461 
7462     static assert(!isExpressionTuple!isExpressionTuple);
7463     static assert(!isExpressionTuple!foo);
7464     static assert(!isExpressionTuple!( (a) { } ));
7465     static assert(!isExpressionTuple!int);
7466     static assert(!isExpressionTuple!myint);
7467 }
7468 
7469 
7470 /**
7471  * Check whether the tuple `T` is a type tuple.
7472  * A type tuple only contains types.
7473  *
7474  * See_Also: $(LREF isExpressions).
7475  */
7476 enum isTypeTuple(T...) =
7477 {
7478     static foreach (U; T)
7479         static if (!is(U))
7480             if (__ctfe)
7481                 return false;
7482     return true;
7483 }();
7484 
7485 ///
7486 @safe unittest
7487 {
7488     static assert(isTypeTuple!(int, float, string));
7489     static assert(!isTypeTuple!(1, 2.0, "a"));
7490     static assert(!isTypeTuple!(1, double, string));
7491 }
7492 
7493 @safe unittest
7494 {
7495     class C {}
7496     void func(int) {}
7497     auto c = new C;
7498     enum CONST = 42;
7499 
7500     static assert( isTypeTuple!int);
7501     static assert( isTypeTuple!string);
7502     static assert( isTypeTuple!C);
7503     static assert( isTypeTuple!(typeof(func)));
7504     static assert( isTypeTuple!(int, char, double));
7505 
7506     static assert(!isTypeTuple!c);
7507     static assert(!isTypeTuple!isTypeTuple);
7508     static assert(!isTypeTuple!CONST);
7509 }
7510 
7511 
7512 /**
7513 Detect whether symbol or type `T` is a function pointer.
7514  */
7515 enum bool isFunctionPointer(alias T) = is(typeof(*T) == function);
7516 
7517 ///
7518 @safe unittest
7519 {
7520     static void foo() {}
7521     void bar() {}
7522 
7523     auto fpfoo = &foo;
7524     static assert( isFunctionPointer!fpfoo);
7525     static assert( isFunctionPointer!(void function()));
7526 
7527     auto dgbar = &bar;
7528     static assert(!isFunctionPointer!dgbar);
7529     static assert(!isFunctionPointer!(void delegate()));
7530     static assert(!isFunctionPointer!foo);
7531     static assert(!isFunctionPointer!bar);
7532 
7533     static assert( isFunctionPointer!((int a) {}));
7534 }
7535 
7536 /**
7537 Detect whether symbol or type `T` is a delegate.
7538 */
7539 enum bool isDelegate(alias T) = is(typeof(T) == delegate) || is(T == delegate);
7540 
7541 ///
7542 @safe unittest
7543 {
7544     static void sfunc() { }
7545     int x;
7546     void func() { x++; }
7547 
7548     int delegate() dg;
7549     assert(isDelegate!dg);
7550     assert(isDelegate!(int delegate()));
7551     assert(isDelegate!(typeof(&func)));
7552 
7553     int function() fp;
7554     assert(!isDelegate!fp);
7555     assert(!isDelegate!(int function()));
7556     assert(!isDelegate!(typeof(&sfunc)));
7557 }
7558 
7559 /**
7560 Detect whether symbol or type `T` is a function, a function pointer or a delegate.
7561 
7562 Params:
7563     T = The type to check
7564 Returns:
7565     A `bool`
7566  */
7567 enum bool isSomeFunction(alias T) =
7568     is(T == return) ||
7569     is(typeof(T) == return) ||
7570     is(typeof(&T) == return); // @property
7571 
7572 ///
7573 @safe unittest
7574 {
7575     static real func(ref int) { return 0; }
7576     static void prop() @property { }
7577     class C
7578     {
7579         real method(ref int) { return 0; }
7580         real prop() @property { return 0; }
7581     }
7582     auto c = new C;
7583     auto fp = &func;
7584     auto dg = &c.method;
7585 
7586     static assert( isSomeFunction!func);
7587     static assert( isSomeFunction!prop);
7588     static assert( isSomeFunction!(C.method));
7589     static assert( isSomeFunction!(C.prop));
7590     static assert( isSomeFunction!(c.prop));
7591     static assert( isSomeFunction!fp);
7592     static assert( isSomeFunction!dg);
7593 
7594     real val;
7595     static assert(!isSomeFunction!int);
7596     static assert(!isSomeFunction!val);
7597 }
7598 
7599 @safe unittest
7600 {
7601     void nestedFunc() { }
7602     void nestedProp() @property { }
7603     static assert(isSomeFunction!nestedFunc);
7604     static assert(isSomeFunction!nestedProp);
7605     static assert(isSomeFunction!(real function(ref int)));
7606     static assert(isSomeFunction!(real delegate(ref int)));
7607     static assert(isSomeFunction!((int a) { return a; }));
7608     static assert(!isSomeFunction!isSomeFunction);
7609 }
7610 
7611 /**
7612 Detect whether `T` is a callable object, which can be called with the
7613 function call operator `$(LPAREN)...$(RPAREN)`.
7614  */
7615 template isCallable(alias callable)
7616 {
7617     static if (is(typeof(&callable.opCall) == delegate))
7618         // T is a object which has a member function opCall().
7619         enum bool isCallable = true;
7620     else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
7621         // T is a type which has a static member function opCall().
7622         enum bool isCallable = true;
7623     else static if (is(typeof(&callable.opCall!()) TemplateInstanceType))
7624     {
7625         enum bool isCallable = isCallable!TemplateInstanceType;
7626     }
7627     else static if (is(typeof(&callable!()) TemplateInstanceType))
7628     {
7629         enum bool isCallable = isCallable!TemplateInstanceType;
7630     }
7631     else
7632     {
7633         enum bool isCallable = isSomeFunction!callable;
7634     }
7635 }
7636 
7637 /// Functions, lambdas, and aggregate types with (static) opCall.
7638 @safe unittest
7639 {
7640     void f() { }
7641     int g(int x) { return x; }
7642 
7643     static assert( isCallable!f);
7644     static assert( isCallable!g);
7645 
7646     class C { int opCall(int) { return 0; } }
7647     auto c = new C;
7648     struct S { static int opCall(int) { return 0; } }
7649     interface I { real value() @property; }
7650 
7651     static assert( isCallable!c);
7652     static assert( isCallable!(c.opCall));
7653     static assert( isCallable!S);
7654     static assert( isCallable!(I.value));
7655     static assert( isCallable!((int a) { return a; }));
7656 
7657     static assert(!isCallable!I);
7658 }
7659 
7660 /// Templates
7661 @safe unittest
7662 {
7663     void f()() { }
7664     T g(T = int)(T x) { return x; }
7665     struct S1 { static void opCall()() { } }
7666     struct S2 { static T opCall(T = int)(T x) {return x; } }
7667 
7668     static assert( isCallable!f);
7669     static assert( isCallable!g);
7670     static assert( isCallable!S1);
7671     static assert( isCallable!S2);
7672 }
7673 
7674 /// Overloaded functions and function templates.
7675 @safe unittest
7676 {
7677     static struct Wrapper
7678     {
7679         void f() { }
7680         int f(int x) { return x; }
7681 
7682         void g()() { }
7683         T g(T = int)(T x) { return x; }
7684     }
7685 
7686     static assert(isCallable!(Wrapper.f));
7687     static assert(isCallable!(Wrapper.g));
7688 }
7689 
7690 
7691 /**
7692 Detect whether `S` is an abstract function.
7693 
7694 See also: $(DDSUBLINK spec/traits, isAbstractFunction, `__traits(isAbstractFunction, S)`)
7695 Params:
7696     S = The symbol to check
7697 Returns:
7698     A `bool`
7699  */
7700 enum isAbstractFunction(alias S) = __traits(isAbstractFunction, S);
7701 
7702 ///
7703 @safe unittest
7704 {
7705     struct S { void foo() { } }
7706     class C { void foo() { } }
7707     class AC { abstract void foo(); }
7708     static assert(!isAbstractFunction!(int));
7709     static assert(!isAbstractFunction!(S.foo));
7710     static assert(!isAbstractFunction!(C.foo));
7711     static assert( isAbstractFunction!(AC.foo));
7712 }
7713 
7714 /**
7715  * Detect whether `S` is a final function.
7716  *
7717  * See also: $(DDSUBLINK spec/traits, isFinalFunction, `__traits(isFinalFunction, S)`)
7718  */
7719 enum isFinalFunction(alias S) = __traits(isFinalFunction, S);
7720 
7721 ///
7722 @safe unittest
7723 {
7724     struct S { void bar() { } }
7725     final class FC { void foo(); }
7726     class C
7727     {
7728         void bar() { }
7729         final void foo();
7730     }
7731     static assert(!isFinalFunction!(int));
7732     static assert(!isFinalFunction!(S.bar));
7733     static assert( isFinalFunction!(FC.foo));
7734     static assert(!isFinalFunction!(C.bar));
7735     static assert( isFinalFunction!(C.foo));
7736 }
7737 
7738 /**
7739 Determines if `f` is a function that requires a context pointer.
7740 
7741 Params:
7742     f = The type to check
7743 Returns
7744     A `bool`
7745 */
7746 template isNestedFunction(alias f)
7747 {
7748     enum isNestedFunction = __traits(isNested, f) && isSomeFunction!(f);
7749 }
7750 
7751 ///
7752 @safe unittest
7753 {
7754     static void f() {}
7755     static void fun()
7756     {
7757         int i;
7758         int f() { return i; }
7759 
7760         static assert(isNestedFunction!(f));
7761     }
7762 
7763     static assert(!isNestedFunction!f);
7764 }
7765 
7766 // https://issues.dlang.org/show_bug.cgi?id=18669
7767 @safe unittest
7768 {
7769     static class Outer
7770     {
7771         class Inner
7772         {
7773         }
7774     }
7775     int i;
7776     struct SS
7777     {
7778         int bar() { return i; }
7779     }
7780     static assert(!isNestedFunction!(Outer.Inner));
7781     static assert(!isNestedFunction!(SS));
7782 }
7783 
7784 /**
7785  * Detect whether `S` is an abstract class.
7786  *
7787  * See also: $(DDSUBLINK spec/traits, isAbstractClass, `__traits(isAbstractClass, S)`)
7788  */
7789 enum isAbstractClass(alias S) = __traits(isAbstractClass, S);
7790 
7791 ///
7792 @safe unittest
7793 {
7794     struct S { }
7795     class C { }
7796     abstract class AC { }
7797     static assert(!isAbstractClass!S);
7798     static assert(!isAbstractClass!C);
7799     static assert( isAbstractClass!AC);
7800     C c;
7801     static assert(!isAbstractClass!c);
7802     AC ac;
7803     static assert( isAbstractClass!ac);
7804 }
7805 
7806 /**
7807  * Detect whether `S` is a final class.
7808  *
7809  * See also: $(DDSUBLINK spec/traits, isFinalClass, `__traits(isFinalClass, S)`)
7810  */
7811 enum isFinalClass(alias S) = __traits(isFinalClass, S);
7812 
7813 ///
7814 @safe unittest
7815 {
7816     class C { }
7817     abstract class AC { }
7818     final class FC1 : C { }
7819     final class FC2 { }
7820     static assert(!isFinalClass!C);
7821     static assert(!isFinalClass!AC);
7822     static assert( isFinalClass!FC1);
7823     static assert( isFinalClass!FC2);
7824     C c;
7825     static assert(!isFinalClass!c);
7826     FC1 fc1;
7827     static assert( isFinalClass!fc1);
7828 }
7829 
7830 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7831 // General Types
7832 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7833 
7834 version (StdDdoc)
7835 {
7836     /**
7837        Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
7838     */
7839     template Unconst(T)
7840     {
7841         import core.internal.traits : CoreUnconst = Unconst;
7842         alias Unconst = CoreUnconst!(T);
7843     }
7844 }
7845 else
7846 {
7847     import core.internal.traits : CoreUnconst = Unconst;
7848     alias Unconst = CoreUnconst;
7849 }
7850 
7851 ///
7852 @safe unittest
7853 {
7854     static assert(is(Unconst!int == int));
7855     static assert(is(Unconst!(const int) == int));
7856     static assert(is(Unconst!(immutable int) == int));
7857     static assert(is(Unconst!(shared int) == shared int));
7858     static assert(is(Unconst!(shared(const int)) == shared int));
7859 }
7860 
7861 @safe unittest
7862 {
7863     static assert(is(Unconst!(                   int) == int));
7864     static assert(is(Unconst!(             const int) == int));
7865     static assert(is(Unconst!(       inout       int) == int));
7866     static assert(is(Unconst!(       inout const int) == int));
7867     static assert(is(Unconst!(shared             int) == shared int));
7868     static assert(is(Unconst!(shared       const int) == shared int));
7869     static assert(is(Unconst!(shared inout       int) == shared int));
7870     static assert(is(Unconst!(shared inout const int) == shared int));
7871     static assert(is(Unconst!(         immutable int) == int));
7872 
7873     alias ImmIntArr = immutable(int[]);
7874     static assert(is(Unconst!ImmIntArr == immutable(int)[]));
7875 }
7876 
7877 /++
7878     Removes `shared` qualifier, if any, from type `T`.
7879 
7880     Note that while `immutable` is implicitly `shared`, it is unaffected by
7881     Unshared. Only explict `shared` is removed.
7882   +/
7883 template Unshared(T)
7884 {
7885     static if (is(T == shared U, U))
7886         alias Unshared = U;
7887     else
7888         alias Unshared = T;
7889 }
7890 
7891 ///
7892 @safe unittest
7893 {
7894     static assert(is(Unshared!int == int));
7895     static assert(is(Unshared!(const int) == const int));
7896     static assert(is(Unshared!(immutable int) == immutable int));
7897 
7898     static assert(is(Unshared!(shared int) == int));
7899     static assert(is(Unshared!(shared(const int)) == const int));
7900 
7901     static assert(is(Unshared!(shared(int[])) == shared(int)[]));
7902 }
7903 
7904 @safe unittest
7905 {
7906     static assert(is(Unshared!(                   int) == int));
7907     static assert(is(Unshared!(             const int) == const int));
7908     static assert(is(Unshared!(       inout       int) == inout int));
7909     static assert(is(Unshared!(       inout const int) == inout const int));
7910     static assert(is(Unshared!(shared             int) == int));
7911     static assert(is(Unshared!(shared       const int) == const int));
7912     static assert(is(Unshared!(shared inout       int) == inout int));
7913     static assert(is(Unshared!(shared inout const int) == inout const int));
7914     static assert(is(Unshared!(         immutable int) == immutable int));
7915 }
7916 
7917 version (StdDdoc)
7918 {
7919     /**
7920        Removes all qualifiers, if any, from type `T`.
7921     */
7922     template Unqual(T)
7923     {
7924         import core.internal.traits : CoreUnqual = Unqual;
7925         alias Unqual = CoreUnqual!(T);
7926     }
7927 }
7928 else
7929 {
7930     import core.internal.traits : CoreUnqual = Unqual;
7931     alias Unqual = CoreUnqual;
7932 }
7933 
7934 ///
7935 @safe unittest
7936 {
7937     static assert(is(Unqual!int == int));
7938     static assert(is(Unqual!(const int) == int));
7939     static assert(is(Unqual!(immutable int) == int));
7940     static assert(is(Unqual!(shared int) == int));
7941     static assert(is(Unqual!(shared(const int)) == int));
7942 }
7943 
7944 @safe unittest
7945 {
7946     static assert(is(Unqual!(                   int) == int));
7947     static assert(is(Unqual!(             const int) == int));
7948     static assert(is(Unqual!(       inout       int) == int));
7949     static assert(is(Unqual!(       inout const int) == int));
7950     static assert(is(Unqual!(shared             int) == int));
7951     static assert(is(Unqual!(shared       const int) == int));
7952     static assert(is(Unqual!(shared inout       int) == int));
7953     static assert(is(Unqual!(shared inout const int) == int));
7954     static assert(is(Unqual!(         immutable int) == int));
7955 
7956     alias ImmIntArr = immutable(int[]);
7957     static assert(is(Unqual!ImmIntArr == immutable(int)[]));
7958 }
7959 
7960 // [For internal use]
7961 package template ModifyTypePreservingTQ(alias Modifier, T)
7962 {
7963     import core.internal.traits : _ModifyTypePreservingTQ = ModifyTypePreservingTQ;
7964     alias ModifyTypePreservingTQ = _ModifyTypePreservingTQ!(Modifier, T);
7965 }
7966 
7967 /**
7968  * Copies type qualifiers from `FromType` to `ToType`.
7969  *
7970  * Supported type qualifiers:
7971  * $(UL
7972  *     $(LI `const`)
7973  *     $(LI `inout`)
7974  *     $(LI `immutable`)
7975  *     $(LI `shared`)
7976  * )
7977  */
7978 template CopyTypeQualifiers(FromType, ToType)
7979 {
7980     alias T(U) = ToType;
7981     alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType);
7982 }
7983 
7984 ///
7985 @safe unittest
7986 {
7987     static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
7988 }
7989 
7990 @safe unittest
7991 {
7992     static assert(is(CopyTypeQualifiers!(                   real, int) ==                    int));
7993     static assert(is(CopyTypeQualifiers!(             const real, int) ==              const int));
7994     static assert(is(CopyTypeQualifiers!(       inout       real, int) ==        inout       int));
7995     static assert(is(CopyTypeQualifiers!(       inout const real, int) ==        inout const int));
7996     static assert(is(CopyTypeQualifiers!(shared             real, int) == shared             int));
7997     static assert(is(CopyTypeQualifiers!(shared       const real, int) == shared       const int));
7998     static assert(is(CopyTypeQualifiers!(shared inout       real, int) == shared inout       int));
7999     static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int));
8000     static assert(is(CopyTypeQualifiers!(         immutable real, int) ==          immutable int));
8001 }
8002 
8003 /**
8004 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness)
8005 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the
8006 returned type will be the same as `ToType`.
8007 */
8008 template CopyConstness(FromType, ToType)
8009 {
8010     alias Unshared(T) = T;
8011     alias Unshared(T: shared U, U) = U;
8012 
8013     alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType));
8014 }
8015 
8016 ///
8017 @safe unittest
8018 {
8019     const(int) i;
8020     CopyConstness!(typeof(i), float) f;
8021     assert( is(typeof(f) == const float));
8022 
8023     CopyConstness!(char, uint) u;
8024     assert( is(typeof(u) == uint));
8025 
8026     //The 'shared' qualifier will not be copied
8027     assert(!is(CopyConstness!(shared bool, int) == shared int));
8028 
8029     //But the constness will be
8030     assert( is(CopyConstness!(shared const real, double) == const double));
8031 
8032     //Careful, const(int)[] is a mutable array of const(int)
8033     alias MutT = CopyConstness!(const(int)[], int);
8034     assert(!is(MutT == const(int)));
8035 
8036     //Okay, const(int[]) applies to array and contained ints
8037     alias CstT = CopyConstness!(const(int[]), int);
8038     assert( is(CstT == const(int)));
8039 }
8040 
8041 @safe unittest
8042 {
8043     struct Test
8044     {
8045         void method1() {}
8046         void method2() const {}
8047         void method3() immutable {}
8048     }
8049 
8050     assert(is(CopyConstness!(typeof(Test.method1), real) == real));
8051 
8052     assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte)));
8053 
8054     assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string)));
8055 }
8056 
8057 @safe unittest
8058 {
8059     assert(is(CopyConstness!(inout(int)[], int[]) == int[]));
8060     assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[])));
8061 }
8062 
8063 @safe unittest
8064 {
8065     static assert(is(CopyConstness!(                   int, real) ==             real));
8066     static assert(is(CopyConstness!(const              int, real) ==       const real));
8067     static assert(is(CopyConstness!(inout              int, real) ==       inout real));
8068     static assert(is(CopyConstness!(inout const        int, real) == inout const real));
8069     static assert(is(CopyConstness!(shared             int, real) ==             real));
8070     static assert(is(CopyConstness!(shared const       int, real) ==       const real));
8071     static assert(is(CopyConstness!(shared inout       int, real) == inout       real));
8072     static assert(is(CopyConstness!(shared inout const int, real) == inout const real));
8073     static assert(is(CopyConstness!(immutable          int, real) ==   immutable real));
8074 }
8075 
8076 /**
8077 Returns the inferred type of the loop variable when a variable of type T
8078 is iterated over using a `foreach` loop with a single loop variable and
8079 automatically inferred return type.  Note that this may not be the same as
8080 `std.range.ElementType!Range` in the case of narrow strings, or if T
8081 has both opApply and a range interface.
8082 */
8083 template ForeachType(T)
8084 {
8085     alias ForeachType = typeof(
8086     (inout int x = 0)
8087     {
8088         foreach (elem; T.init)
8089         {
8090             return elem;
8091         }
8092         assert(0);
8093     }());
8094 }
8095 
8096 ///
8097 @safe unittest
8098 {
8099     static assert(is(ForeachType!(uint[]) == uint));
8100     static assert(is(ForeachType!string == immutable(char)));
8101     static assert(is(ForeachType!(string[string]) == string));
8102     static assert(is(ForeachType!(inout(int)[]) == inout(int)));
8103 }
8104 
8105 
8106 /**
8107  * Strips off all `enum`s from type `T`.
8108  */
8109 template OriginalType(T)
8110 {
8111     import core.internal.traits : _OriginalType = OriginalType;
8112     alias OriginalType = _OriginalType!T;
8113 }
8114 
8115 ///
8116 @safe unittest
8117 {
8118     enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
8119     enum F : E    { a = E.a }
8120     alias G = const(F);
8121     static assert(is(OriginalType!E == real));
8122     static assert(is(OriginalType!F == real));
8123     static assert(is(OriginalType!G == const real));
8124 }
8125 
8126 /**
8127  * Get the Key type of an Associative Array.
8128  */
8129 alias KeyType(V : V[K], K) = K;
8130 
8131 ///
8132 @safe unittest
8133 {
8134     alias Hash = int[string];
8135     static assert(is(KeyType!Hash == string));
8136     static assert(is(ValueType!Hash == int));
8137     KeyType!Hash str = "a"; // str is declared as string
8138     ValueType!Hash num = 1; // num is declared as int
8139 }
8140 
8141 /**
8142  * Get the Value type of an Associative Array.
8143  */
8144 alias ValueType(V : V[K], K) = V;
8145 
8146 ///
8147 @safe unittest
8148 {
8149     alias Hash = int[string];
8150     static assert(is(KeyType!Hash == string));
8151     static assert(is(ValueType!Hash == int));
8152     KeyType!Hash str = "a"; // str is declared as string
8153     ValueType!Hash num = 1; // num is declared as int
8154 }
8155 
8156 /**
8157 Params:
8158     T = A built in integral or vector type.
8159 
8160 Returns:
8161     The corresponding unsigned numeric type for `T` with the
8162     same type qualifiers.
8163 
8164     If `T` is not a integral or vector, a compile-time error is given.
8165  */
8166 template Unsigned(T)
8167 {
8168     template Impl(T)
8169     {
8170         static if (is(T : __vector(V[N]), V, size_t N))
8171             alias Impl = __vector(Impl!V[N]);
8172         else static if (isUnsigned!T)
8173             alias Impl = T;
8174         else static if (isSigned!T && !isFloatingPoint!T)
8175         {
8176             static if (is(T == byte )) alias Impl = ubyte;
8177             static if (is(T == short)) alias Impl = ushort;
8178             static if (is(T == int  )) alias Impl = uint;
8179             static if (is(T == long )) alias Impl = ulong;
8180             static if (is(ucent) && is(T == cent )) alias Impl = ucent;
8181         }
8182         else
8183             static assert(false, "Type " ~ T.stringof ~
8184                                  " does not have an Unsigned counterpart");
8185     }
8186 
8187     alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8188 }
8189 
8190 ///
8191 @safe unittest
8192 {
8193     static assert(is(Unsigned!(int) == uint));
8194     static assert(is(Unsigned!(long) == ulong));
8195     static assert(is(Unsigned!(const short) == const ushort));
8196     static assert(is(Unsigned!(immutable byte) == immutable ubyte));
8197     static assert(is(Unsigned!(inout int) == inout uint));
8198 }
8199 
8200 
8201 /// Unsigned types are forwarded
8202 @safe unittest
8203 {
8204     static assert(is(Unsigned!(uint) == uint));
8205     static assert(is(Unsigned!(const uint) == const uint));
8206 
8207     static assert(is(Unsigned!(ubyte) == ubyte));
8208     static assert(is(Unsigned!(immutable uint) == immutable uint));
8209 }
8210 
8211 @safe unittest
8212 {
8213     alias U1 = Unsigned!int;
8214     alias U2 = Unsigned!(const(int));
8215     alias U3 = Unsigned!(immutable(int));
8216     static assert(is(U1 == uint));
8217     static assert(is(U2 == const(uint)));
8218     static assert(is(U3 == immutable(uint)));
8219     static if (is(__vector(int[4])) && is(__vector(uint[4])))
8220     {
8221         alias UV1 = Unsigned!(__vector(int[4]));
8222         alias UV2 = Unsigned!(const(__vector(int[4])));
8223         static assert(is(UV1 == __vector(uint[4])));
8224         static assert(is(UV2 == const(__vector(uint[4]))));
8225     }
8226     //struct S {}
8227     //alias U2 = Unsigned!S;
8228     //alias U3 = Unsigned!double;
8229     static if (is(ucent))
8230     {
8231         alias U4 = Unsigned!cent;
8232         alias U5 = Unsigned!(const(cent));
8233         alias U6 = Unsigned!(immutable(cent));
8234         static assert(is(U4 == ucent));
8235         static assert(is(U5 == const(ucent)));
8236         static assert(is(U6 == immutable(ucent)));
8237     }
8238 }
8239 
8240 /**
8241 Returns the largest type, i.e. T such that T.sizeof is the largest.  If more
8242 than one type is of the same size, the leftmost argument of these in will be
8243 returned.
8244 */
8245 template Largest(T...)
8246 if (T.length >= 1)
8247 {
8248     alias Largest = T[0];
8249     static foreach (U; T[1 .. $])
8250         Largest = Select!(U.sizeof > Largest.sizeof, U, Largest);
8251 }
8252 
8253 ///
8254 @safe unittest
8255 {
8256     static assert(is(Largest!(uint, ubyte, ushort, real) == real));
8257     static assert(is(Largest!(ulong, double) == ulong));
8258     static assert(is(Largest!(double, ulong) == double));
8259     static assert(is(Largest!(uint, byte, double, short) == double));
8260     static if (is(ucent))
8261         static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent));
8262 }
8263 
8264 /**
8265 Returns the corresponding signed type for T. T must be a numeric integral type,
8266 otherwise a compile-time error occurs.
8267  */
8268 template Signed(T)
8269 {
8270     template Impl(T)
8271     {
8272         static if (is(T : __vector(V[N]), V, size_t N))
8273             alias Impl = __vector(Impl!V[N]);
8274         else static if (isSigned!T)
8275             alias Impl = T;
8276         else static if (isUnsigned!T)
8277         {
8278             static if (is(T == ubyte )) alias Impl = byte;
8279             static if (is(T == ushort)) alias Impl = short;
8280             static if (is(T == uint  )) alias Impl = int;
8281             static if (is(T == ulong )) alias Impl = long;
8282             static if (is(ucent) && is(T == ucent )) alias Impl = cent;
8283         }
8284         else
8285             static assert(false, "Type " ~ T.stringof ~
8286                                  " does not have an Signed counterpart");
8287     }
8288 
8289     alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8290 }
8291 
8292 ///
8293 @safe unittest
8294 {
8295     alias S1 = Signed!uint;
8296     static assert(is(S1 == int));
8297     alias S2 = Signed!(const(uint));
8298     static assert(is(S2 == const(int)));
8299     alias S3 = Signed!(immutable(uint));
8300     static assert(is(S3 == immutable(int)));
8301     static if (is(ucent))
8302     {
8303         alias S4 = Signed!ucent;
8304         static assert(is(S4 == cent));
8305     }
8306 }
8307 
8308 @safe unittest
8309 {
8310     static assert(is(Signed!float == float));
8311     static if (is(__vector(int[4])) && is(__vector(uint[4])))
8312     {
8313         alias SV1 = Signed!(__vector(uint[4]));
8314         alias SV2 = Signed!(const(__vector(uint[4])));
8315         static assert(is(SV1 == __vector(int[4])));
8316         static assert(is(SV2 == const(__vector(int[4]))));
8317     }
8318 }
8319 
8320 
8321 /**
8322 Returns the most negative value of the numeric type T.
8323 */
8324 template mostNegative(T)
8325 if (isNumeric!T || isSomeChar!T || isBoolean!T)
8326 {
8327     static if (is(typeof(T.min_normal)))
8328         enum mostNegative = -T.max;
8329     else static if (T.min == 0)
8330         enum byte mostNegative = 0;
8331     else
8332         enum mostNegative = T.min;
8333 }
8334 
8335 ///
8336 @safe unittest
8337 {
8338     static assert(mostNegative!float == -float.max);
8339     static assert(mostNegative!double == -double.max);
8340     static assert(mostNegative!real == -real.max);
8341     static assert(mostNegative!bool == false);
8342 }
8343 
8344 ///
8345 @safe unittest
8346 {
8347     import std.meta : AliasSeq;
8348 
8349     static foreach (T; AliasSeq!(bool, byte, short, int, long))
8350         static assert(mostNegative!T == T.min);
8351 
8352     static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
8353         static assert(mostNegative!T == 0);
8354 }
8355 
8356 /**
8357 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
8358 to in multi-term arithmetic expressions.
8359 */
8360 template Promoted(T)
8361 if (isScalarType!T)
8362 {
8363     alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
8364 }
8365 
8366 ///
8367 @safe unittest
8368 {
8369     ubyte a = 3, b = 5;
8370     static assert(is(typeof(a * b) == Promoted!ubyte));
8371     static assert(is(Promoted!ubyte == int));
8372 
8373     static assert(is(Promoted!(shared(bool)) == shared(int)));
8374     static assert(is(Promoted!(const(int)) == const(int)));
8375     static assert(is(Promoted!double == double));
8376 }
8377 
8378 @safe unittest
8379 {
8380     // promote to int:
8381     static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar))
8382     {
8383         static assert(is(Promoted!T == int));
8384         static assert(is(Promoted!(shared(const T)) == shared(const int)));
8385     }
8386 
8387     // already promoted:
8388     static foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real))
8389     {
8390         static assert(is(Promoted!T == T));
8391         static assert(is(Promoted!(immutable(T)) == immutable(T)));
8392     }
8393 }
8394 
8395 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8396 // Misc.
8397 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8398 
8399 /**
8400 Returns the mangled name of symbol or type `sth`.
8401 
8402 `mangledName` is the same as builtin `.mangleof` property, but
8403 might be more convenient in generic code, e.g. as a template argument
8404 when invoking staticMap.
8405  */
8406 enum mangledName(alias sth) = sth.mangleof;
8407 
8408 ///
8409 @safe unittest
8410 {
8411     import std.meta : AliasSeq;
8412     alias TL = staticMap!(mangledName, int, const int, immutable int);
8413     static assert(TL == AliasSeq!("i", "xi", "yi"));
8414 }
8415 
8416 version (StdUnittest) private void freeFunc(string);
8417 
8418 @safe unittest
8419 {
8420     class C { int value() @property { return 0; } }
8421     static assert(mangledName!int == int.mangleof);
8422     static assert(mangledName!C == C.mangleof);
8423     static assert(mangledName!(C.value) == C.value.mangleof);
8424     static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi");
8425     static assert(mangledName!mangledName == "3std6traits11mangledName");
8426     static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv");
8427     int x;
8428     // https://issues.dlang.org/show_bug.cgi?id=9148
8429   static if (is(typeof({ return x; }) : int delegate() pure))
8430     static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi");  // pure nothrow @safe @nogc
8431   else
8432     static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi");  // nothrow @safe @nnogc
8433 }
8434 
8435 @system unittest
8436 {
8437     // @system due to demangle
8438     // Test for https://issues.dlang.org/show_bug.cgi?id=5718
8439     import std.demangle : demangle;
8440     int foo;
8441     auto foo_demangled = demangle(mangledName!foo);
8442     assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo",
8443         foo_demangled);
8444 
8445     void bar();
8446     auto bar_demangled = demangle(mangledName!bar);
8447     assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()");
8448 }
8449 
8450 
8451 
8452 // XXX Select & select should go to another module. (functional or algorithm?)
8453 
8454 /**
8455 Aliases itself to `T[0]` if the boolean `condition` is `true`
8456 and to `T[1]` otherwise.
8457  */
8458 template Select(bool condition, T...)
8459 if (T.length == 2)
8460 {
8461     import std.meta : Alias;
8462     alias Select = Alias!(T[!condition]);
8463 }
8464 
8465 ///
8466 @safe unittest
8467 {
8468     // can select types
8469     static assert(is(Select!(true, int, long) == int));
8470     static assert(is(Select!(false, int, long) == long));
8471     static struct Foo {}
8472     static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));
8473 
8474     // can select symbols
8475     int a = 1;
8476     int b = 2;
8477     alias selA = Select!(true, a, b);
8478     alias selB = Select!(false, a, b);
8479     assert(selA == 1);
8480     assert(selB == 2);
8481 
8482     // can select (compile-time) expressions
8483     enum val = Select!(false, -4, 9 - 6);
8484     static assert(val == 3);
8485 }
8486 
8487 /**
8488 Select one of two functions to run via template parameter.
8489 
8490 Params:
8491     cond = A `bool` which determines which function is run
8492     a = The first function
8493     b = The second function
8494 
8495 Returns:
8496     `a` without evaluating `b` if `cond` is `true`.
8497     Otherwise, returns `b` without evaluating `a`.
8498  */
8499 A select(bool cond : true, A, B)(A a, lazy B b) { return a; }
8500 /// Ditto
8501 B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
8502 
8503 ///
8504 @safe unittest
8505 {
8506     real run() { return 0; }
8507     int fail() { assert(0); }
8508     auto a = select!true(run(), fail());
8509     auto b = select!false(fail(), run());
8510     static assert(is(typeof(a) == real));
8511     static assert(is(typeof(b) == real));
8512 }
8513 
8514 /++
8515     Determine if a symbol has a given
8516     $(DDSUBLINK spec/attribute, uda, user-defined attribute).
8517 
8518     See_Also:
8519         $(LREF getUDAs)
8520   +/
8521 enum hasUDA(alias symbol, alias attribute) = getUDAs!(symbol, attribute).length != 0;
8522 
8523 ///
8524 @safe unittest
8525 {
8526     enum E;
8527     struct S {}
8528 
8529     @("alpha") int a;
8530     static assert(hasUDA!(a, "alpha"));
8531     static assert(!hasUDA!(a, S));
8532     static assert(!hasUDA!(a, E));
8533 
8534     @(E) int b;
8535     static assert(!hasUDA!(b, "alpha"));
8536     static assert(!hasUDA!(b, S));
8537     static assert(hasUDA!(b, E));
8538 
8539     @E int c;
8540     static assert(!hasUDA!(c, "alpha"));
8541     static assert(!hasUDA!(c, S));
8542     static assert(hasUDA!(c, E));
8543 
8544     @(S, E) int d;
8545     static assert(!hasUDA!(d, "alpha"));
8546     static assert(hasUDA!(d, S));
8547     static assert(hasUDA!(d, E));
8548 
8549     @S int e;
8550     static assert(!hasUDA!(e, "alpha"));
8551     static assert(hasUDA!(e, S));
8552     static assert(!hasUDA!(e, S()));
8553     static assert(!hasUDA!(e, E));
8554 
8555     @S() int f;
8556     static assert(!hasUDA!(f, "alpha"));
8557     static assert(hasUDA!(f, S));
8558     static assert(hasUDA!(f, S()));
8559     static assert(!hasUDA!(f, E));
8560 
8561     @(S, E, "alpha") int g;
8562     static assert(hasUDA!(g, "alpha"));
8563     static assert(hasUDA!(g, S));
8564     static assert(hasUDA!(g, E));
8565 
8566     @(100) int h;
8567     static assert(hasUDA!(h, 100));
8568 
8569     struct Named { string name; }
8570 
8571     @Named("abc") int i;
8572     static assert(hasUDA!(i, Named));
8573     static assert(hasUDA!(i, Named("abc")));
8574     static assert(!hasUDA!(i, Named("def")));
8575 
8576     struct AttrT(T)
8577     {
8578         string name;
8579         T value;
8580     }
8581 
8582     @AttrT!int("answer", 42) int j;
8583     static assert(hasUDA!(j, AttrT));
8584     static assert(hasUDA!(j, AttrT!int));
8585     static assert(!hasUDA!(j, AttrT!string));
8586 
8587     @AttrT!string("hello", "world") int k;
8588     static assert(hasUDA!(k, AttrT));
8589     static assert(!hasUDA!(k, AttrT!int));
8590     static assert(hasUDA!(k, AttrT!string));
8591 
8592     struct FuncAttr(alias f) { alias func = f; }
8593     static int fourtyTwo() { return 42; }
8594     static size_t getLen(string s) { return s.length; }
8595 
8596     @FuncAttr!getLen int l;
8597     static assert(hasUDA!(l, FuncAttr));
8598     static assert(!hasUDA!(l, FuncAttr!fourtyTwo));
8599     static assert(hasUDA!(l, FuncAttr!getLen));
8600     static assert(!hasUDA!(l, FuncAttr!fourtyTwo()));
8601     static assert(!hasUDA!(l, FuncAttr!getLen()));
8602 
8603     @FuncAttr!getLen() int m;
8604     static assert(hasUDA!(m, FuncAttr));
8605     static assert(!hasUDA!(m, FuncAttr!fourtyTwo));
8606     static assert(hasUDA!(m, FuncAttr!getLen));
8607     static assert(!hasUDA!(m, FuncAttr!fourtyTwo()));
8608     static assert(hasUDA!(m, FuncAttr!getLen()));
8609 }
8610 
8611 /++
8612     Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
8613     from the given symbol.
8614 
8615     If the UDA is a type, then any UDAs of the same type on the symbol will
8616     match. If the UDA is a template for a type, then any UDA which is an
8617     instantiation of that template will match. And if the UDA is a value,
8618     then any UDAs on the symbol which are equal to that value will match.
8619 
8620     See_Also:
8621         $(LREF hasUDA)
8622   +/
8623 template getUDAs(alias symbol, alias attribute)
8624 {
8625     import std.meta : Filter;
8626 
8627     alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, symbol));
8628 }
8629 
8630 ///
8631 @safe unittest
8632 {
8633     struct Attr
8634     {
8635         string name;
8636         int value;
8637     }
8638 
8639     @Attr("Answer", 42) int a;
8640     static assert(getUDAs!(a, Attr).length == 1);
8641     static assert(getUDAs!(a, Attr)[0].name == "Answer");
8642     static assert(getUDAs!(a, Attr)[0].value == 42);
8643 
8644     @(Attr("Answer", 42), "string", 9999) int b;
8645     static assert(getUDAs!(b, Attr).length == 1);
8646     static assert(getUDAs!(b, Attr)[0].name == "Answer");
8647     static assert(getUDAs!(b, Attr)[0].value == 42);
8648 
8649     @Attr("Answer", 42) @Attr("Pi", 3) int c;
8650     static assert(getUDAs!(c, Attr).length == 2);
8651     static assert(getUDAs!(c, Attr)[0].name == "Answer");
8652     static assert(getUDAs!(c, Attr)[0].value == 42);
8653     static assert(getUDAs!(c, Attr)[1].name == "Pi");
8654     static assert(getUDAs!(c, Attr)[1].value == 3);
8655 
8656     static assert(getUDAs!(c, Attr("Answer", 42)).length == 1);
8657     static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer");
8658     static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42);
8659 
8660     static assert(getUDAs!(c, Attr("Answer", 99)).length == 0);
8661 
8662     struct AttrT(T)
8663     {
8664         string name;
8665         T value;
8666     }
8667 
8668     @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d;
8669     static assert(getUDAs!(d, AttrT).length == 2);
8670     static assert(getUDAs!(d, AttrT)[0].name == "Answer");
8671     static assert(getUDAs!(d, AttrT)[0].value == 42);
8672     static assert(getUDAs!(d, AttrT)[1].name == "Pi");
8673     static assert(getUDAs!(d, AttrT)[1].value == 3);
8674 
8675     static assert(getUDAs!(d, AttrT!uint).length == 1);
8676     static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer");
8677     static assert(getUDAs!(d, AttrT!uint)[0].value == 42);
8678 
8679     static assert(getUDAs!(d, AttrT!int).length == 1);
8680     static assert(getUDAs!(d, AttrT!int)[0].name == "Pi");
8681     static assert(getUDAs!(d, AttrT!int)[0].value == 3);
8682 
8683     struct SimpleAttr {}
8684 
8685     @SimpleAttr int e;
8686     static assert(getUDAs!(e, SimpleAttr).length == 1);
8687     static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr));
8688 
8689     @SimpleAttr() int f;
8690     static assert(getUDAs!(f, SimpleAttr).length == 1);
8691     static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr));
8692 
8693     struct FuncAttr(alias f) { alias func = f; }
8694     static int add42(int v) { return v + 42; }
8695     static string concat(string l, string r) { return l ~ r; }
8696 
8697     @FuncAttr!add42 int g;
8698     static assert(getUDAs!(g, FuncAttr).length == 1);
8699     static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47);
8700 
8701     static assert(getUDAs!(g, FuncAttr!add42).length == 1);
8702     static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47);
8703 
8704     static assert(getUDAs!(g, FuncAttr!add42()).length == 0);
8705 
8706     static assert(getUDAs!(g, FuncAttr!concat).length == 0);
8707     static assert(getUDAs!(g, FuncAttr!concat()).length == 0);
8708 
8709     @FuncAttr!add42() int h;
8710     static assert(getUDAs!(h, FuncAttr).length == 1);
8711     static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47);
8712 
8713     static assert(getUDAs!(h, FuncAttr!add42).length == 1);
8714     static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47);
8715 
8716     static assert(getUDAs!(h, FuncAttr!add42()).length == 1);
8717     static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47);
8718 
8719     static assert(getUDAs!(h, FuncAttr!concat).length == 0);
8720     static assert(getUDAs!(h, FuncAttr!concat()).length == 0);
8721 
8722     @("alpha") @(42) int i;
8723     static assert(getUDAs!(i, "alpha").length == 1);
8724     static assert(getUDAs!(i, "alpha")[0] == "alpha");
8725 
8726     static assert(getUDAs!(i, 42).length == 1);
8727     static assert(getUDAs!(i, 42)[0] == 42);
8728 
8729     static assert(getUDAs!(i, 'c').length == 0);
8730 }
8731 
8732 private template isDesiredUDA(alias attribute)
8733 {
8734     template isDesiredUDA(alias toCheck)
8735     {
8736         static if (is(typeof(attribute)) && !__traits(isTemplate, attribute))
8737         {
8738             static if (__traits(compiles, toCheck == attribute))
8739                 enum isDesiredUDA = toCheck == attribute;
8740             else
8741                 enum isDesiredUDA = false;
8742         }
8743         else static if (is(typeof(toCheck)))
8744         {
8745             static if (__traits(isTemplate, attribute))
8746                 enum isDesiredUDA =  isInstanceOf!(attribute, typeof(toCheck));
8747             else
8748                 enum isDesiredUDA = is(typeof(toCheck) == attribute);
8749         }
8750         else static if (__traits(isTemplate, attribute))
8751             enum isDesiredUDA = isInstanceOf!(attribute, toCheck);
8752         else
8753             enum isDesiredUDA = is(toCheck == attribute);
8754     }
8755 }
8756 
8757 /**
8758 Params:
8759     symbol = The aggregate type or module to search
8760     attribute = The user-defined attribute to search for
8761 
8762 Returns:
8763     All symbols within `symbol` that have the given UDA `attribute`.
8764 
8765 Note:
8766     This is not recursive; it will not search for symbols within symbols such as
8767     nested structs or unions.
8768  */
8769 template getSymbolsByUDA(alias symbol, alias attribute)
8770 {
8771     alias membersWithUDA = getSymbolsByUDAImpl!(symbol, attribute, __traits(allMembers, symbol));
8772 
8773     // if the symbol itself has the UDA, tack it on to the front of the list
8774     static if (hasUDA!(symbol, attribute))
8775         alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
8776     else
8777         alias getSymbolsByUDA = membersWithUDA;
8778 }
8779 
8780 ///
8781 @safe unittest
8782 {
8783     enum Attr;
8784     struct A
8785     {
8786         @Attr int a;
8787         int b;
8788     }
8789 
8790     static assert(getSymbolsByUDA!(A, Attr).length == 1);
8791     static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8792 }
8793 
8794 ///
8795 @safe unittest
8796 {
8797     enum Attr;
8798 
8799     static struct A
8800     {
8801         @Attr int a;
8802         int b;
8803         @Attr void doStuff() {}
8804         void doOtherStuff() {}
8805         static struct Inner
8806         {
8807             // Not found by getSymbolsByUDA
8808             @Attr int c;
8809         }
8810     }
8811 
8812     // Finds both variables and functions with the attribute, but
8813     // doesn't include the variables and functions without it.
8814     static assert(getSymbolsByUDA!(A, Attr).length == 2);
8815     // Can access attributes on the symbols returned by getSymbolsByUDA.
8816     static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8817     static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
8818 }
8819 
8820 /// Finds multiple attributes
8821 @safe unittest
8822 {
8823     static struct UDA { string name; }
8824 
8825     static struct B
8826     {
8827         @UDA("X")
8828         int x;
8829         @UDA("Y")
8830         int y;
8831         @(100)
8832         int z;
8833     }
8834 
8835     // Finds both UDA attributes.
8836     static assert(getSymbolsByUDA!(B, UDA).length == 2);
8837     // Finds one `100` attribute.
8838     static assert(getSymbolsByUDA!(B, 100).length == 1);
8839     // Can get the value of the UDA from the return value
8840     static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");
8841 }
8842 
8843 /// Checks for UDAs on the aggregate symbol itself
8844 @safe unittest
8845 {
8846     static struct UDA { string name; }
8847 
8848     @UDA("A")
8849     static struct C
8850     {
8851         @UDA("B")
8852         int d;
8853     }
8854 
8855     static assert(getSymbolsByUDA!(C, UDA).length == 2);
8856     static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
8857     static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
8858 }
8859 
8860 /// Finds nothing if there is no member with specific UDA
8861 @safe unittest
8862 {
8863     static struct UDA { string name; }
8864 
8865     static struct D
8866     {
8867         int x;
8868     }
8869 
8870     static assert(getSymbolsByUDA!(D, UDA).length == 0);
8871 }
8872 
8873 // https://issues.dlang.org/show_bug.cgi?id=18314
8874 @safe unittest
8875 {
8876     enum attr1;
8877     enum attr2;
8878 
8879     struct A
8880     {
8881         @attr1
8882         int n;
8883         // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206
8884         //@attr1
8885         //void foo()(string){}
8886         @attr1
8887         void foo();
8888         @attr2
8889         void foo(int a);
8890     }
8891 
8892     static assert(getSymbolsByUDA!(A, attr1).length == 2);
8893     static assert(getSymbolsByUDA!(A, attr2).length == 1);
8894 }
8895 
8896 // getSymbolsByUDA fails if type has private members
8897 // https://issues.dlang.org/show_bug.cgi?id=15335
8898 @safe unittest
8899 {
8900     // HasPrivateMembers has, well, private members, one of which has a UDA.
8901     import std.internal.test.uda : Attr, HasPrivateMembers;
8902     // Trying access to private member from another file therefore we do not have access
8903     // for this otherwise we get deprecation warning - not visible from module
8904     // This line is commented because `__traits(getMember)` should also consider
8905     // private members; this is not currently the case, but the PR that
8906     // fixes `__traits(getMember)` is blocked by this specific test.
8907     //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
8908     static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr));
8909 }
8910 
8911 // getSymbolsByUDA works with structs but fails with classes
8912 // https://issues.dlang.org/show_bug.cgi?id=16387
8913 @safe unittest
8914 {
8915     enum Attr;
8916     class A
8917     {
8918         @Attr uint a;
8919     }
8920 
8921     alias res = getSymbolsByUDA!(A, Attr);
8922     static assert(res.length == 1);
8923     static assert(res[0].stringof == "a");
8924 }
8925 
8926 // getSymbolsByUDA fails on AliasSeq members
8927 // https://issues.dlang.org/show_bug.cgi?id=18884
8928 @safe unittest
8929 {
8930     struct X
8931     {
8932         alias A = AliasSeq!(ulong, uint);
8933     }
8934 
8935     static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!()));
8936 }
8937 
8938 // https://issues.dlang.org/show_bug.cgi?id=23776
8939 @safe pure nothrow @nogc unittest
8940 {
8941     struct T
8942     {
8943         struct Tag {}
8944         @Tag struct MyStructA {}
8945         @Tag struct MyStructB {}
8946         @Tag struct MyStructC {}
8947     }
8948     alias tcomponents = getSymbolsByUDA!(T, T.Tag);
8949     static assert(tcomponents.length > 0);
8950 
8951     struct X
8952     {
8953         struct Tag {}
8954         @Tag enum MyEnumA;
8955         @Tag enum MyEnumB;
8956         @Tag enum MyEnumC;
8957     }
8958     alias xcomponents = getSymbolsByUDA!(X, X.Tag);
8959     static assert(xcomponents.length > 0);
8960 }
8961 
8962 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
8963 // https://issues.dlang.org/show_bug.cgi?id=18624
8964 @safe unittest
8965 {
8966     enum Attr;
8967     struct A
8968     {
8969         @Attr void a();
8970         @Attr void a(int n);
8971               void b();
8972         @Attr void c();
8973     }
8974 
8975     alias ola = __traits(getOverloads, A, "a");
8976     static assert(__traits(isSame, getSymbolsByUDA!(A, Attr),
8977         AliasSeq!(ola[0], ola[1], A.c)));
8978 }
8979 
8980 // getSymbolsByUDA no longer works on modules
8981 // https://issues.dlang.org/show_bug.cgi?id=20054
8982 version (StdUnittest)
8983 {
8984     @("Issue20054")
8985     void issue20054() {}
8986     static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054")));
8987 }
8988 
8989 private template isAliasSeq(Args...)
8990 {
8991     static if (Args.length != 1)
8992         enum isAliasSeq = true;
8993     else
8994         enum isAliasSeq = false;
8995 }
8996 
8997 private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
8998 {
8999     import std.meta : Alias, AliasSeq, Filter;
9000     static if (names.length == 0)
9001     {
9002         alias getSymbolsByUDAImpl = AliasSeq!();
9003     }
9004     else
9005     {
9006         alias tail = getSymbolsByUDAImpl!(symbol, attribute, names[1 .. $]);
9007 
9008         // Filtering inaccessible members.
9009         static if (!__traits(compiles, __traits(getMember, symbol, names[0])))
9010         {
9011             alias getSymbolsByUDAImpl = tail;
9012         }
9013         else
9014         {
9015             alias member = __traits(getMember, symbol, names[0]);
9016 
9017             // Filtering not compiled members such as alias of basic types.
9018             static if (isAliasSeq!member ||
9019                        (isType!member && !isAggregateType!member && !is(member == enum)))
9020             {
9021                 alias getSymbolsByUDAImpl = tail;
9022             }
9023             // If a symbol is overloaded, get UDAs for each overload (including templated overlaods).
9024             else static if (__traits(getOverloads, symbol, names[0], true).length > 0)
9025             {
9026                 enum hasSpecificUDA(alias member) = hasUDA!(member, attribute);
9027                 alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0]));
9028                 alias getSymbolsByUDAImpl = AliasSeq!(overloadsWithUDA, tail);
9029             }
9030             else static if (hasUDA!(member, attribute))
9031             {
9032                 alias getSymbolsByUDAImpl = AliasSeq!(member, tail);
9033             }
9034             else
9035             {
9036                 alias getSymbolsByUDAImpl = tail;
9037             }
9038         }
9039     }
9040 }
9041 
9042 /**
9043    Returns: `true` iff all types `Ts` are the same.
9044 */
9045 enum bool allSameType(Ts...) =
9046 {
9047     static foreach (T; Ts[Ts.length > 1 .. $])
9048         static if (!is(Ts[0] == T))
9049             if (__ctfe)  // Dodge the "statement is unreachable" warning
9050                 return false;
9051     return true;
9052 }();
9053 
9054 ///
9055 @safe unittest
9056 {
9057     static assert(allSameType!());
9058     static assert(allSameType!(int));
9059     static assert(allSameType!(int, int));
9060     static assert(allSameType!(int, int, int));
9061     static assert(allSameType!(float, float, float));
9062     static assert(!allSameType!(int, double));
9063     static assert(!allSameType!(int, float, double));
9064     static assert(!allSameType!(int, float, double, real));
9065     static assert(!allSameType!(short, int, float, double, real));
9066 }
9067 
9068 /**
9069    Returns: `true` iff the type `T` can be tested in an $(D
9070    if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
9071 */
9072 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
9073 
9074 ///
9075 @safe unittest
9076 {
9077     class C;
9078     struct S1;
9079     struct S2
9080     {
9081         T opCast(T)() const;
9082     }
9083 
9084     static assert( ifTestable!bool);
9085     static assert( ifTestable!int);
9086     static assert( ifTestable!(S1*));
9087     static assert( ifTestable!(typeof(null)));
9088     static assert( ifTestable!(int[]));
9089     static assert( ifTestable!(int[string]));
9090     static assert( ifTestable!S2);
9091     static assert( ifTestable!C);
9092     static assert(!ifTestable!S1);
9093 }
9094 
9095 @safe unittest
9096 {
9097     import std.meta : AliasSeq, allSatisfy;
9098     static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string)));
9099     struct BoolWrapper { bool value; }
9100     static assert(!ifTestable!(bool, a => BoolWrapper(a)));
9101 }
9102 
9103 /**
9104  * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
9105  * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
9106  *
9107  * Returns:
9108  *      `true` if `X` is a type, `false` otherwise
9109  */
9110 enum isType(alias X) = is(X);
9111 
9112 ///
9113 @safe unittest
9114 {
9115     struct S {
9116         template Test() {}
9117     }
9118     class C {}
9119     interface I {}
9120     union U {}
9121     static assert(isType!int);
9122     static assert(isType!string);
9123     static assert(isType!(int[int]));
9124     static assert(isType!S);
9125     static assert(isType!C);
9126     static assert(isType!I);
9127     static assert(isType!U);
9128 
9129     int n;
9130     void func(){}
9131     static assert(!isType!n);
9132     static assert(!isType!func);
9133     static assert(!isType!(S.Test));
9134     static assert(!isType!(S.Test!()));
9135 }
9136 
9137 /**
9138  * Detect whether symbol or type `X` is a function. This is different that finding
9139  * if a symbol is callable or satisfying `is(X == function)`, it finds
9140  * specifically if the symbol represents a normal function declaration, i.e.
9141  * not a delegate or a function pointer.
9142  *
9143  * Returns:
9144  *     `true` if `X` is a function, `false` otherwise
9145  *
9146  * See_Also:
9147  *     Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
9148  *     respectively.
9149  */
9150 template isFunction(alias X)
9151 {
9152     static if (is(typeof(&X) U : U*) && is(U == function) ||
9153                is(typeof(&X) U == delegate))
9154     {
9155         // x is a (nested) function symbol.
9156         enum isFunction = true;
9157     }
9158     else static if (is(X T))
9159     {
9160         // x is a type.  Take the type of it and examine.
9161         enum isFunction = is(T == function);
9162     }
9163     else
9164         enum isFunction = false;
9165 }
9166 
9167 ///
9168 @safe unittest
9169 {
9170     static void func(){}
9171     static assert(isFunction!func);
9172 
9173     struct S
9174     {
9175         void func(){}
9176     }
9177     static assert(isFunction!(S.func));
9178 }
9179 
9180 /**
9181  * Detect whether `X` is a final method or class.
9182  *
9183  * Returns:
9184  *     `true` if `X` is final, `false` otherwise
9185  */
9186 template isFinal(alias X)
9187 {
9188     static if (is(X == class))
9189         enum isFinal = __traits(isFinalClass, X);
9190     else static if (isFunction!X)
9191         enum isFinal = __traits(isFinalFunction, X);
9192     else
9193         enum isFinal = false;
9194 }
9195 
9196 ///
9197 @safe unittest
9198 {
9199     class C
9200     {
9201         void nf() {}
9202         static void sf() {}
9203         final void ff() {}
9204     }
9205     final class FC { }
9206 
9207     static assert(!isFinal!(C));
9208     static assert( isFinal!(FC));
9209 
9210     static assert(!isFinal!(C.nf));
9211     static assert(!isFinal!(C.sf));
9212     static assert( isFinal!(C.ff));
9213 }
9214 
9215 /++
9216  + Determines whether the type `S` can be copied.
9217  + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
9218  + Copying for structs can be disabled by using `@disable this(this)`.
9219  +
9220  + See also: $(DDSUBLINK spec/traits, isCopyable, `__traits(isCopyable, S)`)
9221  + Params:
9222  +  S = The type to check.
9223  +
9224  + Returns:
9225  +  `true` if `S` can be copied. `false` otherwise.
9226  +/
9227 enum isCopyable(S) = __traits(isCopyable, S);
9228 
9229 ///
9230 @safe unittest
9231 {
9232     struct S1 {}                        // Fine. Can be copied
9233     struct S2 {         this(this) {}}  // Fine. Can be copied
9234     struct S3 {@disable this(this);  }  // Not fine. Copying is disabled.
9235     struct S4 {S3 s;}                   // Not fine. A field has copying disabled.
9236 
9237     class C1 {}
9238 
9239     static assert( isCopyable!S1);
9240     static assert( isCopyable!S2);
9241     static assert(!isCopyable!S3);
9242     static assert(!isCopyable!S4);
9243 
9244     static assert(isCopyable!C1);
9245     static assert(isCopyable!int);
9246     static assert(isCopyable!(int[]));
9247 }
9248 
9249 /**
9250  * The parameter type deduced by IFTI when an expression of type T is passed as
9251  * an argument to a template function.
9252  *
9253  * For all types other than pointer and slice types, `DeducedParameterType!T`
9254  * is the same as `T`. For pointer and slice types, it is `T` with the
9255  * outer-most layer of qualifiers dropped.
9256  */
9257 package(std) alias DeducedParameterType(T) = DeducedParameterTypeImpl!T;
9258 /// ditto
9259 package(std) alias DeducedParameterType(alias T) = DeducedParameterTypeImpl!T;
9260 
9261 private template DeducedParameterTypeImpl(T)
9262 {
9263     static if (is(T == U*, U) || is(T == U[], U))
9264         alias DeducedParameterTypeImpl = Unqual!T;
9265     else
9266         alias DeducedParameterTypeImpl = T;
9267 }
9268 
9269 @safe unittest
9270 {
9271     static assert(is(DeducedParameterType!(const(int)) == const(int)));
9272     static assert(is(DeducedParameterType!(const(int[2])) == const(int[2])));
9273 
9274     static assert(is(DeducedParameterType!(const(int*)) == const(int)*));
9275     static assert(is(DeducedParameterType!(const(int[])) == const(int)[]));
9276 }
9277 
9278 @safe unittest
9279 {
9280     static struct NoCopy
9281     {
9282         @disable this(this);
9283     }
9284 
9285     static assert(is(DeducedParameterType!NoCopy == NoCopy));
9286     static assert(is(DeducedParameterType!(inout(NoCopy)) == inout(NoCopy)));
9287 }
9288 
9289 @safe unittest
9290 {
9291     static assert(is(DeducedParameterType!(inout(int[])) == inout(int)[]));
9292 }
9293 
9294 private auto dip1000Test(int x) {return *&x;}
9295 // We don't use isSafe, because betterC client code needs to instantiate
9296 // core.internal.array.comparison.__cmp in the client side. isSafe uses
9297 // __cmp of two strings, so using it would instantate that here instead. That
9298 // won't do because betterC compilations do not link the Phobos binary in.
9299 package(std) enum dip1000Enabled
9300     = is(typeof(&dip1000Test) : int function(int) @safe);