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