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