The OpenD Programming Language

1 // Written in the D programming language.
2 
3 /**
4  * Templates which extract information about types and symbols at compile time.
5  *
6  * $(SCRIPT inhibitQuickIndex = 1;)
7  *
8  * $(DIVC quickindex,
9  * $(BOOKTABLE ,
10  * $(TR $(TH Category) $(TH Templates))
11  * $(TR $(TD Symbol Name traits) $(TD
12  *           $(LREF fullyQualifiedName)
13  *           $(LREF mangledName)
14  *           $(LREF moduleName)
15  *           $(LREF packageName)
16  * ))
17  * $(TR $(TD Function traits) $(TD
18  *           $(LREF isFunction)
19  *           $(LREF arity)
20  *           $(LREF functionAttributes)
21  *           $(LREF hasFunctionAttributes)
22  *           $(LREF functionLinkage)
23  *           $(LREF FunctionTypeOf)
24  *           $(LREF isSafe)
25  *           $(LREF isUnsafe)
26  *           $(LREF isFinal)
27  *           $(LREF ParameterDefaults)
28  *           $(LREF ParameterIdentifierTuple)
29  *           $(LREF ParameterStorageClassTuple)
30  *           $(LREF Parameters)
31  *           $(LREF ReturnType)
32  *           $(LREF SetFunctionAttributes)
33  *           $(LREF variadicFunctionStyle)
34  * ))
35  * $(TR $(TD Aggregate Type traits) $(TD
36  *           $(LREF BaseClassesTuple)
37  *           $(LREF BaseTypeTuple)
38  *           $(LREF classInstanceAlignment)
39  *           $(LREF EnumMembers)
40  *           $(LREF FieldNameTuple)
41  *           $(LREF Fields)
42  *           $(LREF hasAliasing)
43  *           $(LREF hasElaborateAssign)
44  *           $(LREF hasElaborateCopyConstructor)
45  *           $(LREF hasElaborateDestructor)
46  *           $(LREF hasElaborateMove)
47  *           $(LREF hasIndirections)
48  *           $(LREF hasMember)
49  *           $(LREF hasStaticMember)
50  *           $(LREF hasNested)
51  *           $(LREF hasUnsharedAliasing)
52  *           $(LREF InterfacesTuple)
53  *           $(LREF isInnerClass)
54  *           $(LREF isNested)
55  *           $(LREF MemberFunctionsTuple)
56  *           $(LREF RepresentationTypeTuple)
57  *           $(LREF TemplateArgsOf)
58  *           $(LREF TemplateOf)
59  *           $(LREF TransitiveBaseTypeTuple)
60  * ))
61  * $(TR $(TD Type Conversion) $(TD
62  *           $(LREF CommonType)
63  *           $(LREF AllImplicitConversionTargets)
64  *           $(LREF ImplicitConversionTargets)
65  *           $(LREF CopyTypeQualifiers)
66  *           $(LREF CopyConstness)
67  *           $(LREF isAssignable)
68  *           $(LREF isCovariantWith)
69  *           $(LREF isImplicitlyConvertible)
70  *           $(LREF isQualifierConvertible)
71  * ))
72  * $(TR $(TD Type Constructors) $(TD
73  *           $(LREF InoutOf)
74  *           $(LREF ConstOf)
75  *           $(LREF SharedOf)
76  *           $(LREF SharedInoutOf)
77  *           $(LREF SharedConstOf)
78  *           $(LREF SharedConstInoutOf)
79  *           $(LREF ImmutableOf)
80  *           $(LREF QualifierOf)
81  * ))
82  * $(TR $(TD Categories of types) $(TD
83  *           $(LREF allSameType)
84  *           $(LREF ifTestable)
85  *           $(LREF isType)
86  *           $(LREF isAggregateType)
87  *           $(LREF isArray)
88  *           $(LREF isAssociativeArray)
89  *           $(LREF isAutodecodableString)
90  *           $(LREF isBasicType)
91  *           $(LREF isBoolean)
92  *           $(LREF isBuiltinType)
93  *           $(LREF isCopyable)
94  *           $(LREF isDynamicArray)
95  *           $(LREF isEqualityComparable)
96  *           $(LREF isFloatingPoint)
97  *           $(LREF isIntegral)
98  *           $(LREF isNarrowString)
99  *           $(LREF isConvertibleToString)
100  *           $(LREF isNumeric)
101  *           $(LREF isOrderingComparable)
102  *           $(LREF isPointer)
103  *           $(LREF isScalarType)
104  *           $(LREF isSigned)
105  *           $(LREF isSIMDVector)
106  *           $(LREF isSomeChar)
107  *           $(LREF isSomeString)
108  *           $(LREF isStaticArray)
109  *           $(LREF isUnsigned)
110  * ))
111  * $(TR $(TD Type behaviours) $(TD
112  *           $(LREF isAbstractClass)
113  *           $(LREF isAbstractFunction)
114  *           $(LREF isCallable)
115  *           $(LREF isDelegate)
116  *           $(LREF isExpressions)
117  *           $(LREF isFinalClass)
118  *           $(LREF isFinalFunction)
119  *           $(LREF isFunctionPointer)
120  *           $(LREF isInstanceOf)
121  *           $(LREF isIterable)
122  *           $(LREF isMutable)
123  *           $(LREF isSomeFunction)
124  *           $(LREF isTypeTuple)
125  * ))
126  * $(TR $(TD General Types) $(TD
127  *           $(LREF ForeachType)
128  *           $(LREF KeyType)
129  *           $(LREF Largest)
130  *           $(LREF mostNegative)
131  *           $(LREF OriginalType)
132  *           $(LREF PointerTarget)
133  *           $(LREF Signed)
134  *           $(LREF Unconst)
135  *           $(LREF Unshared)
136  *           $(LREF Unqual)
137  *           $(LREF Unsigned)
138  *           $(LREF ValueType)
139  *           $(LREF Promoted)
140  * ))
141  * $(TR $(TD Misc) $(TD
142  *           $(LREF lvalueOf)
143  *           $(LREF rvalueOf)
144  *           $(LREF Select)
145  *           $(LREF select)
146  * ))
147  * $(TR $(TD User-Defined Attributes) $(TD
148  *           $(LREF hasUDA)
149  *           $(LREF getUDAs)
150  *           $(LREF getSymbolsByUDA)
151  * ))
152  * )
153  * )
154  *
155  * Copyright: Copyright The D Language Foundation 2005 - 2009.
156  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
157  * Authors:   $(HTTP digitalmars.com, Walter Bright),
158  *            Tomasz Stachowiak (`isExpressions`),
159  *            $(HTTP erdani.org, Andrei Alexandrescu),
160  *            Shin Fujishiro,
161  *            $(HTTP octarineparrot.com, Robert Clipsham),
162  *            $(HTTP klickverbot.at, David Nadlinger),
163  *            Kenji Hara,
164  *            Shoichi Kato
165  * Source:    $(PHOBOSSRC std/traits.d)
166  */
167 /*          Copyright The D Language Foundation 2005 - 2009.
168  * Distributed under the Boost Software License, Version 1.0.
169  *    (See accompanying file LICENSE_1_0.txt or copy at
170  *          http://www.boost.org/LICENSE_1_0.txt)
171  */
172 module std.traits;
173 
174 import std.meta : AliasSeq, allSatisfy, anySatisfy, ApplyLeft;
175 
176 // Legacy inheritance from std.typetuple
177 // See also: https://github.com/dlang/phobos/pull/5484#discussion_r122602797
178 import std.meta : staticMapMeta = staticMap;
179 // TODO: find a way to trigger deprecation warnings
180 //deprecated("staticMap is part of std.meta: Please import std.meta")
181 alias staticMap = staticMapMeta;
182 
183 ///////////////////////////////////////////////////////////////////////////////
184 // Type lists
185 ///////////////////////////////////////////////////////////////////////////////
186 
187 private
188 {
189     static if (is(ucent))
190     {
191         alias CentTypeList         = AliasSeq!(cent, ucent);
192         alias SignedCentTypeList   = AliasSeq!(cent);
193         alias UnsignedCentTypeList = AliasSeq!(ucent);
194     }
195     else
196     {
197         alias CentTypeList         = AliasSeq!();
198         alias SignedCentTypeList   = AliasSeq!();
199         alias UnsignedCentTypeList = AliasSeq!();
200     }
201 
202     alias IntegralTypeList      = AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList);
203     alias SignedIntTypeList     = AliasSeq!(byte, short, int, long, SignedCentTypeList);
204     alias UnsignedIntTypeList   = AliasSeq!(ubyte, ushort, uint, ulong, UnsignedCentTypeList);
205     alias FloatingPointTypeList = AliasSeq!(float, double, real);
206     alias ImaginaryTypeList     = AliasSeq!(ifloat, idouble, ireal);
207     alias ComplexTypeList       = AliasSeq!(cfloat, cdouble, creal);
208     alias NumericTypeList       = AliasSeq!(IntegralTypeList, FloatingPointTypeList);
209     alias CharTypeList          = AliasSeq!(char, wchar, dchar);
210 }
211 
212 /**
213  * Params:
214  *     T = The type to qualify
215  * Returns:
216  *     `T` with the `inout` qualifier added.
217  */
218 alias InoutOf(T) = inout(T);
219 
220 ///
221 @safe unittest
222 {
223     static assert(is(InoutOf!(int) == inout int));
224     static assert(is(InoutOf!(inout int) == inout int));
225     static assert(is(InoutOf!(const int) == inout const int));
226     static assert(is(InoutOf!(shared int) == inout shared int));
227 }
228 
229 /**
230  * Params:
231  *     T = The type to qualify
232  * Returns:
233  *     `T` with the `const` qualifier added.
234  */
235 alias ConstOf(T) = const(T);
236 
237 ///
238 @safe unittest
239 {
240     static assert(is(ConstOf!(int) == const int));
241     static assert(is(ConstOf!(const int) == const int));
242     static assert(is(ConstOf!(inout int) == const inout int));
243     static assert(is(ConstOf!(shared int) == const shared int));
244 }
245 
246 /**
247  * Params:
248  *     T = The type to qualify
249  * Returns:
250  *     `T` with the `shared` qualifier added.
251  */
252 alias SharedOf(T) = shared(T);
253 
254 ///
255 @safe unittest
256 {
257     static assert(is(SharedOf!(int) == shared int));
258     static assert(is(SharedOf!(shared int) == shared int));
259     static assert(is(SharedOf!(inout int) == shared inout int));
260     static assert(is(SharedOf!(immutable int) == shared immutable int));
261 }
262 
263 /**
264  * Params:
265  *     T = The type to qualify
266  * Returns:
267  *     `T` with the `inout` and `shared` qualifiers added.
268  */
269 alias SharedInoutOf(T) = shared(inout(T));
270 
271 ///
272 @safe unittest
273 {
274     static assert(is(SharedInoutOf!(int) == shared inout int));
275     static assert(is(SharedInoutOf!(int) == inout shared int));
276 
277     static assert(is(SharedInoutOf!(const int) == shared inout const int));
278     static assert(is(SharedInoutOf!(immutable int) == shared inout immutable int));
279 }
280 
281 /**
282  * Params:
283  *     T = The type to qualify
284  * Returns:
285  *     `T` with the `const` and `shared` qualifiers added.
286  */
287 alias SharedConstOf(T) = shared(const(T));
288 
289 ///
290 @safe unittest
291 {
292     static assert(is(SharedConstOf!(int) == shared const int));
293     static assert(is(SharedConstOf!(int) == const shared int));
294 
295     static assert(is(SharedConstOf!(inout int) == shared inout const int));
296     // immutable variables are implicitly shared and const
297     static assert(is(SharedConstOf!(immutable int) == immutable int));
298 }
299 
300 /**
301  * Params:
302  *     T = The type to qualify
303  * Returns:
304  *     `T` with the `const`, `shared`, and `inout` qualifiers added.
305  */
306 alias SharedConstInoutOf(T) = shared(const(inout(T)));
307 
308 ///
309 @safe unittest
310 {
311     static assert(is(SharedConstInoutOf!(int) == shared const inout int));
312     static assert(is(SharedConstInoutOf!(int) == const shared inout int));
313     static assert(is(SharedConstInoutOf!(inout int) == shared inout const int));
314     // immutable variables are implicitly shared and const
315     static assert(is(SharedConstInoutOf!(immutable int) == immutable int));
316 }
317 
318 /**
319  * Params:
320  *     T = The type to qualify
321  * Returns:
322  *     `T` with the `immutable` qualifier added.
323  */
324 alias ImmutableOf(T) = immutable(T);
325 
326 ///
327 @safe unittest
328 {
329     static assert(is(ImmutableOf!(int) == immutable int));
330     static assert(is(ImmutableOf!(const int) == immutable int));
331     static assert(is(ImmutableOf!(inout int) == immutable int));
332     static assert(is(ImmutableOf!(shared int) == immutable int));
333 }
334 
335 @safe unittest
336 {
337     static assert(is(      InoutOf!int ==        inout int));
338     static assert(is(      ConstOf!int ==        const int));
339     static assert(is(     SharedOf!int == shared       int));
340     static assert(is(SharedInoutOf!int == shared inout int));
341     static assert(is(SharedConstOf!int == shared const int));
342     static assert(is(  ImmutableOf!int ==    immutable int));
343 }
344 
345 /**
346  * Gives a template that can be used to apply the same
347  * attributes that are on the given type `T`. E.g. passing
348  * `inout shared int` will return `SharedInoutOf`.
349  *
350  * Params:
351  *     T = the type to check qualifiers from
352  * Returns:
353  *     The qualifier template from the given type `T`
354  */
355 template QualifierOf(T)
356 {
357     static if (is(immutable T == T))
358     {
359         alias QualifierOf = ImmutableOf;
360     }
361     else
362     {
363         private enum quals = is(const T == T) | (is(inout T == T) << 1) | (is(shared T == T) << 2);
364         static if (quals == 0)      { import std.meta : Alias; alias QualifierOf = Alias; }
365         else static if (quals == 1) alias QualifierOf = ConstOf;
366         else static if (quals == 2) alias QualifierOf = InoutOf;
367         else static if (quals == 3) alias QualifierOf = ConstInoutOf;
368         else static if (quals == 4) alias QualifierOf = SharedOf;
369         else static if (quals == 5) alias QualifierOf = SharedConstOf;
370         else static if (quals == 6) alias QualifierOf = SharedInoutOf;
371         else                        alias QualifierOf = SharedConstInoutOf;
372     }
373 }
374 
375 ///
376 @safe unittest
377 {
378     static assert(__traits(isSame, QualifierOf!(shared const inout int), SharedConstInoutOf));
379     static assert(__traits(isSame, QualifierOf!(immutable int), ImmutableOf));
380     static assert(__traits(isSame, QualifierOf!(shared int), SharedOf));
381     static assert(__traits(isSame, QualifierOf!(shared inout int), SharedInoutOf));
382     import std.meta : Alias;
383     static assert(__traits(isSame, QualifierOf!(int), Alias));
384 }
385 
386 @safe unittest
387 {
388     alias Qual1 = QualifierOf!(             int);   static assert(is(Qual1!long ==              long));
389     alias Qual2 = QualifierOf!(       inout int);   static assert(is(Qual2!long ==        inout long));
390     alias Qual3 = QualifierOf!(       const int);   static assert(is(Qual3!long ==        const long));
391     alias Qual4 = QualifierOf!(shared       int);   static assert(is(Qual4!long == shared       long));
392     alias Qual5 = QualifierOf!(shared inout int);   static assert(is(Qual5!long == shared inout long));
393     alias Qual6 = QualifierOf!(shared const int);   static assert(is(Qual6!long == shared const long));
394     alias Qual7 = QualifierOf!(   immutable int);   static assert(is(Qual7!long ==    immutable long));
395 }
396 
397 version (StdUnittest)
398 {
399     import std.meta : Alias;
400     alias TypeQualifierList = AliasSeq!(Alias, ConstOf, SharedOf, SharedConstOf, ImmutableOf);
401 
402     struct SubTypeOf(T)
403     {
404         T val;
405         alias val this;
406     }
407 }
408 
409 private alias parentOf(alias sym) = Identity!(__traits(parent, sym));
410 private alias parentOf(alias sym : T!Args, alias T, Args...) = Identity!(__traits(parent, T));
411 
412 /**
413  * Get the full package name for the given symbol.
414  */
415 template packageName(alias T)
416 {
417     import std.algorithm.searching : startsWith;
418 
419     enum bool isNotFunc = !isSomeFunction!(T);
420 
421     static if (__traits(compiles, parentOf!T))
422         enum parent = packageName!(parentOf!T);
423     else
424         enum string parent = null;
425 
426     static if (isNotFunc && T.stringof.startsWith("package "))
427         enum packageName = (parent.length ? parent ~ '.' : "") ~ T.stringof[8 .. $];
428     else static if (parent)
429         enum packageName = parent;
430     else
431         static assert(false, T.stringof ~ " has no parent");
432 }
433 
434 ///
435 @safe unittest
436 {
437     static assert(packageName!packageName == "std");
438 }
439 
440 @safe unittest
441 {
442     import std.array;
443 
444     static assert(packageName!std == "std");
445     static assert(packageName!(std.traits) == "std");     // this module
446     static assert(packageName!packageName == "std");      // symbol in this module
447     static assert(packageName!(std.array) == "std");  // other module from same package
448 
449     import core.sync.barrier;  // local import
450     static assert(packageName!core == "core");
451     static assert(packageName!(core.sync) == "core.sync");
452     static assert(packageName!Barrier == "core.sync");
453 
454     struct X12287(T) { T i; }
455     static assert(packageName!(X12287!int.i) == "std");
456 }
457 
458 version (none) @safe unittest //Please uncomment me when changing packageName to test global imports
459 {
460     import core.sync.barrier;  // global import
461     static assert(packageName!core == "core");
462     static assert(packageName!(core.sync) == "core.sync");
463     static assert(packageName!Barrier == "core.sync");
464 }
465 
466 ///
467 @safe unittest
468 {
469     static assert(packageName!moduleName == "std");
470 }
471 
472 // https://issues.dlang.org/show_bug.cgi?id=13741
473 @safe unittest
474 {
475     import std.ascii : isWhite;
476     static assert(packageName!(isWhite) == "std");
477 
478     struct Foo{void opCall(int){}}
479     static assert(packageName!(Foo.opCall) == "std");
480 
481     @property void function(int) vf;
482     static assert(packageName!(vf) == "std");
483 }
484 
485 /**
486  * Get the module name (including package) for the given symbol.
487  */
488 template moduleName(alias T)
489 {
490     import std.algorithm.searching : startsWith;
491 
492     enum bool isNotFunc = !isSomeFunction!(T);
493 
494     static if (isNotFunc)
495         static assert(!T.stringof.startsWith("package "),
496             "cannot get the module name for a package");
497 
498     static if (isNotFunc && T.stringof.startsWith("module "))
499     {
500         static if (__traits(compiles, packageName!T))
501             enum packagePrefix = packageName!T ~ '.';
502         else
503             enum packagePrefix = "";
504 
505         enum moduleName = packagePrefix ~ T.stringof[7..$];
506     }
507     else
508         alias moduleName = moduleName!(parentOf!T); // If you use enum, it will cause compiler ICE
509 }
510 
511 ///
512 @safe unittest
513 {
514     static assert(moduleName!moduleName == "std.traits");
515 }
516 
517 @safe unittest
518 {
519     import std.array;
520 
521     static assert(!__traits(compiles, moduleName!std));
522     static assert(moduleName!(std.traits) == "std.traits");            // this module
523     static assert(moduleName!moduleName == "std.traits");              // symbol in this module
524     static assert(moduleName!(std.array) == "std.array");      // other module
525     static assert(moduleName!(std.array.array) == "std.array");  // symbol in other module
526 
527     import core.sync.barrier;  // local import
528     static assert(!__traits(compiles, moduleName!(core.sync)));
529     static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
530     static assert(moduleName!Barrier == "core.sync.barrier");
531 
532     struct X12287(T) { T i; }
533     static assert(moduleName!(X12287!int.i) == "std.traits");
534 }
535 
536 // https://issues.dlang.org/show_bug.cgi?id=13741
537 @safe unittest
538 {
539     import std.ascii : isWhite;
540     static assert(moduleName!(isWhite) == "std.ascii");
541 
542     struct Foo{void opCall(int){}}
543     static assert(moduleName!(Foo.opCall) == "std.traits");
544 
545     @property void function(int) vf;
546     static assert(moduleName!(vf) == "std.traits");
547 }
548 
549 version (none) @safe unittest //Please uncomment me when changing moduleName to test global imports
550 {
551     import core.sync.barrier;  // global import
552     static assert(!__traits(compiles, moduleName!(core.sync)));
553     static assert(moduleName!(core.sync.barrier) == "core.sync.barrier");
554     static assert(moduleName!Barrier == "core.sync.barrier");
555 }
556 
557 /***
558  * Get the fully qualified name of a type or a symbol. Can act as an intelligent type/symbol to string  converter.
559 
560 Example:
561 -----------------
562 module myModule;
563 struct MyStruct {}
564 static assert(fullyQualifiedName!(const MyStruct[]) == "const(myModule.MyStruct[])");
565 -----------------
566 */
567 enum fullyQualifiedName(T) = fqnType!(T, false, false, false, false);
568 
569 /// ditto
570 enum fullyQualifiedName(alias T) = fqnSym!(T);
571 
572 ///
573 @safe unittest
574 {
575     static assert(fullyQualifiedName!fullyQualifiedName == "std.traits.fullyQualifiedName");
576 }
577 
578 version (StdUnittest)
579 {
580     // Used for both fqnType and fqnSym unittests
581     private struct QualifiedNameTests
582     {
583         struct Inner
584         {
585             bool value;
586         }
587 
588         ref const(Inner[string]) func( ref Inner var1, lazy scope string var2 );
589         ref const(Inner[string]) retfunc( return ref Inner var1 );
590         Inner inoutFunc(inout Inner) inout;
591         shared(const(Inner[string])[]) data;
592         const Inner delegate(double, string) @safe nothrow deleg;
593         inout(int) delegate(inout int) inout inoutDeleg;
594         Inner function(out double, string) funcPtr;
595         extern(C) Inner function(double, string) cFuncPtr;
596 
597         extern(C) void cVarArg(int, ...);
598         void dVarArg(...);
599         void dVarArg2(int, ...);
600         void typesafeVarArg(int[] ...);
601 
602         Inner[] array;
603         Inner[16] sarray;
604         Inner[Inner] aarray;
605         const(Inner[const(Inner)]) qualAarray;
606 
607         shared(immutable(Inner) delegate(ref double, scope string) const shared @trusted nothrow) attrDeleg;
608 
609         struct Data(T) { int x; }
610         void tfunc(T...)(T args) {}
611 
612         template Inst(alias A) { int x; }
613 
614         class Test12309(T, int x, string s) {}
615     }
616 
617     private enum QualifiedEnum
618     {
619         a = 42
620     }
621 }
622 
623 private template fqnSym(alias T : X!A, alias X, A...)
624 {
625     template fqnTuple(T...)
626     {
627         static if (T.length == 0)
628             enum fqnTuple = "";
629         else static if (T.length == 1)
630         {
631             static if (isExpressionTuple!T)
632                 enum fqnTuple = T[0].stringof;
633             else
634                 enum fqnTuple = fullyQualifiedName!(T[0]);
635         }
636         else
637             enum fqnTuple = fqnTuple!(T[0]) ~ ", " ~ fqnTuple!(T[1 .. $]);
638     }
639 
640     enum fqnSym =
641         fqnSym!(__traits(parent, X)) ~
642         '.' ~ __traits(identifier, X) ~ "!(" ~ fqnTuple!A ~ ")";
643 }
644 
645 private template fqnSym(alias T)
646 {
647     static if (__traits(compiles, __traits(parent, T)) && !__traits(isSame, T, __traits(parent, T)))
648         enum parentPrefix = fqnSym!(__traits(parent, T)) ~ ".";
649     else
650         enum parentPrefix = null;
651 
652     static string adjustIdent(string s)
653     {
654         import std.algorithm.searching : findSplit, skipOver;
655 
656         if (s.skipOver("package ") || s.skipOver("module "))
657             return s;
658         return s.findSplit("(")[0];
659     }
660     enum fqnSym = parentPrefix ~ adjustIdent(__traits(identifier, T));
661 }
662 
663 @safe unittest
664 {
665     alias fqn = fullyQualifiedName;
666 
667     // Make sure those 2 are the same
668     static assert(fqnSym!fqn == fqn!fqn);
669 
670     static assert(fqn!fqn == "std.traits.fullyQualifiedName");
671 
672     alias qnTests = QualifiedNameTests;
673     enum prefix = "std.traits.QualifiedNameTests.";
674     static assert(fqn!(qnTests.Inner)           == prefix ~ "Inner");
675     static assert(fqn!(qnTests.func)            == prefix ~ "func");
676     static assert(fqn!(qnTests.Data!int)        == prefix ~ "Data!(int)");
677     static assert(fqn!(qnTests.Data!int.x)      == prefix ~ "Data!(int).x");
678     static assert(fqn!(qnTests.tfunc!(int[]))   == prefix ~ "tfunc!(int[])");
679     static assert(fqn!(qnTests.Inst!(Object))   == prefix ~ "Inst!(object.Object)");
680     static assert(fqn!(qnTests.Inst!(Object).x) == prefix ~ "Inst!(object.Object).x");
681 
682     static assert(fqn!(qnTests.Test12309!(int, 10, "str"))
683                                                 == prefix ~ "Test12309!(int, 10, \"str\")");
684 
685     import core.sync.barrier;
686     static assert(fqn!Barrier == "core.sync.barrier.Barrier");
687 }
688 
689 @safe unittest
690 {
691     struct TemplatedStruct()
692     {
693         enum foo = 0;
694     }
695     alias TemplatedStructAlias = TemplatedStruct;
696     assert("TemplatedStruct.foo" == fullyQualifiedName!(TemplatedStructAlias!().foo));
697 }
698 
699 private template fqnType(T,
700     bool alreadyConst, bool alreadyImmutable, bool alreadyShared, bool alreadyInout)
701 {
702     // Convenience tags
703     enum {
704         _const = 0,
705         _immutable = 1,
706         _shared = 2,
707         _inout = 3
708     }
709 
710     alias qualifiers   = AliasSeq!(is(T == const), is(T == immutable), is(T == shared), is(T == inout));
711     alias noQualifiers = AliasSeq!(false, false, false, false);
712 
713     string storageClassesString(uint psc)() @property
714     {
715         import std.conv : text;
716 
717         alias PSC = ParameterStorageClass;
718 
719         return text(
720             psc & PSC.scope_ ? "scope " : "",
721             psc & PSC.return_ ? "return " : "",
722             psc & PSC.in_ ? "in " : "",
723             psc & PSC.out_ ? "out " : "",
724             psc & PSC.ref_ ? "ref " : "",
725             psc & PSC.lazy_ ? "lazy " : "",
726         );
727     }
728 
729     string parametersTypeString(T)() @property
730     {
731         alias parameters   = Parameters!(T);
732         alias parameterStC = ParameterStorageClassTuple!(T);
733 
734         enum variadic = variadicFunctionStyle!T;
735         static if (variadic == Variadic.no)
736             enum variadicStr = "";
737         else static if (variadic == Variadic.c)
738             enum variadicStr = ", ...";
739         else static if (variadic == Variadic.d)
740             enum variadicStr = parameters.length ? ", ..." : "...";
741         else static if (variadic == Variadic.typesafe)
742             enum variadicStr = " ...";
743         else
744             static assert(0, "New variadic style has been added, please update fullyQualifiedName implementation");
745 
746         static if (parameters.length)
747         {
748             import std.algorithm.iteration : map;
749             import std.array : join;
750             import std.meta : staticMap;
751             import std.range : zip;
752 
753             string result = join(
754                 map!(a => (a[0] ~ a[1]))(
755                     zip([staticMap!(storageClassesString, parameterStC)],
756                         [staticMap!(fullyQualifiedName, parameters)])
757                 ),
758                 ", "
759             );
760 
761             return result ~= variadicStr;
762         }
763         else
764             return variadicStr;
765     }
766 
767     string linkageString(T)() @property
768     {
769         enum linkage = functionLinkage!T;
770 
771         if (linkage != "D")
772             return "extern(" ~ linkage ~ ") ";
773         else
774             return "";
775     }
776 
777     string functionAttributeString(T)() @property
778     {
779         alias FA = FunctionAttribute;
780         enum attrs = functionAttributes!T;
781 
782         static if (attrs == FA.none)
783             return "";
784         else
785             return
786                 (attrs & FA.pure_ ? " pure" : "")
787                 ~ (attrs & FA.nothrow_ ? " nothrow" : "")
788                 ~ (attrs & FA.ref_ ? " ref" : "")
789                 ~ (attrs & FA.property ? " @property" : "")
790                 ~ (attrs & FA.trusted ? " @trusted" : "")
791                 ~ (attrs & FA.safe ? " @safe" : "")
792                 ~ (attrs & FA.nogc ? " @nogc" : "")
793                 ~ (attrs & FA.return_ ? " return" : "")
794                 ~ (attrs & FA.live ? " @live" : "");
795     }
796 
797     string addQualifiers(string typeString,
798         bool addConst, bool addImmutable, bool addShared, bool addInout)
799     {
800         auto result = typeString;
801         if (addShared)
802         {
803             result = "shared(" ~ result ~")";
804         }
805         if (addConst || addImmutable || addInout)
806         {
807             result = (addConst ? "const" : addImmutable ? "immutable" : "inout")
808                 ~ "(" ~ result ~ ")";
809         }
810         return result;
811     }
812 
813     // Convenience template to avoid copy-paste
814     template chain(string current)
815     {
816         enum chain = addQualifiers(current,
817             qualifiers[_const]     && !alreadyConst,
818             qualifiers[_immutable] && !alreadyImmutable,
819             qualifiers[_shared]    && !alreadyShared,
820             qualifiers[_inout]     && !alreadyInout);
821     }
822 
823     static if (is(T == string))
824     {
825         enum fqnType = "string";
826     }
827     else static if (is(T == wstring))
828     {
829         enum fqnType = "wstring";
830     }
831     else static if (is(T == dstring))
832     {
833         enum fqnType = "dstring";
834     }
835     else static if (is(T == typeof(null)))
836     {
837         enum fqnType = "typeof(null)";
838     }
839     else static if (isBasicType!T && !is(T == enum))
840     {
841         enum fqnType = chain!((Unqual!T).stringof);
842     }
843     else static if (isAggregateType!T || is(T == enum))
844     {
845         enum fqnType = chain!(fqnSym!T);
846     }
847     else static if (isStaticArray!T)
848     {
849         import std.conv : to;
850         enum fqnType = chain!(
851             fqnType!(typeof(T.init[0]), qualifiers) ~ "[" ~ to!string(T.length) ~ "]"
852         );
853     }
854     else static if (isArray!T)
855     {
856         enum fqnType = chain!(
857             fqnType!(typeof(T.init[0]), qualifiers) ~ "[]"
858         );
859     }
860     else static if (isAssociativeArray!T)
861     {
862         enum fqnType = chain!(
863             fqnType!(ValueType!T, qualifiers) ~ '[' ~ fqnType!(KeyType!T, noQualifiers) ~ ']'
864         );
865     }
866     else static if (isSomeFunction!T)
867     {
868         static if (is(T F == delegate))
869         {
870             enum qualifierString =
871                 (is(F == shared) ? " shared" : "")
872                 ~ (is(F == inout) ? " inout" :
873                     is(F == immutable) ? " immutable" :
874                     is(F == const) ? " const" : "");
875             enum fqnType = chain!(
876                 linkageString!T
877                 ~ fqnType!(ReturnType!T, noQualifiers)
878                 ~ " delegate(" ~ parametersTypeString!(T) ~ ")"
879                 ~ functionAttributeString!T
880                 ~ qualifierString
881             );
882         }
883         else
884         {
885             enum fqnType = chain!(
886                 linkageString!T
887                 ~ fqnType!(ReturnType!T, noQualifiers)
888                 ~ (isFunctionPointer!T ? " function(" : "(")
889                 ~ parametersTypeString!(T) ~ ")"
890                 ~ functionAttributeString!T
891             );
892         }
893     }
894     else static if (is(T == U*, U))
895     {
896         enum fqnType = chain!(
897             fqnType!(U, qualifiers) ~ "*"
898         );
899     }
900     else static if (is(T : __vector(V[N]), V, size_t N))
901     {
902         import std.conv : to;
903         enum fqnType = chain!(
904             "__vector(" ~ fqnType!(V, qualifiers) ~ "[" ~ N.to!string ~ "])"
905         );
906     }
907     else
908         // In case something is forgotten
909         static assert(0, "Unrecognized type " ~ T.stringof ~ ", can't convert to fully qualified string");
910 }
911 
912 @safe unittest
913 {
914     import std.format : format;
915     alias fqn = fullyQualifiedName;
916 
917     // Verify those 2 are the same for simple case
918     alias Ambiguous = const(QualifiedNameTests.Inner);
919     static assert(fqn!Ambiguous == fqnType!(Ambiguous, false, false, false, false));
920 
921     // Main tests
922     enum inner_name = "std.traits.QualifiedNameTests.Inner";
923     with (QualifiedNameTests)
924     {
925         // Special cases
926         static assert(fqn!(string) == "string");
927         static assert(fqn!(wstring) == "wstring");
928         static assert(fqn!(dstring) == "dstring");
929         static assert(fqn!(typeof(null)) == "typeof(null)");
930         static assert(fqn!(void) == "void");
931         static assert(fqn!(const(void)) == "const(void)");
932         static assert(fqn!(shared(void)) == "shared(void)");
933         static assert(fqn!(shared const(void)) == "const(shared(void))");
934         static assert(fqn!(shared inout(void)) == "inout(shared(void))");
935         static assert(fqn!(shared inout const(void)) == "const(shared(void))");
936         static assert(fqn!(inout(void)) == "inout(void)");
937         static assert(fqn!(inout const(void)) == "const(void)");
938         static assert(fqn!(immutable(void)) == "immutable(void)");
939 
940         // Basic qualified name
941         static assert(fqn!(Inner) == inner_name);
942         static assert(fqn!(QualifiedEnum) == "std.traits.QualifiedEnum"); // type
943         static assert(fqn!(QualifiedEnum.a) == "std.traits.QualifiedEnum.a"); // symbol
944 
945         // Array types
946         static assert(fqn!(typeof(array)) == format("%s[]", inner_name));
947         static assert(fqn!(typeof(sarray)) == format("%s[16]", inner_name));
948         static assert(fqn!(typeof(aarray)) == format("%s[%s]", inner_name, inner_name));
949 
950         // qualified key for AA
951         static assert(fqn!(typeof(qualAarray)) == format("const(%s[const(%s)])", inner_name, inner_name));
952 
953         // Qualified composed data types
954         static assert(fqn!(typeof(data)) == format("shared(const(%s[string])[])", inner_name));
955 
956         // Function types + function attributes
957         static assert(fqn!(typeof(func)) == format("const(%s[string])(ref %s, scope lazy string) ref",
958                     inner_name, inner_name));
959         static assert(fqn!(typeof(retfunc)) == format("const(%s[string])(return %s) ref", inner_name, inner_name));
960         static assert(fqn!(typeof(inoutFunc)) == format("inout(%s(inout(%s)))", inner_name, inner_name));
961         static assert(fqn!(typeof(deleg)) == format("const(%s delegate(double, string) nothrow @safe)", inner_name));
962         static assert(fqn!(typeof(inoutDeleg)) == "inout(int) delegate(inout(int)) inout");
963         static assert(fqn!(typeof(funcPtr)) == format("%s function(out double, string)", inner_name));
964         static assert(fqn!(typeof(cFuncPtr)) == format("extern(C) %s function(double, string)", inner_name));
965 
966         // Delegate type with qualified function type
967         static assert(fqn!(typeof(attrDeleg)) == format("shared(immutable(%s) "~
968             "delegate(ref double, scope string) nothrow @trusted shared const)", inner_name));
969 
970         // Variable argument function types
971         static assert(fqn!(typeof(cVarArg)) == "extern(C) void(int, ...)");
972         static assert(fqn!(typeof(dVarArg)) == "void(...)");
973         static assert(fqn!(typeof(dVarArg2)) == "void(int, ...)");
974         static assert(fqn!(typeof(typesafeVarArg)) == "void(int[] ...)");
975 
976         // SIMD vector
977         static if (is(__vector(float[4])))
978         {
979             static assert(fqn!(__vector(float[4])) == "__vector(float[4])");
980         }
981     }
982 }
983 
984 /***
985  * Get the type of the return value from a function,
986  * a pointer to function, a delegate, a struct
987  * with an opCall, a pointer to a struct with an opCall,
988  * or a class with an `opCall`. Please note that $(D_KEYWORD ref)
989  * is not part of a type, but the attribute of the function
990  * (see template $(LREF functionAttributes)).
991  *
992  * $(NOTE To reduce template instantiations, consider instead using
993  * $(D typeof(() { return func(args); } ())) if the argument types are known or
994  * $(D static if (is(typeof(func) Ret == return))) if only that basic test is needed.)
995  */
996 template ReturnType(alias func)
997 if (isCallable!func)
998 {
999     static if (is(FunctionTypeOf!func R == return))
1000         alias ReturnType = R;
1001     else
1002         static assert(0, "argument has no return type");
1003 }
1004 
1005 ///
1006 @safe unittest
1007 {
1008     int foo();
1009     ReturnType!foo x;   // x is declared as int
1010 }
1011 
1012 @safe unittest
1013 {
1014     struct G
1015     {
1016         int opCall (int i) { return 1;}
1017     }
1018 
1019     alias ShouldBeInt = ReturnType!G;
1020     static assert(is(ShouldBeInt == int));
1021 
1022     G g;
1023     static assert(is(ReturnType!g == int));
1024 
1025     G* p;
1026     alias pg = ReturnType!p;
1027     static assert(is(pg == int));
1028 
1029     class C
1030     {
1031         int opCall (int i) { return 1;}
1032     }
1033 
1034     static assert(is(ReturnType!C == int));
1035 
1036     C c;
1037     static assert(is(ReturnType!c == int));
1038 
1039     class Test
1040     {
1041         int prop() @property { return 0; }
1042     }
1043     alias R_Test_prop = ReturnType!(Test.prop);
1044     static assert(is(R_Test_prop == int));
1045 
1046     alias R_dglit = ReturnType!((int a) { return a; });
1047     static assert(is(R_dglit == int));
1048 }
1049 
1050 /***
1051 Get, as a tuple, the types of the parameters to a function, a pointer
1052 to function, a delegate, a struct with an `opCall`, a pointer to a
1053 struct with an `opCall`, or a class with an `opCall`.
1054 */
1055 template Parameters(alias func)
1056 if (isCallable!func)
1057 {
1058     static if (is(FunctionTypeOf!func P == function))
1059         alias Parameters = P;
1060     else
1061         static assert(0, "argument has no parameters");
1062 }
1063 
1064 ///
1065 @safe unittest
1066 {
1067     int foo(int, long);
1068     void bar(Parameters!foo);      // declares void bar(int, long);
1069     void abc(Parameters!foo[1]);   // declares void abc(long);
1070 }
1071 
1072 /**
1073  * Alternate name for $(LREF Parameters), kept for legacy compatibility.
1074  */
1075 alias ParameterTypeTuple = Parameters;
1076 
1077 @safe unittest
1078 {
1079     int foo(int i, bool b) { return 0; }
1080     static assert(is(ParameterTypeTuple!foo == AliasSeq!(int, bool)));
1081     static assert(is(ParameterTypeTuple!(typeof(&foo)) == AliasSeq!(int, bool)));
1082 
1083     struct S { real opCall(real r, int i) { return 0.0; } }
1084     S s;
1085     static assert(is(ParameterTypeTuple!S == AliasSeq!(real, int)));
1086     static assert(is(ParameterTypeTuple!(S*) == AliasSeq!(real, int)));
1087     static assert(is(ParameterTypeTuple!s == AliasSeq!(real, int)));
1088 
1089     class Test
1090     {
1091         int prop() @property { return 0; }
1092     }
1093     alias P_Test_prop = ParameterTypeTuple!(Test.prop);
1094     static assert(P_Test_prop.length == 0);
1095 
1096     alias P_dglit = ParameterTypeTuple!((int a){});
1097     static assert(P_dglit.length == 1);
1098     static assert(is(P_dglit[0] == int));
1099 }
1100 
1101 /**
1102 Returns the number of arguments of function `func`.
1103 arity is undefined for variadic functions.
1104 */
1105 template arity(alias func)
1106 if (isCallable!func && variadicFunctionStyle!func == Variadic.no)
1107 {
1108     enum size_t arity = Parameters!func.length;
1109 }
1110 
1111 ///
1112 @safe unittest
1113 {
1114     void foo(){}
1115     static assert(arity!foo == 0);
1116     void bar(uint){}
1117     static assert(arity!bar == 1);
1118     void variadicFoo(uint...){}
1119     static assert(!__traits(compiles, arity!variadicFoo));
1120 }
1121 
1122 // https://issues.dlang.org/show_bug.cgi?id=11389
1123 @safe unittest
1124 {
1125     alias TheType = size_t function( string[] );
1126     static assert(arity!TheType == 1);
1127 }
1128 
1129 /**
1130 Get a tuple of the storage classes of a function's parameters.
1131 Params:
1132     func = function symbol or type of function, delegate, or pointer to function
1133 Returns:
1134     A tuple of ParameterStorageClass bits
1135  */
1136 enum ParameterStorageClass : uint
1137 {
1138     /**
1139      * These flags can be bitwise OR-ed together to represent complex storage
1140      * class.
1141      */
1142     none    = 0x00,
1143     in_     = 0x01, /// ditto
1144     ref_    = 0x02, /// ditto
1145     out_    = 0x04, /// ditto
1146     lazy_   = 0x08, /// ditto
1147     scope_  = 0x10, /// ditto
1148     return_ = 0x20, /// ditto
1149 }
1150 
1151 /// ditto
1152 template ParameterStorageClassTuple(alias func)
1153 if (isCallable!func)
1154 {
1155     alias Func = FunctionTypeOf!func;
1156 
1157     static if (is(Func PT == __parameters))
1158     {
1159         alias ParameterStorageClassTuple = AliasSeq!();
1160         static foreach (i; 0 .. PT.length)
1161         {
1162             ParameterStorageClassTuple = AliasSeq!(ParameterStorageClassTuple,
1163                 extractParameterStorageClassFlags!(__traits(getParameterStorageClasses, Func, i)));
1164         }
1165     }
1166     else
1167     {
1168         static assert(0, func.stringof, " is not a function");
1169         alias ParameterStorageClassTuple = AliasSeq!();
1170     }
1171 }
1172 
1173 ///
1174 @safe unittest
1175 {
1176     alias STC = ParameterStorageClass; // shorten the enum name
1177 
1178     void func(ref int ctx, out real result, in real param, void* ptr)
1179     {
1180     }
1181     alias pstc = ParameterStorageClassTuple!func;
1182     static assert(pstc.length == 4); // number of parameters
1183     static assert(pstc[0] == STC.ref_);
1184     static assert(pstc[1] == STC.out_);
1185     version (none)
1186     {
1187         // TODO: When the DMD PR (dlang/dmd#11474) gets merged,
1188         // remove the versioning and the second test
1189         static assert(pstc[2] == STC.in_);
1190         // This is the current behavior, before `in` is fixed to not be an alias
1191         static assert(pstc[2] == STC.scope_);
1192     }
1193     static assert(pstc[3] == STC.none);
1194 }
1195 
1196 /**
1197 Convert the result of $(DDSUBLINK spec/traits, getParameterStorageClasses, `__traits(getParameterStorageClasses)`)
1198 to $(LREF ParameterStorageClass) `enum`s.
1199 
1200 Params:
1201     Attribs = The return value of `__traits(getParameterStorageClasses)`
1202 Returns:
1203     The bitwise OR of the equivalent $(LREF ParameterStorageClass) `enum`s.
1204  */
1205 template extractParameterStorageClassFlags(Attribs...)
1206 {
1207     enum ParameterStorageClass extractParameterStorageClassFlags = ()
1208     {
1209         auto result = ParameterStorageClass.none;
1210         static if (Attribs.length > 0)
1211         {
1212             static foreach (attrib; Attribs)
1213             {
1214                 final switch (attrib) with (ParameterStorageClass)
1215                 {
1216                     case "scope":  result |= scope_;  break;
1217                     case "in":     result |= in_;    break;
1218                     case "out":    result |= out_;    break;
1219                     case "ref":    result |= ref_;    break;
1220                     case "lazy":   result |= lazy_;   break;
1221                     case "return": result |= return_; break;
1222                 }
1223             }
1224             /* Mimic behavor of original version of ParameterStorageClassTuple()
1225              * to avoid breaking existing code.
1226              */
1227             if (result == (ParameterStorageClass.ref_ | ParameterStorageClass.return_))
1228                 result = ParameterStorageClass.return_;
1229         }
1230         return result;
1231     }();
1232 }
1233 
1234 ///
1235 @safe unittest
1236 {
1237     static void func(ref int ctx, out real result);
1238 
1239     enum param1 = extractParameterStorageClassFlags!(
1240         __traits(getParameterStorageClasses, func, 0)
1241     );
1242     static assert(param1 == ParameterStorageClass.ref_);
1243 
1244     enum param2 = extractParameterStorageClassFlags!(
1245         __traits(getParameterStorageClasses, func, 1)
1246     );
1247     static assert(param2 == ParameterStorageClass.out_);
1248 
1249     enum param3 = extractParameterStorageClassFlags!(
1250         __traits(getParameterStorageClasses, func, 0),
1251         __traits(getParameterStorageClasses, func, 1)
1252     );
1253     static assert(param3 == (ParameterStorageClass.ref_ | ParameterStorageClass.out_));
1254 }
1255 
1256 @safe unittest
1257 {
1258     alias STC = ParameterStorageClass;
1259 
1260     void noparam() {}
1261     static assert(ParameterStorageClassTuple!noparam.length == 0);
1262 
1263     ref int test(scope int*, ref int, out int, lazy int, int, return ref int i) { return i; }
1264     alias test_pstc = ParameterStorageClassTuple!test;
1265     static assert(test_pstc.length == 6);
1266     static assert(test_pstc[0] == STC.scope_);
1267     static assert(test_pstc[1] == STC.ref_);
1268     static assert(test_pstc[2] == STC.out_);
1269     static assert(test_pstc[3] == STC.lazy_);
1270     static assert(test_pstc[4] == STC.none);
1271     static assert(test_pstc[5] == STC.return_);
1272 
1273     interface Test
1274     {
1275         void test_const(int) const;
1276         void test_sharedconst(int) shared const;
1277     }
1278     Test testi;
1279 
1280     alias test_const_pstc = ParameterStorageClassTuple!(Test.test_const);
1281     static assert(test_const_pstc.length == 1);
1282     static assert(test_const_pstc[0] == STC.none);
1283 
1284     alias test_sharedconst_pstc = ParameterStorageClassTuple!(testi.test_sharedconst);
1285     static assert(test_sharedconst_pstc.length == 1);
1286     static assert(test_sharedconst_pstc[0] == STC.none);
1287 
1288     alias dglit_pstc = ParameterStorageClassTuple!((ref int a) {});
1289     static assert(dglit_pstc.length == 1);
1290     static assert(dglit_pstc[0] == STC.ref_);
1291 
1292     // https://issues.dlang.org/show_bug.cgi?id=9317
1293     static inout(int) func(inout int param) { return param; }
1294     static assert(ParameterStorageClassTuple!(typeof(func))[0] == STC.none);
1295 }
1296 
1297 @safe unittest
1298 {
1299     // https://issues.dlang.org/show_bug.cgi?id=14253
1300     static struct Foo {
1301         ref Foo opAssign(ref Foo rhs) return { return this; }
1302     }
1303 
1304     alias tup = ParameterStorageClassTuple!(__traits(getOverloads, Foo, "opAssign")[0]);
1305 }
1306 
1307 
1308 /**
1309 Get, as a tuple, the identifiers of the parameters to a function symbol.
1310  */
1311 template ParameterIdentifierTuple(alias func)
1312 if (isCallable!func)
1313 {
1314     static if (is(FunctionTypeOf!func PT == __parameters))
1315     {
1316         alias ParameterIdentifierTuple = AliasSeq!();
1317         static foreach (i; 0 .. PT.length)
1318         {
1319             static if (!isFunctionPointer!func && !isDelegate!func
1320                        // Unnamed parameters yield CT error.
1321                        && is(typeof(__traits(identifier, PT[i .. i+1])))
1322                        // Filter out unnamed args, which look like (Type) instead of (Type name).
1323                        && PT[i].stringof != PT[i .. i+1].stringof[1..$-1])
1324             {
1325                 ParameterIdentifierTuple = AliasSeq!(ParameterIdentifierTuple,
1326                     __traits(identifier, PT[i .. i+1]));
1327             }
1328             else
1329             {
1330                 ParameterIdentifierTuple = AliasSeq!(ParameterIdentifierTuple, "");
1331             }
1332         }
1333     }
1334     else
1335     {
1336         static assert(0, func.stringof ~ " is not a function");
1337         // avoid pointless errors
1338         alias ParameterIdentifierTuple = AliasSeq!();
1339     }
1340 }
1341 
1342 ///
1343 @safe unittest
1344 {
1345     int foo(int num, string name, int);
1346     static assert([ParameterIdentifierTuple!foo] == ["num", "name", ""]);
1347 }
1348 
1349 // https://issues.dlang.org/show_bug.cgi?id=19456
1350 @safe unittest
1351 {
1352     struct SomeType {}
1353     void foo(SomeType);
1354     void bar(int);
1355     static assert([ParameterIdentifierTuple!foo] == [""]);
1356     static assert([ParameterIdentifierTuple!bar] == [""]);
1357 }
1358 
1359 @safe unittest
1360 {
1361     alias PIT = ParameterIdentifierTuple;
1362 
1363     void bar(int num, string name, int[] array){}
1364     static assert([PIT!bar] == ["num", "name", "array"]);
1365 
1366     // might be changed in the future?
1367     void function(int num, string name) fp;
1368     static assert([PIT!fp] == ["", ""]);
1369 
1370     // might be changed in the future?
1371     void delegate(int num, string name, int[long] aa) dg;
1372     static assert([PIT!dg] == ["", "", ""]);
1373 
1374     interface Test
1375     {
1376         @property string getter();
1377         @property void setter(int a);
1378         Test method(int a, long b, string c);
1379     }
1380     static assert([PIT!(Test.getter)] == []);
1381     static assert([PIT!(Test.setter)] == ["a"]);
1382     static assert([PIT!(Test.method)] == ["a", "b", "c"]);
1383 
1384 /+
1385     // depends on internal
1386     void baw(int, string, int[]){}
1387     static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]);
1388 
1389     // depends on internal
1390     void baz(AliasSeq!(int, string, int[]) args){}
1391     static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]);
1392 +/
1393 }
1394 
1395 
1396 /**
1397 Get, as a tuple, the default values of the parameters to a function symbol.
1398 If a parameter doesn't have the default value, `void` is returned instead.
1399  */
1400 template ParameterDefaults(alias func)
1401 if (isCallable!func)
1402 {
1403     alias param_names = ParameterIdentifierTuple!func;
1404     static if (is(FunctionTypeOf!(func) PT == __parameters))
1405     {
1406         template Get(size_t i)
1407         {
1408             // `PT[i .. i+1]` declares a parameter with an arbitrary name.
1409             // To avoid a name clash, generate local names that are distinct
1410             // from the parameter name, and mix them in.
1411             enum name = param_names[i];
1412             enum args = "args" ~ (name == "args" ? "_" : "");
1413             enum val = "val" ~ (name == "val" ? "_" : "");
1414             enum ptr = "ptr" ~ (name == "ptr" ? "_" : "");
1415             enum hasDefaultArg = mixin("(PT[i .. i+1] ", args, ") => true");
1416             static if (is(typeof(hasDefaultArg())))
1417             {
1418                 enum get = mixin("(return scope PT[i .. i+1] ", args, ")
1419                 {
1420                     // If the parameter is lazy, we force it to be evaluated
1421                     // like this.
1422                     auto ", val, " = ", args, "[0];
1423                     auto ", ptr, " = &", val, ";
1424                     return *", ptr, ";
1425                 }");
1426                 enum Get = get();
1427             }
1428             else
1429                 alias Get = void;
1430                 // If default arg doesn't exist, returns void instead.
1431         }
1432         alias ParameterDefaults = AliasSeq!();
1433         static foreach (i; 0 .. PT.length)
1434         {
1435             ParameterDefaults = AliasSeq!(ParameterDefaults,
1436                 Get!i);
1437         }
1438     }
1439     else
1440     {
1441         static assert(0, func.stringof ~ " is not a function");
1442         // avoid pointless errors
1443         alias ParameterDefaults = AliasSeq!();
1444     }
1445 }
1446 
1447 ///
1448 @safe unittest
1449 {
1450     int foo(int num, string name = "hello", int[] = [1,2,3], lazy int x = 0);
1451     static assert(is(ParameterDefaults!foo[0] == void));
1452     static assert(   ParameterDefaults!foo[1] == "hello");
1453     static assert(   ParameterDefaults!foo[2] == [1,2,3]);
1454     static assert(   ParameterDefaults!foo[3] == 0);
1455 }
1456 
1457 // https://issues.dlang.org/show_bug.cgi?id=17192
1458 @safe unittest
1459 {
1460     static void func(int i, int PT, int __pd_value, int __pd_val, int __args,
1461         int name, int args, int val, int ptr, int args_, int val_, int ptr_)
1462     {
1463     }
1464     alias Voids = ParameterDefaults!func;
1465     static assert(Voids.length == 12);
1466     static foreach (V; Voids) static assert(is(V == void));
1467 }
1468 
1469 // https://issues.dlang.org/show_bug.cgi?id=20182
1470 @safe pure nothrow @nogc unittest
1471 {
1472     struct S
1473     {
1474         this(ref S) {}
1475     }
1476 
1477     static assert(__traits(compiles, ParameterDefaults!(S.__ctor)));
1478 }
1479 
1480 /**
1481  * Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
1482  */
1483 alias ParameterDefaultValueTuple = ParameterDefaults;
1484 
1485 @safe unittest
1486 {
1487     alias PDVT = ParameterDefaultValueTuple;
1488 
1489     void bar(int n = 1, string s = "hello"){}
1490     static assert(PDVT!bar.length == 2);
1491     static assert(PDVT!bar[0] == 1);
1492     static assert(PDVT!bar[1] == "hello");
1493     static assert(is(typeof(PDVT!bar) == typeof(AliasSeq!(1, "hello"))));
1494 
1495     void baz(int x, int n = 1, string s = "hello"){}
1496     static assert(PDVT!baz.length == 3);
1497     static assert(is(PDVT!baz[0] == void));
1498     static assert(   PDVT!baz[1] == 1);
1499     static assert(   PDVT!baz[2] == "hello");
1500     static assert(is(typeof(PDVT!baz) == typeof(AliasSeq!(void, 1, "hello"))));
1501 
1502     // property functions return empty string
1503     // https://issues.dlang.org/show_bug.cgi?id=10800
1504     @property void foo(int x = 3) { }
1505     static assert(PDVT!foo.length == 1);
1506     static assert(PDVT!foo[0] == 3);
1507     static assert(is(typeof(PDVT!foo) == typeof(AliasSeq!(3))));
1508 
1509     struct Colour
1510     {
1511         ubyte a,r,g,b;
1512 
1513         static immutable Colour white = Colour(255,255,255,255);
1514     }
1515     // https://issues.dlang.org/show_bug.cgi?id=8106
1516     void bug8106(Colour c = Colour.white) {}
1517     //pragma(msg, PDVT!bug8106);
1518     static assert(PDVT!bug8106[0] == Colour.white);
1519     // https://issues.dlang.org/show_bug.cgi?id=16582
1520     void bug16582(scope int* val = null) {}
1521     static assert(PDVT!bug16582[0] is null);
1522 }
1523 
1524 
1525 /**
1526 Returns the FunctionAttribute mask for function `func`.
1527 
1528 See_Also:
1529     $(LREF hasFunctionAttributes)
1530  */
1531 enum FunctionAttribute : uint
1532 {
1533     /**
1534      * These flags can be bitwise OR-ed together to represent a complex attribute.
1535      */
1536     none       = 0,
1537     pure_      = 1 << 0,  /// ditto
1538     nothrow_   = 1 << 1,  /// ditto
1539     ref_       = 1 << 2,  /// ditto
1540     property   = 1 << 3,  /// ditto
1541     trusted    = 1 << 4,  /// ditto
1542     safe       = 1 << 5,  /// ditto
1543     nogc       = 1 << 6,  /// ditto
1544     system     = 1 << 7,  /// ditto
1545     const_     = 1 << 8,  /// ditto
1546     immutable_ = 1 << 9,  /// ditto
1547     inout_     = 1 << 10, /// ditto
1548     shared_    = 1 << 11, /// ditto
1549     return_    = 1 << 12, /// ditto
1550     scope_     = 1 << 13, /// ditto
1551     live       = 1 << 14, /// ditto
1552 }
1553 
1554 /// ditto
1555 template functionAttributes(alias func)
1556 if (isCallable!func)
1557 {
1558     // @bug: workaround for opCall
1559     alias FuncSym = Select!(is(typeof(__traits(getFunctionAttributes, func))),
1560                             func, Unqual!(FunctionTypeOf!func));
1561 
1562     enum FunctionAttribute functionAttributes =
1563         extractAttribFlags!(__traits(getFunctionAttributes, FuncSym))();
1564 }
1565 
1566 ///
1567 @safe unittest
1568 {
1569     alias FA = FunctionAttribute; // shorten the enum name
1570 
1571     real func(real x) pure nothrow @safe
1572     {
1573         return x;
1574     }
1575     static assert(functionAttributes!func & FA.pure_);
1576     static assert(functionAttributes!func & FA.safe);
1577     static assert(!(functionAttributes!func & FA.trusted)); // not @trusted
1578 }
1579 
1580 @system unittest
1581 {
1582     alias FA = FunctionAttribute;
1583 
1584     struct S
1585     {
1586         int noF() { return 0; }
1587         int constF() const { return 0; }
1588         int immutableF() immutable { return 0; }
1589         int inoutF() inout { return 0; }
1590         int sharedF() shared { return 0; }
1591 
1592         int x;
1593         ref int refF() return { return x; }
1594         int propertyF() @property { return 0; }
1595         int nothrowF() nothrow { return 0; }
1596         int nogcF() @nogc { return 0; }
1597 
1598         int systemF() @system { return 0; }
1599         int trustedF() @trusted { return 0; }
1600         int safeF() @safe { return 0; }
1601 
1602         int pureF() pure { return 0; }
1603 
1604         int liveF() @live { return 0; }
1605     }
1606 
1607     static assert(functionAttributes!(S.noF) == FA.system);
1608     static assert(functionAttributes!(typeof(S.noF)) == FA.system);
1609 
1610     static assert(functionAttributes!(S.constF) == (FA.const_ | FA.system));
1611     static assert(functionAttributes!(typeof(S.constF)) == (FA.const_ | FA.system));
1612 
1613     static assert(functionAttributes!(S.immutableF) == (FA.immutable_ | FA.system));
1614     static assert(functionAttributes!(typeof(S.immutableF)) == (FA.immutable_ | FA.system));
1615 
1616     static assert(functionAttributes!(S.inoutF) == (FA.inout_ | FA.system));
1617     static assert(functionAttributes!(typeof(S.inoutF)) == (FA.inout_ | FA.system));
1618 
1619     static assert(functionAttributes!(S.sharedF) == (FA.shared_ | FA.system));
1620     static assert(functionAttributes!(typeof(S.sharedF)) == (FA.shared_ | FA.system));
1621 
1622     static assert(functionAttributes!(S.refF) == (FA.ref_ | FA.system | FA.return_));
1623     static assert(functionAttributes!(typeof(S.refF)) == (FA.ref_ | FA.system | FA.return_));
1624 
1625     static assert(functionAttributes!(S.propertyF) == (FA.property | FA.system));
1626     static assert(functionAttributes!(typeof(&S.propertyF)) == (FA.property | FA.system));
1627 
1628     static assert(functionAttributes!(S.nothrowF) == (FA.nothrow_ | FA.system));
1629     static assert(functionAttributes!(typeof(S.nothrowF)) == (FA.nothrow_ | FA.system));
1630 
1631     static assert(functionAttributes!(S.nogcF) == (FA.nogc | FA.system));
1632     static assert(functionAttributes!(typeof(S.nogcF)) == (FA.nogc | FA.system));
1633 
1634     static assert(functionAttributes!(S.systemF) == FA.system);
1635     static assert(functionAttributes!(typeof(S.systemF)) == FA.system);
1636 
1637     static assert(functionAttributes!(S.trustedF) == FA.trusted);
1638     static assert(functionAttributes!(typeof(S.trustedF)) == FA.trusted);
1639 
1640     static assert(functionAttributes!(S.safeF) == FA.safe);
1641     static assert(functionAttributes!(typeof(S.safeF)) == FA.safe);
1642 
1643     static assert(functionAttributes!(S.pureF) == (FA.pure_ | FA.system));
1644     static assert(functionAttributes!(typeof(S.pureF)) == (FA.pure_ | FA.system));
1645 
1646     static assert(functionAttributes!(S.liveF) == (FA.live | FA.system));
1647     static assert(functionAttributes!(typeof(S.liveF)) == (FA.live | FA.system));
1648 
1649     int pure_nothrow() nothrow pure;
1650     void safe_nothrow() @safe nothrow;
1651     static ref int static_ref_property() @property;
1652     ref int ref_property() @property;
1653 
1654     static assert(functionAttributes!(pure_nothrow) == (FA.pure_ | FA.nothrow_ | FA.system));
1655     static assert(functionAttributes!(typeof(pure_nothrow)) == (FA.pure_ | FA.nothrow_ | FA.system));
1656 
1657     static assert(functionAttributes!(safe_nothrow) == (FA.safe | FA.nothrow_));
1658     static assert(functionAttributes!(typeof(safe_nothrow)) == (FA.safe | FA.nothrow_));
1659 
1660     static assert(functionAttributes!(static_ref_property) == (FA.property | FA.ref_ | FA.system));
1661     static assert(functionAttributes!(typeof(&static_ref_property)) == (FA.property | FA.ref_ | FA.system));
1662 
1663     static assert(functionAttributes!(ref_property) == (FA.property | FA.ref_ | FA.system));
1664     static assert(functionAttributes!(typeof(&ref_property)) == (FA.property | FA.ref_ | FA.system));
1665 
1666     struct S2
1667     {
1668         int pure_const() const pure { return 0; }
1669         int pure_sharedconst() const shared pure { return 0; }
1670     }
1671 
1672     static assert(functionAttributes!(S2.pure_const) == (FA.const_ | FA.pure_ | FA.system));
1673     static assert(functionAttributes!(typeof(S2.pure_const)) == (FA.const_ | FA.pure_ | FA.system));
1674 
1675     static assert(functionAttributes!(S2.pure_sharedconst) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1676     static assert(functionAttributes!(typeof(S2.pure_sharedconst)) == (FA.const_ | FA.shared_ | FA.pure_ | FA.system));
1677 
1678     static assert(functionAttributes!((int a) { }) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1679     static assert(functionAttributes!(typeof((int a) { })) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1680 
1681     auto safeDel = delegate() @safe { };
1682     static assert(functionAttributes!(safeDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1683     static assert(functionAttributes!(typeof(safeDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.safe));
1684 
1685     auto trustedDel = delegate() @trusted { };
1686     static assert(functionAttributes!(trustedDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1687     static assert(functionAttributes!(typeof(trustedDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.trusted));
1688 
1689     auto systemDel = delegate() @system { };
1690     static assert(functionAttributes!(systemDel) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1691     static assert(functionAttributes!(typeof(systemDel)) == (FA.pure_ | FA.nothrow_ | FA.nogc | FA.system));
1692 }
1693 
1694 private FunctionAttribute extractAttribFlags(Attribs...)()
1695 {
1696     auto res = FunctionAttribute.none;
1697 
1698     static foreach (attrib; Attribs)
1699     {
1700         switch (attrib) with (FunctionAttribute)
1701         {
1702             case "pure":      res |= pure_; break;
1703             case "nothrow":   res |= nothrow_; break;
1704             case "ref":       res |= ref_; break;
1705             case "@property": res |= property; break;
1706             case "@trusted":  res |= trusted; break;
1707             case "@safe":     res |= safe; break;
1708             case "@nogc":     res |= nogc; break;
1709             case "@system":   res |= system; break;
1710             case "const":     res |= const_; break;
1711             case "immutable": res |= immutable_; break;
1712             case "inout":     res |= inout_; break;
1713             case "shared":    res |= shared_; break;
1714             case "return":    res |= return_; break;
1715             case "scope":     res |= scope_; break;
1716             case "@live":     res |= live; break;
1717             default: assert(0, attrib);
1718         }
1719     }
1720 
1721     return res;
1722 }
1723 
1724 /**
1725 Checks whether a function has the given attributes attached.
1726 
1727 Params:
1728     args = Function to check, followed by a
1729     variadic number of function attributes as strings
1730 
1731 Returns:
1732     `true`, if the function has the list of attributes attached and `false` otherwise.
1733 
1734 See_Also:
1735     $(LREF functionAttributes)
1736 */
1737 template hasFunctionAttributes(args...)
1738 if (args.length > 0 && isCallable!(args[0])
1739      && allSatisfy!(isSomeString, typeof(args[1 .. $])))
1740 {
1741     enum bool hasFunctionAttributes = {
1742         import std.algorithm.searching : canFind;
1743         import std.range : only;
1744         enum funcAttribs = only(__traits(getFunctionAttributes, args[0]));
1745         static foreach (attribute; args[1 .. $])
1746         {
1747             if (!funcAttribs.canFind(attribute))
1748                 return false;
1749         }
1750         return true;
1751     }();
1752 }
1753 
1754 ///
1755 @safe unittest
1756 {
1757     real func(real x) pure nothrow @safe;
1758     static assert(hasFunctionAttributes!(func, "@safe", "pure"));
1759     static assert(!hasFunctionAttributes!(func, "@trusted"));
1760 
1761     // for templates attributes are automatically inferred
1762     bool myFunc(T)(T b)
1763     {
1764         return !b;
1765     }
1766     static assert(hasFunctionAttributes!(myFunc!bool, "@safe", "pure", "@nogc", "nothrow"));
1767     static assert(!hasFunctionAttributes!(myFunc!bool, "shared"));
1768 }
1769 
1770 @system unittest
1771 {
1772     struct S
1773     {
1774         int noF();
1775         int constF() const;
1776         int immutableF() immutable;
1777         int inoutF() inout;
1778         int sharedF() shared;
1779 
1780         ref int refF() return;
1781         int propertyF() @property;
1782         int nothrowF() nothrow;
1783         int nogcF() @nogc;
1784 
1785         int systemF() @system;
1786         int trustedF() @trusted;
1787         int safeF() @safe;
1788 
1789         int pureF() pure;
1790 
1791         int liveF() @live;
1792     }
1793 
1794     // true if no args passed
1795     static assert(hasFunctionAttributes!(S.noF));
1796 
1797     static assert(hasFunctionAttributes!(S.noF, "@system"));
1798     static assert(hasFunctionAttributes!(typeof(S.noF), "@system"));
1799     static assert(!hasFunctionAttributes!(S.noF, "@system", "pure"));
1800 
1801     static assert(hasFunctionAttributes!(S.constF, "const", "@system"));
1802     static assert(hasFunctionAttributes!(typeof(S.constF), "const", "@system"));
1803     static assert(!hasFunctionAttributes!(S.constF, "const", "@system", "@nogc"));
1804 
1805     static assert(hasFunctionAttributes!(S.immutableF, "immutable", "@system"));
1806     static assert(hasFunctionAttributes!(typeof(S.immutableF), "immutable", "@system"));
1807     static assert(!hasFunctionAttributes!(S.immutableF, "immutable", "@system", "pure"));
1808 
1809     static assert(hasFunctionAttributes!(S.inoutF, "inout", "@system"));
1810     static assert(hasFunctionAttributes!(typeof(S.inoutF), "inout", "@system"));
1811     static assert(!hasFunctionAttributes!(S.inoutF, "inout", "@system", "pure"));
1812 
1813     static assert(hasFunctionAttributes!(S.sharedF, "shared", "@system"));
1814     static assert(hasFunctionAttributes!(typeof(S.sharedF), "shared", "@system"));
1815     static assert(!hasFunctionAttributes!(S.sharedF, "shared", "@system", "@trusted"));
1816 
1817     static assert(hasFunctionAttributes!(S.refF, "ref", "@system", "return"));
1818     static assert(hasFunctionAttributes!(typeof(S.refF), "ref", "@system", "return"));
1819     static assert(!hasFunctionAttributes!(S.refF, "ref", "@system", "return", "pure"));
1820 
1821     static assert(hasFunctionAttributes!(S.propertyF, "@property", "@system"));
1822     static assert(hasFunctionAttributes!(typeof(&S.propertyF), "@property", "@system"));
1823     static assert(!hasFunctionAttributes!(S.propertyF, "@property", "@system", "ref"));
1824 
1825     static assert(hasFunctionAttributes!(S.nothrowF, "nothrow", "@system"));
1826     static assert(hasFunctionAttributes!(typeof(S.nothrowF), "nothrow", "@system"));
1827     static assert(!hasFunctionAttributes!(S.nothrowF, "nothrow", "@system", "@trusted"));
1828 
1829     static assert(hasFunctionAttributes!(S.nogcF, "@nogc", "@system"));
1830     static assert(hasFunctionAttributes!(typeof(S.nogcF), "@nogc", "@system"));
1831     static assert(!hasFunctionAttributes!(S.nogcF, "@nogc", "@system", "ref"));
1832 
1833     static assert(hasFunctionAttributes!(S.systemF, "@system"));
1834     static assert(hasFunctionAttributes!(typeof(S.systemF), "@system"));
1835     static assert(!hasFunctionAttributes!(S.systemF, "@system", "ref"));
1836 
1837     static assert(hasFunctionAttributes!(S.trustedF, "@trusted"));
1838     static assert(hasFunctionAttributes!(typeof(S.trustedF), "@trusted"));
1839     static assert(!hasFunctionAttributes!(S.trustedF, "@trusted", "@safe"));
1840 
1841     static assert(hasFunctionAttributes!(S.safeF, "@safe"));
1842     static assert(hasFunctionAttributes!(typeof(S.safeF), "@safe"));
1843     static assert(!hasFunctionAttributes!(S.safeF, "@safe", "nothrow"));
1844 
1845     static assert(hasFunctionAttributes!(S.pureF, "pure", "@system"));
1846     static assert(hasFunctionAttributes!(typeof(S.pureF), "pure", "@system"));
1847     static assert(!hasFunctionAttributes!(S.pureF, "pure", "@system", "ref"));
1848 
1849     static assert(hasFunctionAttributes!(S.liveF, "@live", "@system"));
1850     static assert(hasFunctionAttributes!(typeof(S.liveF), "@live", "@system"));
1851     static assert(!hasFunctionAttributes!(S.liveF, "@live", "@system", "ref"));
1852 
1853     int pure_nothrow() nothrow pure { return 0; }
1854     void safe_nothrow() @safe nothrow { }
1855     static ref int static_ref_property() @property { return *(new int); }
1856     ref int ref_property() @property { return *(new int); }
1857 
1858     static assert(hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe"));
1859     static assert(hasFunctionAttributes!(typeof(pure_nothrow), "pure", "nothrow", "@safe"));
1860     static assert(!hasFunctionAttributes!(pure_nothrow, "pure", "nothrow", "@safe", "@trusted"));
1861 
1862     static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow"));
1863     static assert(hasFunctionAttributes!(typeof(safe_nothrow), "@safe", "nothrow"));
1864     static assert(hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure"));
1865     static assert(!hasFunctionAttributes!(safe_nothrow, "@safe", "nothrow", "pure", "@trusted"));
1866 
1867     static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe"));
1868     static assert(hasFunctionAttributes!(typeof(&static_ref_property), "@property", "ref", "@safe"));
1869     static assert(hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow"));
1870     static assert(!hasFunctionAttributes!(static_ref_property, "@property", "ref", "@safe", "nothrow", "@nogc"));
1871 
1872     static assert(hasFunctionAttributes!(ref_property, "@property", "ref", "@safe"));
1873     static assert(hasFunctionAttributes!(typeof(&ref_property), "@property", "ref", "@safe"));
1874     static assert(!hasFunctionAttributes!(ref_property, "@property", "ref", "@safe", "@nogc"));
1875 
1876     struct S2
1877     {
1878         int pure_const() const pure { return 0; }
1879         int pure_sharedconst() const shared pure { return 0; }
1880     }
1881 
1882     static assert(hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system"));
1883     static assert(hasFunctionAttributes!(typeof(S2.pure_const), "const", "pure", "@system"));
1884     static assert(!hasFunctionAttributes!(S2.pure_const, "const", "pure", "@system", "ref"));
1885 
1886     static assert(hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system"));
1887     static assert(hasFunctionAttributes!(typeof(S2.pure_sharedconst), "const", "shared", "pure", "@system"));
1888     static assert(!hasFunctionAttributes!(S2.pure_sharedconst, "const", "shared", "pure", "@system", "@nogc"));
1889 
1890     static assert(hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe"));
1891     static assert(hasFunctionAttributes!(typeof((int a) { }), "pure", "nothrow", "@nogc", "@safe"));
1892     static assert(!hasFunctionAttributes!((int a) { }, "pure", "nothrow", "@nogc", "@safe", "ref"));
1893 
1894     auto safeDel = delegate() @safe { };
1895     static assert(hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe"));
1896     static assert(hasFunctionAttributes!(typeof(safeDel), "pure", "nothrow", "@nogc", "@safe"));
1897     static assert(!hasFunctionAttributes!(safeDel, "pure", "nothrow", "@nogc", "@safe", "@system"));
1898 
1899     auto trustedDel = delegate() @trusted { };
1900     static assert(hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted"));
1901     static assert(hasFunctionAttributes!(typeof(trustedDel), "pure", "nothrow", "@nogc", "@trusted"));
1902     static assert(!hasFunctionAttributes!(trustedDel, "pure", "nothrow", "@nogc", "@trusted", "ref"));
1903 
1904     auto systemDel = delegate() @system { };
1905     static assert(hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system"));
1906     static assert(hasFunctionAttributes!(typeof(systemDel), "pure", "nothrow", "@nogc", "@system"));
1907     static assert(!hasFunctionAttributes!(systemDel, "pure", "nothrow", "@nogc", "@system", "@property"));
1908 
1909 
1910     // call functions to make CodeCov happy
1911     {
1912         assert(pure_nothrow == 0);
1913         safe_nothrow;
1914         assert(static_ref_property == 0);
1915         assert(ref_property == 0);
1916         assert(S2().pure_const == 0);
1917         assert((shared S2()).pure_sharedconst == 0);
1918         cast(void) safeDel;
1919         cast(void) trustedDel;
1920         cast(void) systemDel;
1921     }
1922 }
1923 
1924 /**
1925 `true` if `func` is `@safe` or `@trusted`.
1926  */
1927 template isSafe(alias func)
1928 if (isCallable!func)
1929 {
1930     enum isSafe = (functionAttributes!func & FunctionAttribute.safe) != 0 ||
1931                   (functionAttributes!func & FunctionAttribute.trusted) != 0;
1932 }
1933 
1934 ///
1935 @safe unittest
1936 {
1937     @safe    int add(int a, int b) {return a+b;}
1938     @trusted int sub(int a, int b) {return a-b;}
1939     @system  int mul(int a, int b) {return a*b;}
1940 
1941     static assert( isSafe!add);
1942     static assert( isSafe!sub);
1943     static assert(!isSafe!mul);
1944 }
1945 
1946 
1947 @safe unittest
1948 {
1949     //Member functions
1950     interface Set
1951     {
1952         int systemF() @system;
1953         int trustedF() @trusted;
1954         int safeF() @safe;
1955     }
1956     static assert( isSafe!(Set.safeF));
1957     static assert( isSafe!(Set.trustedF));
1958     static assert(!isSafe!(Set.systemF));
1959 
1960     //Functions
1961     @safe static void safeFunc() {}
1962     @trusted static void trustedFunc() {}
1963     @system static void systemFunc() {}
1964 
1965     static assert( isSafe!safeFunc);
1966     static assert( isSafe!trustedFunc);
1967     static assert(!isSafe!systemFunc);
1968 
1969     //Delegates
1970     auto safeDel = delegate() @safe {};
1971     auto trustedDel = delegate() @trusted {};
1972     auto systemDel = delegate() @system {};
1973 
1974     static assert( isSafe!safeDel);
1975     static assert( isSafe!trustedDel);
1976     static assert(!isSafe!systemDel);
1977 
1978     //Lambdas
1979     static assert( isSafe!({safeDel();}));
1980     static assert( isSafe!({trustedDel();}));
1981     static assert(!isSafe!({systemDel();}));
1982 
1983     //Static opCall
1984     struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
1985     struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
1986     struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
1987 
1988     static assert( isSafe!(SafeStatic()));
1989     static assert( isSafe!(TrustedStatic()));
1990     static assert(!isSafe!(SystemStatic()));
1991 
1992     //Non-static opCall
1993     struct Safe { @safe Safe opCall() { return Safe.init; } }
1994     struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
1995     struct System { @system System opCall() { return System.init; } }
1996 
1997     static assert( isSafe!(Safe.init()));
1998     static assert( isSafe!(Trusted.init()));
1999     static assert(!isSafe!(System.init()));
2000 }
2001 
2002 
2003 /**
2004 `true` if `func` is `@system`.
2005 */
2006 template isUnsafe(alias func)
2007 {
2008     enum isUnsafe = !isSafe!func;
2009 }
2010 
2011 ///
2012 @safe unittest
2013 {
2014     @safe    int add(int a, int b) {return a+b;}
2015     @trusted int sub(int a, int b) {return a-b;}
2016     @system  int mul(int a, int b) {return a*b;}
2017 
2018     static assert(!isUnsafe!add);
2019     static assert(!isUnsafe!sub);
2020     static assert( isUnsafe!mul);
2021 }
2022 
2023 @safe unittest
2024 {
2025     //Member functions
2026     interface Set
2027     {
2028         int systemF() @system;
2029         int trustedF() @trusted;
2030         int safeF() @safe;
2031     }
2032     static assert(!isUnsafe!(Set.safeF));
2033     static assert(!isUnsafe!(Set.trustedF));
2034     static assert( isUnsafe!(Set.systemF));
2035 
2036     //Functions
2037     @safe static void safeFunc() {}
2038     @trusted static void trustedFunc() {}
2039     @system static void systemFunc() {}
2040 
2041     static assert(!isUnsafe!safeFunc);
2042     static assert(!isUnsafe!trustedFunc);
2043     static assert( isUnsafe!systemFunc);
2044 
2045     //Delegates
2046     auto safeDel = delegate() @safe {};
2047     auto trustedDel = delegate() @trusted {};
2048     auto systemDel = delegate() @system {};
2049 
2050     static assert(!isUnsafe!safeDel);
2051     static assert(!isUnsafe!trustedDel);
2052     static assert( isUnsafe!systemDel);
2053 
2054     //Lambdas
2055     static assert(!isUnsafe!({safeDel();}));
2056     static assert(!isUnsafe!({trustedDel();}));
2057     static assert( isUnsafe!({systemDel();}));
2058 
2059     //Static opCall
2060     struct SafeStatic { @safe static SafeStatic opCall() { return SafeStatic.init; } }
2061     struct TrustedStatic { @trusted static TrustedStatic opCall() { return TrustedStatic.init; } }
2062     struct SystemStatic { @system static SystemStatic opCall() { return SystemStatic.init; } }
2063 
2064     static assert(!isUnsafe!(SafeStatic()));
2065     static assert(!isUnsafe!(TrustedStatic()));
2066     static assert( isUnsafe!(SystemStatic()));
2067 
2068     //Non-static opCall
2069     struct Safe { @safe Safe opCall() { return Safe.init; } }
2070     struct Trusted { @trusted Trusted opCall() { return Trusted.init; } }
2071     struct System { @system System opCall() { return System.init; } }
2072 
2073     static assert(!isUnsafe!(Safe.init()));
2074     static assert(!isUnsafe!(Trusted.init()));
2075     static assert( isUnsafe!(System.init()));
2076 }
2077 
2078 
2079 /**
2080 Determine the linkage attribute of the function.
2081 Params:
2082     func = the function symbol, or the type of a function, delegate, or pointer to function
2083 Returns:
2084     one of the strings "D", "C", "C++", "Windows", "Objective-C", or "System".
2085 */
2086 template functionLinkage(alias func)
2087 if (isCallable!func)
2088 {
2089     enum string functionLinkage = __traits(getLinkage, FunctionTypeOf!func);
2090 }
2091 
2092 ///
2093 @safe unittest
2094 {
2095     extern(D) void Dfunc() {}
2096     extern(C) void Cfunc() {}
2097     static assert(functionLinkage!Dfunc == "D");
2098     static assert(functionLinkage!Cfunc == "C");
2099 
2100     string a = functionLinkage!Dfunc;
2101     assert(a == "D");
2102 
2103     auto fp = &Cfunc;
2104     string b = functionLinkage!fp;
2105     assert(b == "C");
2106 }
2107 
2108 @safe unittest
2109 {
2110     interface Test
2111     {
2112         void const_func() const;
2113         void sharedconst_func() shared const;
2114     }
2115     static assert(functionLinkage!(Test.const_func) == "D");
2116     static assert(functionLinkage!(Test.sharedconst_func) == "D");
2117 
2118     static assert(functionLinkage!((int a){}) == "D");
2119 }
2120 
2121 
2122 /**
2123 Determines what kind of variadic parameters function has.
2124 Params:
2125     func = function symbol or type of function, delegate, or pointer to function
2126 Returns:
2127     enum Variadic
2128  */
2129 enum Variadic
2130 {
2131     /// Function is not variadic.
2132     no,
2133     /// Function is a _C-style variadic function, which uses
2134     /// `core.stdc.stdarg`
2135     c,
2136     /// Function is a _D-style variadic function, which uses
2137     /// `__argptr` and `__arguments`.
2138     d,
2139     /// Function is a typesafe variadic function.
2140     typesafe,
2141 }
2142 
2143 /// ditto
2144 template variadicFunctionStyle(alias func)
2145 if (isCallable!func)
2146 {
2147     enum string varargs = __traits(getFunctionVariadicStyle, FunctionTypeOf!func);
2148     enum Variadic variadicFunctionStyle =
2149         (varargs == "stdarg") ? Variadic.c :
2150         (varargs == "argptr") ? Variadic.d :
2151         (varargs == "typesafe") ? Variadic.typesafe :
2152         (varargs == "none") ? Variadic.no : Variadic.no;
2153 }
2154 
2155 ///
2156 @safe unittest
2157 {
2158     void func() {}
2159     static assert(variadicFunctionStyle!func == Variadic.no);
2160 
2161     extern(C) int printf(const char*, ...);
2162     static assert(variadicFunctionStyle!printf == Variadic.c);
2163 }
2164 
2165 @safe unittest
2166 {
2167     import core.vararg;
2168 
2169     extern(D) void novar() {}
2170     extern(C) void cstyle(int, ...) {}
2171     extern(D) void dstyle(...) {}
2172     extern(D) void typesafe(int[]...) {}
2173 
2174     static assert(variadicFunctionStyle!novar == Variadic.no);
2175     static assert(variadicFunctionStyle!cstyle == Variadic.c);
2176     static assert(variadicFunctionStyle!dstyle == Variadic.d);
2177     static assert(variadicFunctionStyle!typesafe == Variadic.typesafe);
2178 
2179     static assert(variadicFunctionStyle!((int[] a...) {}) == Variadic.typesafe);
2180 }
2181 
2182 
2183 /**
2184 Get the function type from a callable object `func`.
2185 
2186 Using builtin `typeof` on a property function yields the types of the
2187 property value, not of the property function itself.  Still,
2188 `FunctionTypeOf` is able to obtain function types of properties.
2189 
2190 Note:
2191 Do not confuse function types with function pointer types; function types are
2192 usually used for compile-time reflection purposes.
2193  */
2194 template FunctionTypeOf(alias func)
2195 if (isCallable!func)
2196 {
2197     static if ((is(typeof(& func) Fsym : Fsym*) && is(Fsym == function)) || is(typeof(& func) Fsym == delegate))
2198     {
2199         alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol
2200     }
2201     else static if (is(typeof(& func.opCall) Fobj == delegate) || is(typeof(& func.opCall!()) Fobj == delegate))
2202     {
2203         alias FunctionTypeOf = Fobj; // HIT: callable object
2204     }
2205     else static if (
2206             (is(typeof(& func.opCall) Ftyp : Ftyp*) && is(Ftyp == function)) ||
2207             (is(typeof(& func.opCall!()) Ftyp : Ftyp*) && is(Ftyp == function))
2208         )
2209     {
2210         alias FunctionTypeOf = Ftyp; // HIT: callable type
2211     }
2212     else static if (is(func T) || is(typeof(func) T))
2213     {
2214         static if (is(T == function))
2215             alias FunctionTypeOf = T;    // HIT: function
2216         else static if (is(T Fptr : Fptr*) && is(Fptr == function))
2217             alias FunctionTypeOf = Fptr; // HIT: function pointer
2218         else static if (is(T Fdlg == delegate))
2219             alias FunctionTypeOf = Fdlg; // HIT: delegate
2220         else
2221             static assert(0);
2222     }
2223     else
2224         static assert(0);
2225 }
2226 
2227 ///
2228 @safe unittest
2229 {
2230     class C
2231     {
2232         int value() @property { return 0; }
2233     }
2234     static assert(is( typeof(C.value) == int ));
2235     static assert(is( FunctionTypeOf!(C.value) == function ));
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(T : Base!Args, alias Base, Args...) = Base;
4725 
4726 /// ditto
4727 alias TemplateOf(T) = void;
4728 
4729 ///
4730 @safe unittest
4731 {
4732     struct Foo(T, U) {}
4733     static assert(__traits(isSame, TemplateOf!(Foo!(int, real)), Foo));
4734 }
4735 
4736 @safe unittest
4737 {
4738     template Foo1(A) {}
4739     template Foo2(A, B) {}
4740     template Foo3(alias A) {}
4741     template Foo4(string A) {}
4742     struct Foo5(A) {}
4743     struct Foo6(A, B) {}
4744     struct Foo7(alias A) {}
4745     template Foo8(A) { template Foo9(B) {} }
4746     template Foo10() {}
4747 
4748     static assert(__traits(isSame, TemplateOf!(Foo1!(int)), Foo1));
4749     static assert(__traits(isSame, TemplateOf!(Foo2!(int, int)), Foo2));
4750     static assert(__traits(isSame, TemplateOf!(Foo3!(123)), Foo3));
4751     static assert(__traits(isSame, TemplateOf!(Foo4!("123")), Foo4));
4752     static assert(__traits(isSame, TemplateOf!(Foo5!(int)), Foo5));
4753     static assert(__traits(isSame, TemplateOf!(Foo6!(int, int)), Foo6));
4754     static assert(__traits(isSame, TemplateOf!(Foo7!(123)), Foo7));
4755     static assert(__traits(isSame, TemplateOf!(Foo8!(int).Foo9!(real)), Foo8!(int).Foo9));
4756     static assert(__traits(isSame, TemplateOf!(Foo10!()), Foo10));
4757 }
4758 
4759 // https://issues.dlang.org/show_bug.cgi?id=18214
4760 @safe unittest
4761 {
4762     static assert(is(TemplateOf!(int[]) == void));
4763     static assert(is(TemplateOf!bool == void));
4764 }
4765 
4766 /**
4767 Returns a `AliasSeq` of the template arguments used to instantiate `T`.
4768  */
4769 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
4770 
4771 /// ditto
4772 alias TemplateArgsOf(T : Base!Args, alias Base, Args...) = Args;
4773 
4774 ///
4775 @safe unittest
4776 {
4777     import std.meta : AliasSeq;
4778 
4779     struct Foo(T, U) {}
4780     static assert(is(TemplateArgsOf!(Foo!(int, real)) == AliasSeq!(int, real)));
4781 }
4782 
4783 @safe unittest
4784 {
4785     template Foo1(A) {}
4786     template Foo2(A, B) {}
4787     template Foo3(alias A) {}
4788     template Foo4(string A) {}
4789     struct Foo5(A) {}
4790     struct Foo6(A, B) {}
4791     struct Foo7(alias A) {}
4792     template Foo8(A) { template Foo9(B) {} }
4793     template Foo10() {}
4794 
4795     enum x = 123;
4796     enum y = "123";
4797     static assert(is(TemplateArgsOf!(Foo1!(int)) == AliasSeq!(int)));
4798     static assert(is(TemplateArgsOf!(Foo2!(int, int)) == AliasSeq!(int, int)));
4799     static assert(__traits(isSame, TemplateArgsOf!(Foo3!(x)), AliasSeq!(x)));
4800     static assert(TemplateArgsOf!(Foo4!(y)) == AliasSeq!(y));
4801     static assert(is(TemplateArgsOf!(Foo5!(int)) == AliasSeq!(int)));
4802     static assert(is(TemplateArgsOf!(Foo6!(int, int)) == AliasSeq!(int, int)));
4803     static assert(__traits(isSame, TemplateArgsOf!(Foo7!(x)), AliasSeq!(x)));
4804     static assert(is(TemplateArgsOf!(Foo8!(int).Foo9!(real)) == AliasSeq!(real)));
4805     static assert(is(TemplateArgsOf!(Foo10!()) == AliasSeq!()));
4806 }
4807 
4808 // Returns the largest alignment in a type tuple.
4809 package enum maxAlignment(U...) =
4810 {
4811     size_t result = U[0].alignof;
4812     static foreach (T; U[1 .. $])
4813         if (result < T.alignof)
4814             result = T.alignof;
4815     return result;
4816 }();
4817 
4818 /**
4819 Returns class instance alignment.
4820 
4821 See also: $(DDSUBLINK spec/traits, classInstanceAlignment, `__traits(classInstanceAlignment, T)`)
4822  */
4823 template classInstanceAlignment(T)
4824 if (is(T == class))
4825 {
4826     enum classInstanceAlignment = __traits(classInstanceAlignment, T);
4827 }
4828 
4829 ///
4830 @safe unittest
4831 {
4832     class A { byte b; }
4833     class B { long l; }
4834 
4835     // As class instance always has a hidden pointer
4836     static assert(classInstanceAlignment!A == (void*).alignof);
4837     static assert(classInstanceAlignment!B == long.alignof);
4838 }
4839 
4840 
4841 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4842 // Type Conversion
4843 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
4844 
4845 /**
4846 Get the type that all types can be implicitly converted to. Useful
4847 e.g. in figuring out an array type from a bunch of initializing
4848 values. Returns $(D_PARAM void) if passed an empty list, or if the
4849 types have no common type.
4850  */
4851 template CommonType(T...)
4852 {
4853     static if (T.length == 1)
4854         alias CommonType = typeof(T[0].init);
4855     else static if (is(typeof(true ? T[0].init : T[1].init) U))
4856         alias CommonType = CommonType!(U, T[2 .. $]);
4857     else
4858         alias CommonType = void;
4859 }
4860 
4861 ///
4862 @safe unittest
4863 {
4864     alias X = CommonType!(int, long, short);
4865     assert(is(X == long));
4866     alias Y = CommonType!(int, char[], short);
4867     assert(is(Y == void));
4868 }
4869 
4870 ///
4871 @safe unittest
4872 {
4873     static assert(is(CommonType!(3) == int));
4874     static assert(is(CommonType!(double, 4, float) == double));
4875     static assert(is(CommonType!(string, char[]) == const(char)[]));
4876     static assert(is(CommonType!(3, 3U) == uint));
4877     static assert(is(CommonType!(double, int) == double));
4878 }
4879 
4880 
4881 /**
4882 Params:
4883     T = The type to check
4884 
4885 Returns:
4886     An $(REF AliasSeq,std,meta) with all possible target types of an implicit
4887     conversion `T`.
4888 
4889     If `T` is a class derived from `Object`, the result of
4890     $(LREF TransitiveBaseTypeTuple) is returned.
4891 
4892     If the type is not a built-in value type or a class derived from
4893     `Object`, an empty $(REF AliasSeq,std,meta) is returned.
4894 
4895 See_Also:
4896     $(LREF isImplicitlyConvertible)
4897  */
4898 template AllImplicitConversionTargets(T)
4899 {
4900     static if (is(T == bool))
4901         alias AllImplicitConversionTargets =
4902             AliasSeq!(byte, AllImplicitConversionTargets!byte);
4903     else static if (is(T == byte))
4904         alias AllImplicitConversionTargets =
4905             AliasSeq!(char, ubyte, short, AllImplicitConversionTargets!short);
4906     else static if (is(T == ubyte))
4907         alias AllImplicitConversionTargets =
4908             AliasSeq!(byte, char, short, AllImplicitConversionTargets!short);
4909     else static if (is(T == short))
4910         alias AllImplicitConversionTargets =
4911             AliasSeq!(ushort, wchar, int, AllImplicitConversionTargets!int);
4912     else static if (is(T == ushort))
4913         alias AllImplicitConversionTargets =
4914             AliasSeq!(short, wchar, dchar, AllImplicitConversionTargets!dchar);
4915     else static if (is(T == int))
4916         alias AllImplicitConversionTargets =
4917             AliasSeq!(dchar, uint, long, AllImplicitConversionTargets!long);
4918     else static if (is(T == uint))
4919         alias AllImplicitConversionTargets =
4920             AliasSeq!(dchar, int, long, AllImplicitConversionTargets!long);
4921     else static if (is(T == long))
4922         alias AllImplicitConversionTargets = AliasSeq!(ulong, CentTypeList, float, double, real);
4923     else static if (is(T == ulong))
4924         alias AllImplicitConversionTargets = AliasSeq!(long, CentTypeList, float, double, real);
4925     else static if (is(T == float))
4926         alias AllImplicitConversionTargets = AliasSeq!(double, real);
4927     else static if (is(T == double))
4928         alias AllImplicitConversionTargets = AliasSeq!(float, real);
4929     else static if (is(T == real))
4930         alias AllImplicitConversionTargets = AliasSeq!(float, double);
4931     else static if (is(T == char))
4932         alias AllImplicitConversionTargets =
4933             AliasSeq!(byte, ubyte, short, AllImplicitConversionTargets!short);
4934     else static if (is(T == wchar))
4935         alias AllImplicitConversionTargets =
4936             AliasSeq!(short, ushort, dchar, AllImplicitConversionTargets!dchar);
4937     else static if (is(T == dchar))
4938         alias AllImplicitConversionTargets =
4939             AliasSeq!(int, uint, long, AllImplicitConversionTargets!long);
4940     else static if (is(T == class))
4941         alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!T);
4942     else static if (is(T == interface))
4943         alias AllImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), InterfacesTuple!T);
4944     else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
4945     {
4946        static if (is(typeof(T.init[0]) == shared))
4947            alias AllImplicitConversionTargets =
4948            AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
4949        else
4950            alias AllImplicitConversionTargets =
4951            AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
4952     }
4953     else static if (is(T : void*) && !is(T == void*))
4954         alias AllImplicitConversionTargets = AliasSeq!(void*);
4955     else static if (is(cent) && is(T == cent))
4956         alias AllImplicitConversionTargets = AliasSeq!(UnsignedCentTypeList, float, double, real);
4957     else static if (is(ucent) && is(T == ucent))
4958         alias AllImplicitConversionTargets = AliasSeq!(SignedCentTypeList, float, double, real);
4959     else
4960         alias AllImplicitConversionTargets = AliasSeq!();
4961 }
4962 
4963 ///
4964 @safe unittest
4965 {
4966     import std.meta : AliasSeq;
4967 
4968     static assert(is(AllImplicitConversionTargets!(ulong) == AliasSeq!(long, float, double, real)));
4969     static assert(is(AllImplicitConversionTargets!(int) == AliasSeq!(dchar, uint, long, ulong, float, double, real)));
4970     static assert(is(AllImplicitConversionTargets!(float) == AliasSeq!(double, real)));
4971     static assert(is(AllImplicitConversionTargets!(double) == AliasSeq!(float, real)));
4972 
4973     static assert(is(AllImplicitConversionTargets!(char) ==
4974         AliasSeq!(byte, ubyte, short, ushort, wchar, int, dchar, uint, long,
4975             ulong, float, double, real)
4976     ));
4977     static assert(is(AllImplicitConversionTargets!(wchar) == AliasSeq!(
4978         short, ushort, dchar, int, uint, long, ulong, float, double, real
4979     )));
4980     static assert(is(AllImplicitConversionTargets!(dchar) == AliasSeq!(
4981         int, uint, long, ulong, float, double, real
4982     )));
4983 
4984     static assert(is(AllImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
4985     static assert(is(AllImplicitConversionTargets!(int*) == AliasSeq!(void*)));
4986 
4987     interface A {}
4988     interface B {}
4989     class C : A, B {}
4990 
4991     static assert(is(AllImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
4992     static assert(is(AllImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
4993     static assert(is(AllImplicitConversionTargets!(immutable C) == AliasSeq!(
4994         immutable Object, immutable A, immutable B
4995     )));
4996 
4997     interface I : A, B {}
4998 
4999     static assert(is(AllImplicitConversionTargets!(I) == AliasSeq!(A, B)));
5000     static assert(is(AllImplicitConversionTargets!(const I) == AliasSeq!(const A, const B)));
5001     static assert(is(AllImplicitConversionTargets!(immutable I) == AliasSeq!(
5002         immutable A, immutable B
5003     )));
5004 }
5005 
5006 @safe unittest
5007 {
5008     static assert(is(AllImplicitConversionTargets!(double)[0] == float));
5009     static assert(is(AllImplicitConversionTargets!(double)[1] == real));
5010     static assert(is(AllImplicitConversionTargets!(string)[0] == const(char)[]));
5011 }
5012 
5013 
5014 /**
5015 Params:
5016     T = The type to check
5017 
5018 Warning:
5019     This template is considered out-dated. It will be removed from
5020     Phobos in 2.107.0. Please use $(LREF AllImplicitConversionTargets) instead.
5021 
5022 Returns:
5023     An $(REF AliasSeq,std,meta) with all possible target types of an implicit
5024     conversion `T`.
5025 
5026     If `T` is a class derived from `Object`, the result of
5027     $(LREF TransitiveBaseTypeTuple) is returned.
5028 
5029     If the type is not a built-in value type or a class derived from
5030     `Object`, an empty $(REF AliasSeq,std,meta) is returned.
5031 
5032 Note:
5033     The possible targets are computed more conservatively than the
5034     language allows, eliminating all dangerous conversions. For example,
5035     `ImplicitConversionTargets!double` does not include `float`.
5036 
5037 See_Also:
5038     $(LREF isImplicitlyConvertible)
5039  */
5040 // @@@DEPRECATED_[2.107.0]@@@
5041 deprecated("ImplicitConversionTargets has been deprecated in favour of AllImplicitConversionTargets "
5042    ~ "and will be removed in 2.107.0")
5043 template ImplicitConversionTargets(T)
5044 {
5045     static if (is(T == bool))
5046         alias ImplicitConversionTargets =
5047             AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, CentTypeList,
5048                        float, double, real, char, wchar, dchar);
5049     else static if (is(T == byte))
5050         alias ImplicitConversionTargets =
5051             AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5052                        float, double, real, char, wchar, dchar);
5053     else static if (is(T == ubyte))
5054         alias ImplicitConversionTargets =
5055             AliasSeq!(short, ushort, int, uint, long, ulong, CentTypeList,
5056                        float, double, real, char, wchar, dchar);
5057     else static if (is(T == short))
5058         alias ImplicitConversionTargets =
5059             AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5060     else static if (is(T == ushort))
5061         alias ImplicitConversionTargets =
5062             AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5063     else static if (is(T == int))
5064         alias ImplicitConversionTargets =
5065             AliasSeq!(long, ulong, CentTypeList, float, double, real);
5066     else static if (is(T == uint))
5067         alias ImplicitConversionTargets =
5068             AliasSeq!(long, ulong, CentTypeList, float, double, real);
5069     else static if (is(T == long))
5070         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5071     else static if (is(T == ulong))
5072         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5073     else static if (is(cent) && is(T == cent))
5074         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5075     else static if (is(ucent) && is(T == ucent))
5076         alias ImplicitConversionTargets = AliasSeq!(float, double, real);
5077     else static if (is(T == float))
5078         alias ImplicitConversionTargets = AliasSeq!(double, real);
5079     else static if (is(T == double))
5080         alias ImplicitConversionTargets = AliasSeq!real;
5081     else static if (is(T == char))
5082         alias ImplicitConversionTargets =
5083             AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
5084                        int, uint, long, ulong, CentTypeList, float, double, real);
5085     else static if (is(T == wchar))
5086         alias ImplicitConversionTargets =
5087             AliasSeq!(dchar, short, ushort, int, uint, long, ulong, CentTypeList,
5088                        float, double, real);
5089     else static if (is(T == dchar))
5090         alias ImplicitConversionTargets =
5091             AliasSeq!(int, uint, long, ulong, CentTypeList, float, double, real);
5092     else static if (is(T : typeof(null)))
5093         alias ImplicitConversionTargets = AliasSeq!(typeof(null));
5094     else static if (is(T == class))
5095         alias ImplicitConversionTargets = staticMap!(ApplyLeft!(CopyConstness, T), TransitiveBaseTypeTuple!(T));
5096     else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
5097     {
5098        static if (is(typeof(T.init[0]) == shared))
5099            alias ImplicitConversionTargets =
5100            AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
5101        else
5102            alias ImplicitConversionTargets =
5103            AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
5104     }
5105     else static if (is(T : void*))
5106         alias ImplicitConversionTargets = AliasSeq!(void*);
5107     else
5108         alias ImplicitConversionTargets = AliasSeq!();
5109 }
5110 
5111 deprecated @safe unittest
5112 {
5113     import std.meta : AliasSeq;
5114 
5115     static assert(is(ImplicitConversionTargets!(ulong) == AliasSeq!(float, double, real)));
5116     static assert(is(ImplicitConversionTargets!(int) == AliasSeq!(long, ulong, float, double, real)));
5117     static assert(is(ImplicitConversionTargets!(float) == AliasSeq!(double, real)));
5118     static assert(is(ImplicitConversionTargets!(double) == AliasSeq!(real)));
5119 
5120     static assert(is(ImplicitConversionTargets!(char) == AliasSeq!(
5121         wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real
5122     )));
5123     static assert(is(ImplicitConversionTargets!(wchar) == AliasSeq!(
5124         dchar, short, ushort, int, uint, long, ulong, float, double, real
5125     )));
5126     static assert(is(ImplicitConversionTargets!(dchar) == AliasSeq!(
5127         int, uint, long, ulong, float, double, real
5128     )));
5129 
5130     static assert(is(ImplicitConversionTargets!(string) == AliasSeq!(const(char)[])));
5131     static assert(is(ImplicitConversionTargets!(void*) == AliasSeq!(void*)));
5132 
5133     interface A {}
5134     interface B {}
5135     class C : A, B {}
5136 
5137     static assert(is(ImplicitConversionTargets!(C) == AliasSeq!(Object, A, B)));
5138     static assert(is(ImplicitConversionTargets!(const C) == AliasSeq!(const Object, const A, const B)));
5139     static assert(is(ImplicitConversionTargets!(immutable C) == AliasSeq!(
5140         immutable Object, immutable A, immutable B
5141     )));
5142 }
5143 
5144 deprecated @safe unittest
5145 {
5146     static assert(is(ImplicitConversionTargets!(double)[0] == real));
5147     static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[]));
5148 }
5149 
5150 /**
5151 Is `From` implicitly convertible to `To`?
5152  */
5153 enum bool isImplicitlyConvertible(From, To) = is(From : To);
5154 
5155 ///
5156 @safe unittest
5157 {
5158     static assert( isImplicitlyConvertible!(immutable(char), char));
5159     static assert( isImplicitlyConvertible!(const(char), char));
5160     static assert( isImplicitlyConvertible!(char, wchar));
5161     static assert(!isImplicitlyConvertible!(wchar, char));
5162 
5163     static assert(!isImplicitlyConvertible!(const(ushort), ubyte));
5164     static assert(!isImplicitlyConvertible!(const(uint), ubyte));
5165     static assert(!isImplicitlyConvertible!(const(ulong), ubyte));
5166 
5167     static assert(!isImplicitlyConvertible!(const(char)[], string));
5168     static assert( isImplicitlyConvertible!(string, const(char)[]));
5169 }
5170 
5171 /**
5172 Is `From` $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible) to `To`?
5173 */
5174 enum bool isQualifierConvertible(From, To) =
5175     is(immutable From == immutable To) && is(From* : To*);
5176 
5177 ///
5178 @safe unittest
5179 {
5180     // Mutable and immmutable both convert to const...
5181     static assert( isQualifierConvertible!(char, const(char)));
5182     static assert( isQualifierConvertible!(immutable(char), const(char)));
5183     // ...but const does not convert back to mutable or immutable
5184     static assert(!isQualifierConvertible!(const(char), char));
5185     static assert(!isQualifierConvertible!(const(char), immutable(char)));
5186 }
5187 
5188 @safe unittest
5189 {
5190     import std.meta : AliasSeq;
5191 
5192     alias Ts = AliasSeq!(int, const int, shared int, inout int, const shared int,
5193         const inout int, inout shared int, const inout shared int, immutable int);
5194 
5195     // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
5196     enum _ = 0;
5197     static immutable bool[Ts.length][Ts.length] conversions = [
5198     //   m   c   s   i   cs  ci  is  cis im
5199         [1,  1,  _,  _,  _,  _,  _,  _,  _],  // mutable
5200         [_,  1,  _,  _,  _,  _,  _,  _,  _],  // const
5201         [_,  _,  1,  _,  1,  _,  _,  _,  _],  // shared
5202         [_,  1,  _,  1,  _,  1,  _,  _,  _],  // inout
5203         [_,  _,  _,  _,  1,  _,  _,  _,  _],  // const shared
5204         [_,  1,  _,  _,  _,  1,  _,  _,  _],  // const inout
5205         [_,  _,  _,  _,  1,  _,  1,  1,  _],  // inout shared
5206         [_,  _,  _,  _,  1,  _,  _,  1,  _],  // const inout shared
5207         [_,  1,  _,  _,  1,  1,  _,  1,  1],  // immutable
5208     ];
5209 
5210     static foreach (i, From; Ts)
5211     {
5212         static foreach (j, To; Ts)
5213         {
5214             static assert(isQualifierConvertible!(From, To) == conversions[i][j],
5215                 "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`"
5216                 ~ " should be `" ~ (conversions[i][j] ? "true" : "false") ~ "`");
5217         }
5218     }
5219 }
5220 
5221 @safe unittest
5222 {
5223     // int* -> void* is not a qualifier conversion
5224     static assert(!isQualifierConvertible!(int, void));
5225 }
5226 
5227 /**
5228 Returns `true` iff a value of type `Rhs` can be assigned to a variable of
5229 type `Lhs`.
5230 
5231 `isAssignable` returns whether both an lvalue and rvalue can be assigned.
5232 
5233 If you omit `Rhs`, `isAssignable` will check identity assignable of `Lhs`.
5234 */
5235 enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs);
5236 
5237 ///
5238 @safe unittest
5239 {
5240     static assert( isAssignable!(long, int));
5241     static assert(!isAssignable!(int, long));
5242     static assert( isAssignable!(const(char)[], string));
5243     static assert(!isAssignable!(string, char[]));
5244 
5245     // int is assignable to int
5246     static assert( isAssignable!int);
5247 
5248     // immutable int is not assignable to immutable int
5249     static assert(!isAssignable!(immutable int));
5250 }
5251 
5252 /**
5253 Returns `true` iff an rvalue of type `Rhs` can be assigned to a variable of
5254 type `Lhs`.
5255 */
5256 enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = rvalueOf!Rhs; });
5257 
5258 ///
5259 @safe unittest
5260 {
5261     struct S1
5262     {
5263         void opAssign(S1);
5264     }
5265 
5266     struct S2
5267     {
5268         void opAssign(ref S2);
5269     }
5270 
5271     static assert( isRvalueAssignable!(long, int));
5272     static assert(!isRvalueAssignable!(int, long));
5273     static assert( isRvalueAssignable!S1);
5274     static assert(!isRvalueAssignable!S2);
5275 }
5276 
5277 /**
5278 Returns `true` iff an lvalue of type `Rhs` can be assigned to a variable of
5279 type `Lhs`.
5280 */
5281 enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lvalueOf!Rhs; });
5282 
5283 ///
5284 @safe unittest
5285 {
5286     struct S1
5287     {
5288         void opAssign(S1);
5289     }
5290 
5291     struct S2
5292     {
5293         void opAssign(ref S2);
5294     }
5295 
5296     static assert( isLvalueAssignable!(long, int));
5297     static assert(!isLvalueAssignable!(int, long));
5298     static assert( isLvalueAssignable!S1);
5299     static assert( isLvalueAssignable!S2);
5300 }
5301 
5302 @safe unittest
5303 {
5304     static assert(!isAssignable!(immutable int, int));
5305     static assert( isAssignable!(int, immutable int));
5306 
5307     static assert(!isAssignable!(inout int, int));
5308     static assert( isAssignable!(int, inout int));
5309     static assert(!isAssignable!(inout int));
5310 
5311     static assert( isAssignable!(shared int, int));
5312     static assert( isAssignable!(int, shared int));
5313     static assert( isAssignable!(shared int));
5314 
5315     static assert( isAssignable!(void[1], void[1]));
5316 
5317     struct S { @disable this(); this(int n){} }
5318     static assert( isAssignable!(S, S));
5319 
5320     struct S2 { this(int n){} }
5321     static assert( isAssignable!(S2, S2));
5322     static assert(!isAssignable!(S2, int));
5323 
5324     struct S3 { @disable void opAssign(); }
5325     static assert( isAssignable!(S3, S3));
5326 
5327     struct S3X { @disable void opAssign(S3X); }
5328     static assert(!isAssignable!(S3X, S3X));
5329 
5330     struct S4 { void opAssign(int); }
5331     static assert( isAssignable!(S4, S4));
5332     static assert( isAssignable!(S4, int));
5333     static assert( isAssignable!(S4, immutable int));
5334 
5335     struct S5 { @disable this(); @disable this(this); }
5336     // https://issues.dlang.org/show_bug.cgi?id=21210
5337     static assert(!isAssignable!S5);
5338 
5339     // `-preview=in` is enabled
5340     alias DScannerBug895 = int[256];
5341     static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init))
5342     {
5343         struct S6 { void opAssign(in S5); }
5344 
5345         static assert(isRvalueAssignable!(S6, S5));
5346         static assert(isLvalueAssignable!(S6, S5));
5347         static assert(isAssignable!(S6, S5));
5348         static assert(isAssignable!(S6, immutable S5));
5349     }
5350     else
5351     {
5352         mixin(q{ struct S6 { void opAssign(scope const ref S5); } });
5353 
5354         static assert(!isRvalueAssignable!(S6, S5));
5355         static assert( isLvalueAssignable!(S6, S5));
5356         static assert(!isAssignable!(S6, S5));
5357         static assert( isLvalueAssignable!(S6, immutable S5));
5358     }
5359 }
5360 
5361 
5362 // Equivalent with TypeStruct::isAssignable in compiler code.
5363 package template isBlitAssignable(T)
5364 {
5365     static if (is(T == enum))
5366     {
5367         enum isBlitAssignable = isBlitAssignable!(OriginalType!T);
5368     }
5369     else static if (isStaticArray!T && is(T == E[n], E, size_t n))
5370     // Workaround for https://issues.dlang.org/show_bug.cgi?id=11499 : isStaticArray!T should not be necessary.
5371     {
5372         enum isBlitAssignable = isBlitAssignable!E;
5373     }
5374     else static if (is(T == struct) || is(T == union))
5375     {
5376         enum isBlitAssignable = isMutable!T &&
5377         {
5378             size_t offset = 0;
5379             bool assignable = true;
5380             foreach (i, F; FieldTypeTuple!T)
5381             {
5382                 static if (i == 0)
5383                 {
5384                 }
5385                 else
5386                 {
5387                     if (T.tupleof[i].offsetof == offset)
5388                     {
5389                         if (assignable)
5390                             continue;
5391                     }
5392                     else
5393                     {
5394                         if (!assignable)
5395                             return false;
5396                     }
5397                 }
5398                 assignable = isBlitAssignable!(typeof(T.tupleof[i]));
5399                 offset = T.tupleof[i].offsetof;
5400             }
5401             return assignable;
5402         }();
5403     }
5404     else
5405         enum isBlitAssignable = isMutable!T;
5406 }
5407 
5408 @safe unittest
5409 {
5410     static assert( isBlitAssignable!int);
5411     static assert(!isBlitAssignable!(const int));
5412 
5413     class C{ const int i; }
5414     static assert( isBlitAssignable!C);
5415 
5416     struct S1{ int i; }
5417     struct S2{ const int i; }
5418     static assert( isBlitAssignable!S1);
5419     static assert(!isBlitAssignable!S2);
5420 
5421     struct S3X { union {       int x;       int y; } }
5422     struct S3Y { union {       int x; const int y; } }
5423     struct S3Z { union { const int x; const int y; } }
5424     static assert( isBlitAssignable!(S3X));
5425     static assert( isBlitAssignable!(S3Y));
5426     static assert(!isBlitAssignable!(S3Z));
5427     static assert(!isBlitAssignable!(const S3X));
5428     static assert(!isBlitAssignable!(inout S3Y));
5429     static assert(!isBlitAssignable!(immutable S3Z));
5430     static assert( isBlitAssignable!(S3X[3]));
5431     static assert( isBlitAssignable!(S3Y[3]));
5432     static assert(!isBlitAssignable!(S3Z[3]));
5433     enum ES3X : S3X { a = S3X() }
5434     enum ES3Y : S3Y { a = S3Y() }
5435     enum ES3Z : S3Z { a = S3Z() }
5436     static assert( isBlitAssignable!(ES3X));
5437     static assert( isBlitAssignable!(ES3Y));
5438     static assert(!isBlitAssignable!(ES3Z));
5439     static assert(!isBlitAssignable!(const ES3X));
5440     static assert(!isBlitAssignable!(inout ES3Y));
5441     static assert(!isBlitAssignable!(immutable ES3Z));
5442     static assert( isBlitAssignable!(ES3X[3]));
5443     static assert( isBlitAssignable!(ES3Y[3]));
5444     static assert(!isBlitAssignable!(ES3Z[3]));
5445 
5446     union U1X {       int x;       int y; }
5447     union U1Y {       int x; const int y; }
5448     union U1Z { const int x; const int y; }
5449     static assert( isBlitAssignable!(U1X));
5450     static assert( isBlitAssignable!(U1Y));
5451     static assert(!isBlitAssignable!(U1Z));
5452     static assert(!isBlitAssignable!(const U1X));
5453     static assert(!isBlitAssignable!(inout U1Y));
5454     static assert(!isBlitAssignable!(immutable U1Z));
5455     static assert( isBlitAssignable!(U1X[3]));
5456     static assert( isBlitAssignable!(U1Y[3]));
5457     static assert(!isBlitAssignable!(U1Z[3]));
5458     enum EU1X : U1X { a = U1X() }
5459     enum EU1Y : U1Y { a = U1Y() }
5460     enum EU1Z : U1Z { a = U1Z() }
5461     static assert( isBlitAssignable!(EU1X));
5462     static assert( isBlitAssignable!(EU1Y));
5463     static assert(!isBlitAssignable!(EU1Z));
5464     static assert(!isBlitAssignable!(const EU1X));
5465     static assert(!isBlitAssignable!(inout EU1Y));
5466     static assert(!isBlitAssignable!(immutable EU1Z));
5467     static assert( isBlitAssignable!(EU1X[3]));
5468     static assert( isBlitAssignable!(EU1Y[3]));
5469     static assert(!isBlitAssignable!(EU1Z[3]));
5470 
5471     struct SA
5472     {
5473         @property int[3] foo() { return [1,2,3]; }
5474         alias foo this;
5475         const int x;    // SA is not blit assignable
5476     }
5477     static assert(!isStaticArray!SA);
5478     static assert(!isBlitAssignable!(SA[3]));
5479 }
5480 
5481 
5482 /*
5483 Works like `isImplicitlyConvertible`, except this cares only about storage
5484 classes of the arguments.
5485  */
5486 private template isStorageClassImplicitlyConvertible(From, To)
5487 {
5488     alias Pointify(T) = void*;
5489 
5490     enum isStorageClassImplicitlyConvertible = is(
5491             ModifyTypePreservingTQ!(Pointify, From) :
5492             ModifyTypePreservingTQ!(Pointify,   To) );
5493 }
5494 
5495 @safe unittest
5496 {
5497     static assert( isStorageClassImplicitlyConvertible!(          int, const int));
5498     static assert( isStorageClassImplicitlyConvertible!(immutable int, const int));
5499 
5500     static assert(!isStorageClassImplicitlyConvertible!(const int,           int));
5501     static assert(!isStorageClassImplicitlyConvertible!(const int, immutable int));
5502     static assert(!isStorageClassImplicitlyConvertible!(int, shared int));
5503     static assert(!isStorageClassImplicitlyConvertible!(shared int, int));
5504 }
5505 
5506 
5507 /**
5508 Determines whether the function type `F` is covariant with `G`, i.e.,
5509 functions of the type `F` can override ones of the type `G`.
5510  */
5511 template isCovariantWith(F, G)
5512 if (is(F == function) && is(G == function) ||
5513     is(F == delegate) && is(G == delegate) ||
5514     isFunctionPointer!F && isFunctionPointer!G)
5515 {
5516     static if (is(F : G))
5517         enum isCovariantWith = true;
5518     else
5519     {
5520         alias Upr = F;
5521         alias Lwr = G;
5522 
5523         /*
5524          * Check for calling convention: require exact match.
5525          */
5526         template checkLinkage()
5527         {
5528             enum ok = functionLinkage!Upr == functionLinkage!Lwr;
5529         }
5530         /*
5531          * Check for variadic parameter: require exact match.
5532          */
5533         template checkVariadicity()
5534         {
5535             enum ok = variadicFunctionStyle!Upr == variadicFunctionStyle!Lwr;
5536         }
5537         /*
5538          * Check for function storage class:
5539          *  - overrider can have narrower storage class than base
5540          */
5541         template checkSTC()
5542         {
5543             // Note the order of arguments.  The convertion order Lwr -> Upr is
5544             // correct since Upr should be semantically 'narrower' than Lwr.
5545             enum ok = isStorageClassImplicitlyConvertible!(Lwr, Upr);
5546         }
5547         /*
5548          * Check for function attributes:
5549          *  - require exact match for ref and @property
5550          *  - overrider can add pure and nothrow, but can't remove them
5551          *  - @safe and @trusted are covariant with each other, unremovable
5552          */
5553         template checkAttributes()
5554         {
5555             alias FA = FunctionAttribute;
5556             enum uprAtts = functionAttributes!Upr;
5557             enum lwrAtts = functionAttributes!Lwr;
5558             //
5559             enum wantExact = FA.ref_ | FA.property;
5560             enum safety = FA.safe | FA.trusted;
5561             enum ok =
5562                 (  (uprAtts & wantExact)   == (lwrAtts & wantExact)) &&
5563                 (  (uprAtts & FA.pure_   ) >= (lwrAtts & FA.pure_   )) &&
5564                 (  (uprAtts & FA.nothrow_) >= (lwrAtts & FA.nothrow_)) &&
5565                 (!!(uprAtts & safety    )  >= !!(lwrAtts & safety    )) ;
5566         }
5567         /*
5568          * Check for return type: usual implicit convertion.
5569          */
5570         template checkReturnType()
5571         {
5572             enum ok = is(ReturnType!Upr : ReturnType!Lwr);
5573         }
5574         /*
5575          * Check for parameters:
5576          *  - require exact match for types
5577          *    (cf. https://issues.dlang.org/show_bug.cgi?id=3075)
5578          *  - require exact match for in, out, ref and lazy
5579          *  - overrider can add scope, but can't remove
5580          */
5581         template checkParameters()
5582         {
5583             alias STC = ParameterStorageClass;
5584             alias UprParams = Parameters!Upr;
5585             alias LwrParams = Parameters!Lwr;
5586             alias UprPSTCs  = ParameterStorageClassTuple!Upr;
5587             alias LwrPSTCs  = ParameterStorageClassTuple!Lwr;
5588             //
5589             template checkNext(size_t i)
5590             {
5591                 static if (i < UprParams.length)
5592                 {
5593                     enum uprStc = UprPSTCs[i];
5594                     enum lwrStc = LwrPSTCs[i];
5595                     //
5596                     enum wantExact = STC.out_ | STC.ref_ | STC.lazy_ | STC.return_;
5597                     enum ok =
5598                         ((uprStc & wantExact )  == (lwrStc & wantExact )) &&
5599                         ((uprStc & STC.scope_)  >= (lwrStc & STC.scope_)) &&
5600                         checkNext!(i + 1).ok;
5601                 }
5602                 else
5603                     enum ok = true; // done
5604             }
5605             static if (UprParams.length == LwrParams.length)
5606                 enum ok = is(UprParams == LwrParams) && checkNext!(0).ok;
5607             else
5608                 enum ok = false;
5609         }
5610 
5611         /* run all the checks */
5612         enum isCovariantWith =
5613             checkLinkage    !().ok &&
5614             checkVariadicity!().ok &&
5615             checkSTC        !().ok &&
5616             checkAttributes !().ok &&
5617             checkReturnType !().ok &&
5618             checkParameters !().ok ;
5619     }
5620 }
5621 
5622 ///
5623 @safe unittest
5624 {
5625     interface I { I clone(); }
5626     interface J { J clone(); }
5627     class C : I
5628     {
5629         override C clone()   // covariant overriding of I.clone()
5630         {
5631             return new C;
5632         }
5633     }
5634 
5635     // C.clone() can override I.clone(), indeed.
5636     static assert(isCovariantWith!(typeof(C.clone), typeof(I.clone)));
5637 
5638     // C.clone() can't override J.clone(); the return type C is not implicitly
5639     // convertible to J.
5640     static assert(!isCovariantWith!(typeof(C.clone), typeof(J.clone)));
5641 }
5642 
5643 @safe unittest
5644 {
5645     enum bool isCovariantWith(alias f, alias g) = .isCovariantWith!(typeof(f), typeof(g));
5646 
5647     // covariant return type
5648     interface I     {}
5649     interface J : I {}
5650     interface BaseA            {          const(I) test(int); }
5651     interface DerivA_1 : BaseA { override const(J) test(int); }
5652     interface DerivA_2 : BaseA { override       J  test(int); }
5653     static assert( isCovariantWith!(DerivA_1.test, BaseA.test));
5654     static assert( isCovariantWith!(DerivA_2.test, BaseA.test));
5655     static assert(!isCovariantWith!(BaseA.test, DerivA_1.test));
5656     static assert(!isCovariantWith!(BaseA.test, DerivA_2.test));
5657     static assert( isCovariantWith!(BaseA.test, BaseA.test));
5658     static assert( isCovariantWith!(DerivA_1.test, DerivA_1.test));
5659     static assert( isCovariantWith!(DerivA_2.test, DerivA_2.test));
5660 
5661      // function, function pointer and delegate
5662      J function() derived_function;
5663      I function() base_function;
5664      J delegate() derived_delegate;
5665      I delegate() base_delegate;
5666      static assert(.isCovariantWith!(typeof(derived_function), typeof(base_function)));
5667      static assert(.isCovariantWith!(typeof(*derived_function), typeof(*base_function)));
5668      static assert(.isCovariantWith!(typeof(derived_delegate), typeof(base_delegate)));
5669 
5670     // scope parameter
5671     interface BaseB            {          void test(      int*,       int*); }
5672     interface DerivB_1 : BaseB { override void test(scope int*,       int*); }
5673     interface DerivB_2 : BaseB { override void test(      int*, scope int*); }
5674     interface DerivB_3 : BaseB { override void test(scope int*, scope int*); }
5675     static assert( isCovariantWith!(DerivB_1.test, BaseB.test));
5676     static assert( isCovariantWith!(DerivB_2.test, BaseB.test));
5677     static assert( isCovariantWith!(DerivB_3.test, BaseB.test));
5678     static assert(!isCovariantWith!(BaseB.test, DerivB_1.test));
5679     static assert(!isCovariantWith!(BaseB.test, DerivB_2.test));
5680     static assert(!isCovariantWith!(BaseB.test, DerivB_3.test));
5681 
5682     // function storage class
5683     interface BaseC            {          void test()      ; }
5684     interface DerivC_1 : BaseC { override void test() const; }
5685     static assert( isCovariantWith!(DerivC_1.test, BaseC.test));
5686     static assert(!isCovariantWith!(BaseC.test, DerivC_1.test));
5687 
5688     // increasing safety
5689     interface BaseE            {          void test()         ; }
5690     interface DerivE_1 : BaseE { override void test() @safe   ; }
5691     interface DerivE_2 : BaseE { override void test() @trusted; }
5692     static assert( isCovariantWith!(DerivE_1.test, BaseE.test));
5693     static assert( isCovariantWith!(DerivE_2.test, BaseE.test));
5694     static assert(!isCovariantWith!(BaseE.test, DerivE_1.test));
5695     static assert(!isCovariantWith!(BaseE.test, DerivE_2.test));
5696 
5697     // @safe and @trusted
5698     interface BaseF
5699     {
5700         void test1() @safe;
5701         void test2() @trusted;
5702     }
5703     interface DerivF : BaseF
5704     {
5705         override void test1() @trusted;
5706         override void test2() @safe;
5707     }
5708     static assert( isCovariantWith!(DerivF.test1, BaseF.test1));
5709     static assert( isCovariantWith!(DerivF.test2, BaseF.test2));
5710 }
5711 
5712 
5713 // Needed for rvalueOf/lvalueOf because "inout on return means
5714 // inout must be on a parameter as well"
5715 private struct __InoutWorkaroundStruct{}
5716 
5717 /**
5718 Creates an lvalue or rvalue of type `T` for `typeof(...)` and
5719 $(DDSUBLINK spec/traits, compiles, `__traits(compiles, ...)`) purposes. No actual value is returned.
5720 
5721 Params:
5722     T = The type to transform
5723 
5724 Note: Trying to use returned value will result in a
5725 "Symbol Undefined" error at link time.
5726 */
5727 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5728 
5729 /// ditto
5730 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
5731 
5732 // Note: can't put these unittests together as function overloads
5733 // aren't allowed inside functions.
5734 ///
5735 @system unittest
5736 {
5737     static int f(int);
5738     static assert(is(typeof(f(rvalueOf!int)) == int));
5739 }
5740 
5741 ///
5742 @system unittest
5743 {
5744     static bool f(ref int);
5745     static assert(is(typeof(f(lvalueOf!int)) == bool));
5746 }
5747 
5748 @system unittest
5749 {
5750     void needLvalue(T)(ref T);
5751     static struct S { }
5752     int i;
5753     struct Nested { void f() { ++i; } }
5754     static foreach (T; AliasSeq!(int, immutable int, inout int, string, S, Nested, Object))
5755     {
5756         static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
5757         static assert( __traits(compiles, needLvalue(lvalueOf!T)));
5758         static assert(is(typeof(rvalueOf!T) == T));
5759         static assert(is(typeof(lvalueOf!T) == T));
5760     }
5761 
5762     static assert(!__traits(compiles, rvalueOf!int = 1));
5763     static assert( __traits(compiles, lvalueOf!byte = 127));
5764     static assert(!__traits(compiles, lvalueOf!byte = 128));
5765 }
5766 
5767 
5768 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5769 // SomethingTypeOf
5770 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
5771 
5772 /*
5773  */
5774 template BooleanTypeOf(T)
5775 {
5776     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5777         alias X = BooleanTypeOf!AT;
5778     else
5779         alias X = OriginalType!T;
5780 
5781     static if (is(immutable X == immutable bool))
5782     {
5783         alias BooleanTypeOf = X;
5784     }
5785     else
5786         static assert(0, T.stringof~" is not boolean type");
5787 }
5788 
5789 @safe unittest
5790 {
5791     // unexpected failure, maybe dmd type-merging bug
5792     static foreach (T; AliasSeq!bool)
5793         static foreach (Q; TypeQualifierList)
5794         {
5795             static assert( is(Q!T == BooleanTypeOf!(            Q!T  )));
5796             static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) )));
5797         }
5798 
5799     static foreach (T; AliasSeq!(void, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5800         static foreach (Q; TypeQualifierList)
5801         {
5802             static assert(!is(BooleanTypeOf!(            Q!T  )), Q!T.stringof);
5803             static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) )));
5804         }
5805 }
5806 
5807 @safe unittest
5808 {
5809     struct B
5810     {
5811         bool val;
5812         alias val this;
5813     }
5814     struct S
5815     {
5816         B b;
5817         alias b this;
5818     }
5819     static assert(is(BooleanTypeOf!B == bool));
5820     static assert(is(BooleanTypeOf!S == bool));
5821 }
5822 
5823 /*
5824  */
5825 template IntegralTypeOf(T)
5826 {
5827     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5828         alias X = IntegralTypeOf!AT;
5829     else
5830         alias X = OriginalType!T;
5831 
5832     static if (__traits(isIntegral, X) && __traits(isZeroInit, X) // Not char, wchar, or dchar.
5833         && !is(immutable X == immutable bool) && !is(X == __vector))
5834     {
5835         alias IntegralTypeOf = X;
5836     }
5837     else
5838         static assert(0, T.stringof~" is not an integral type");
5839 }
5840 
5841 @safe unittest
5842 {
5843     static foreach (T; IntegralTypeList)
5844         static foreach (Q; TypeQualifierList)
5845         {
5846             static assert( is(Q!T == IntegralTypeOf!(            Q!T  )));
5847             static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) )));
5848         }
5849 
5850     static foreach (T; AliasSeq!(void, bool, FloatingPointTypeList,
5851                 /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5852         static foreach (Q; TypeQualifierList)
5853         {
5854             static assert(!is(IntegralTypeOf!(            Q!T  )));
5855             static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) )));
5856         }
5857 }
5858 
5859 /*
5860  */
5861 template FloatingPointTypeOf(T)
5862 {
5863     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5864         alias X = FloatingPointTypeOf!AT;
5865     else
5866         alias X = OriginalType!T;
5867 
5868     static if (is(immutable X == immutable U, U) && is(U == float) || is(U == double) || is(U == real))
5869     {
5870         alias FloatingPointTypeOf = X;
5871     }
5872     else
5873         static assert(0, T.stringof~" is not a floating point type");
5874 }
5875 
5876 @safe unittest
5877 {
5878     static foreach (T; FloatingPointTypeList)
5879         static foreach (Q; TypeQualifierList)
5880         {
5881             static assert( is(Q!T == FloatingPointTypeOf!(            Q!T  )));
5882             static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5883         }
5884 
5885     static foreach (T; AliasSeq!(void, bool, IntegralTypeList, /*ImaginaryTypeList, ComplexTypeList,*/ CharTypeList))
5886         static foreach (Q; TypeQualifierList)
5887         {
5888             static assert(!is(FloatingPointTypeOf!(            Q!T  )));
5889             static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) )));
5890         }
5891 }
5892 
5893 /*
5894  */
5895 template NumericTypeOf(T)
5896 {
5897     static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X))
5898     {
5899         alias NumericTypeOf = X;
5900     }
5901     else
5902         static assert(0, T.stringof~" is not a numeric type");
5903 }
5904 
5905 @safe unittest
5906 {
5907     static foreach (T; NumericTypeList)
5908         static foreach (Q; TypeQualifierList)
5909         {
5910             static assert( is(Q!T == NumericTypeOf!(            Q!T  )));
5911             static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) )));
5912         }
5913 
5914     static foreach (T; AliasSeq!(void, bool, CharTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5915         static foreach (Q; TypeQualifierList)
5916         {
5917             static assert(!is(NumericTypeOf!(            Q!T  )));
5918             static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) )));
5919         }
5920 }
5921 
5922 /*
5923  */
5924 template UnsignedTypeOf(T)
5925 {
5926     static if (is(IntegralTypeOf!T X) && __traits(isUnsigned, X))
5927         alias UnsignedTypeOf = X;
5928     else
5929         static assert(0, T.stringof~" is not an unsigned type.");
5930 }
5931 
5932 /*
5933  */
5934 template SignedTypeOf(T)
5935 {
5936     static if (is(IntegralTypeOf!T X) && !__traits(isUnsigned, X))
5937         alias SignedTypeOf = X;
5938     else static if (is(FloatingPointTypeOf!T X))
5939         alias SignedTypeOf = X;
5940     else
5941         static assert(0, T.stringof~" is not an signed type.");
5942 }
5943 
5944 /*
5945  */
5946 template CharTypeOf(T)
5947 {
5948     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5949         alias X = CharTypeOf!AT;
5950     else
5951         alias X = OriginalType!T;
5952 
5953     static if (is(immutable X == immutable U, U) && is(U == char) || is(U == wchar) || is(U == dchar))
5954     {
5955         alias CharTypeOf = X;
5956     }
5957     else
5958         static assert(0, T.stringof~" is not a character type");
5959 }
5960 
5961 @safe unittest
5962 {
5963     static foreach (T; CharTypeList)
5964         static foreach (Q; TypeQualifierList)
5965         {
5966             static assert( is(CharTypeOf!(            Q!T  )));
5967             static assert( is(CharTypeOf!( SubTypeOf!(Q!T) )));
5968         }
5969 
5970     static foreach (T; AliasSeq!(void, bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
5971         static foreach (Q; TypeQualifierList)
5972         {
5973             static assert(!is(CharTypeOf!(            Q!T  )));
5974             static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5975         }
5976 
5977     static foreach (T; AliasSeq!(string, wstring, dstring, char[4]))
5978         static foreach (Q; TypeQualifierList)
5979         {
5980             static assert(!is(CharTypeOf!(            Q!T  )));
5981             static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) )));
5982         }
5983 }
5984 
5985 /*
5986  */
5987 template StaticArrayTypeOf(T)
5988 {
5989     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
5990         alias X = StaticArrayTypeOf!AT;
5991     else
5992         alias X = OriginalType!T;
5993 
5994     static if (__traits(isStaticArray, X))
5995         alias StaticArrayTypeOf = X;
5996     else
5997         static assert(0, T.stringof~" is not a static array type");
5998 }
5999 
6000 @safe unittest
6001 {
6002     static foreach (T; AliasSeq!(bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6003         static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6004         {
6005             static assert(is( Q!(   T[1] ) == StaticArrayTypeOf!( Q!(              T[1]  ) ) ));
6006 
6007             static foreach (P; TypeQualifierList)
6008             { // SubTypeOf cannot have inout type
6009                 static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) ));
6010             }
6011         }
6012 
6013     static foreach (T; AliasSeq!void)
6014         static foreach (Q; AliasSeq!TypeQualifierList)
6015         {
6016             static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) ));
6017         }
6018 }
6019 
6020 /*
6021  */
6022 template DynamicArrayTypeOf(T)
6023 {
6024     import core.internal.traits : _DynamicArrayTypeOf = DynamicArrayTypeOf;
6025     alias DynamicArrayTypeOf = _DynamicArrayTypeOf!T;
6026 }
6027 
6028 @safe unittest
6029 {
6030     import std.meta : Alias;
6031     static foreach (T; AliasSeq!(/*void, */bool, NumericTypeList, /*ImaginaryTypeList, ComplexTypeList*/))
6032         static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6033         {
6034             static assert(is( Q!T[]  == DynamicArrayTypeOf!( Q!T[] ) ));
6035             static assert(is( Q!(T[])  == DynamicArrayTypeOf!( Q!(T[]) ) ));
6036 
6037             static foreach (P; AliasSeq!(Alias, ConstOf, ImmutableOf))
6038             {
6039                 static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) ));
6040                 static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) ));
6041             }
6042         }
6043 
6044     static assert(!is(DynamicArrayTypeOf!(int[3])));
6045     static assert(!is(DynamicArrayTypeOf!(void[3])));
6046     static assert(!is(DynamicArrayTypeOf!(typeof(null))));
6047 }
6048 
6049 /*
6050  */
6051 template ArrayTypeOf(T)
6052 {
6053     static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X))
6054     {
6055         alias ArrayTypeOf = X;
6056     }
6057     else
6058         static assert(0, T.stringof~" is not an array type");
6059 }
6060 
6061 /*
6062  * Converts strings and string-like types to the corresponding dynamic array of characters.
6063  * Params:
6064  * T = one of the following:
6065  * 1. dynamic arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6066  *    (`shared` is rejected)
6067  * 2. static arrays of `char`, `wchar`, or `dchar` that are implicitly convertible to `const`
6068  *    (`shared` is rejected)
6069  * 3. aggregates that use `alias this` to refer to a field that is (1), (2), or (3)
6070  *
6071  * Other cases are rejected with a compile time error.
6072  * `typeof(null)` is rejected.
6073  *
6074  * Returns:
6075  *  The result of `[]` applied to the qualified character type.
6076  */
6077 template StringTypeOf(T)
6078 {
6079     static if (is(T == typeof(null)))
6080     {
6081         // It is impossible to determine exact string type from typeof(null) -
6082         // it means that StringTypeOf!(typeof(null)) is undefined.
6083         // Then this behavior is convenient for template constraint.
6084         static assert(0, T.stringof~" is not a string type");
6085     }
6086     else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[]))
6087     {
6088         static if (is(T : U[], U))
6089             alias StringTypeOf = U[];
6090         else
6091             static assert(0);
6092     }
6093     else
6094         static assert(0, T.stringof~" is not a string type");
6095 }
6096 
6097 @safe unittest
6098 {
6099     import std.meta : Alias;
6100     static foreach (T; CharTypeList)
6101         static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, InoutOf))
6102         {
6103             static assert(is(Q!T[] == StringTypeOf!( Q!T[] )));
6104 
6105             static if (!__traits(isSame, Q, InoutOf))
6106             {{
6107                 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
6108 
6109                 alias Str = Q!T[];
6110                 struct C(S) { S val;  alias val this; }
6111                 static assert(is(StringTypeOf!(C!Str) == Str));
6112             }}
6113         }
6114 
6115     static foreach (T; CharTypeList)
6116         static foreach (Q; AliasSeq!(SharedOf, SharedConstOf, SharedInoutOf))
6117         {
6118             static assert(!is(StringTypeOf!( Q!T[] )));
6119         }
6120 }
6121 
6122 @safe unittest
6123 {
6124     static assert(is(StringTypeOf!(char[4]) == char[]));
6125 
6126     struct S
6127     {
6128         string s;
6129         alias s this;
6130     }
6131 
6132     struct T
6133     {
6134         S s;
6135         alias s this;
6136     }
6137 
6138     static assert(is(StringTypeOf!S == string));
6139     static assert(is(StringTypeOf!T == string));
6140 }
6141 
6142 /*
6143  */
6144 template AssocArrayTypeOf(T)
6145 {
6146     static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6147         alias X = AssocArrayTypeOf!AT;
6148     else
6149         alias X = OriginalType!T;
6150 
6151     static if (__traits(isAssociativeArray, X))
6152     {
6153         alias AssocArrayTypeOf = X;
6154     }
6155     else
6156         static assert(0, T.stringof~" is not an associative array type");
6157 }
6158 
6159 @safe unittest
6160 {
6161     static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6162         static foreach (P; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6163             static foreach (Q; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6164                 static foreach (R; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6165                 {
6166                     static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!(            P!(Q!T[R!T])  ) ));
6167                 }
6168 
6169     static foreach (T; AliasSeq!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/))
6170         static foreach (O; AliasSeq!(TypeQualifierList, InoutOf, SharedInoutOf))
6171             static foreach (P; AliasSeq!TypeQualifierList)
6172                 static foreach (Q; AliasSeq!TypeQualifierList)
6173                     static foreach (R; AliasSeq!TypeQualifierList)
6174                     {
6175                         static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) ));
6176                     }
6177 }
6178 
6179 /*
6180  */
6181 template BuiltinTypeOf(T)
6182 {
6183     static if (is(T : void))
6184         alias BuiltinTypeOf = void;
6185     else
6186     {
6187         static if (is(typeof(__traits(getMember, T.init, __traits(getAliasThis, T)[0])) AT) && !is(AT[] == AT))
6188             alias X = BuiltinTypeOf!AT;
6189         else
6190             alias X = OriginalType!T;
6191         static if (__traits(isArithmetic, X) && !is(X == __vector) ||
6192                 __traits(isStaticArray, X) || is(X == E[], E) ||
6193                 __traits(isAssociativeArray, X) || is(X == typeof(null)))
6194             alias BuiltinTypeOf = X;
6195         else
6196             static assert(0);
6197     }
6198 }
6199 
6200 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6201 // isSomething
6202 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
6203 
6204 /**
6205  * Detect whether `T` is a built-in boolean type or enum of boolean base type.
6206  */
6207 enum bool isBoolean(T) = __traits(isUnsigned, T) && is(T : bool);
6208 
6209 ///
6210 @safe unittest
6211 {
6212     static assert( isBoolean!bool);
6213     enum EB : bool { a = true }
6214     static assert( isBoolean!EB);
6215 
6216     struct SubTypeOfBool
6217     {
6218         bool val;
6219         alias val this;
6220     }
6221     static assert(!isBoolean!(SubTypeOfBool));
6222 }
6223 
6224 @safe unittest
6225 {
6226     static struct S(T)
6227     {
6228         T t;
6229         alias t this;
6230     }
6231     static assert(!isIntegral!(S!bool));
6232 }
6233 
6234 /**
6235  * Detect whether `T` is a built-in integral type.
6236  * Integral types are `byte`, `ubyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `cent`, `ucent`,
6237  * and enums with an integral type as its base type.
6238  * Params:
6239  *      T = type to test
6240  * Returns:
6241  *      `true` if `T` is an integral type
6242  * Note:
6243  *      this is not the same as $(LINK2 https://dlang.org/spec/traits.html#isIntegral, `__traits(isIntegral)`)
6244  */
6245 template isIntegral(T)
6246 {
6247     static if (!__traits(isIntegral, T))
6248         enum isIntegral = false;
6249     else static if (is(T U == enum))
6250         enum isIntegral = isIntegral!U;
6251     else
6252         enum isIntegral = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6253             && !is(immutable T == immutable bool) && !is(T == __vector);
6254 }
6255 
6256 ///
6257 @safe unittest
6258 {
6259     static assert(
6260         isIntegral!byte &&
6261         isIntegral!short &&
6262         isIntegral!int &&
6263         isIntegral!long &&
6264         isIntegral!(const(long)) &&
6265         isIntegral!(immutable(long))
6266     );
6267 
6268     static assert(
6269         !isIntegral!bool &&
6270         !isIntegral!char &&
6271         !isIntegral!double
6272     );
6273 
6274     // types which act as integral values do not pass
6275     struct S
6276     {
6277         int val;
6278         alias val this;
6279     }
6280 
6281     static assert(!isIntegral!S);
6282 }
6283 
6284 @safe unittest
6285 {
6286     static foreach (T; IntegralTypeList)
6287     {
6288         static foreach (Q; TypeQualifierList)
6289         {
6290             static assert( isIntegral!(Q!T));
6291             static assert(!isIntegral!(SubTypeOf!(Q!T)));
6292         }
6293     }
6294 
6295     static assert(!isIntegral!float);
6296 
6297     enum EU : uint { a = 0, b = 1, c = 2 }  // base type is unsigned
6298     // base type is signed (https://issues.dlang.org/show_bug.cgi?id=7909)
6299     enum EI : int { a = -1, b = 0, c = 1 }
6300     static assert(isIntegral!EU &&  isUnsigned!EU && !isSigned!EU);
6301     static assert(isIntegral!EI && !isUnsigned!EI &&  isSigned!EI);
6302 }
6303 
6304 /**
6305  * Detect whether `T` is a built-in floating point type.
6306  *
6307  * See also: $(DDSUBLINK spec/traits, isFloating, `__traits(isFloating, T)`)
6308  */
6309 // is(T : real) to discount complex types
6310 enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real);
6311 
6312 ///
6313 @safe unittest
6314 {
6315     static assert(
6316         isFloatingPoint!float &&
6317         isFloatingPoint!double &&
6318         isFloatingPoint!real &&
6319         isFloatingPoint!(const(real)) &&
6320         isFloatingPoint!(immutable(real))
6321     );
6322 
6323     static assert(!isFloatingPoint!int);
6324 
6325     // types which act as floating point values do not pass
6326     struct S
6327     {
6328         float val;
6329         alias val this;
6330     }
6331 
6332     static assert(!isFloatingPoint!S);
6333 }
6334 
6335 @safe unittest
6336 {
6337     enum EF : real { a = 1.414, b = 1.732, c = 2.236 }
6338 
6339     static foreach (T; AliasSeq!(FloatingPointTypeList, EF))
6340     {
6341         static foreach (Q; TypeQualifierList)
6342         {
6343             static assert( isFloatingPoint!(Q!T));
6344             static assert(!isFloatingPoint!(SubTypeOf!(Q!T)));
6345         }
6346     }
6347     static foreach (T; IntegralTypeList)
6348     {
6349         static foreach (Q; TypeQualifierList)
6350         {
6351             static assert(!isFloatingPoint!(Q!T));
6352         }
6353     }
6354     static if (is(__vector(float[4])))
6355     {
6356         static assert(!isFloatingPoint!(__vector(float[4])));
6357     }
6358 }
6359 
6360 /**
6361  * Detect whether `T` is a built-in numeric type (integral or floating
6362  * point).
6363  */
6364 template isNumeric(T)
6365 {
6366     static if (!__traits(isArithmetic, T))
6367         enum isNumeric = false;
6368     else static if (__traits(isFloating, T))
6369         enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
6370     else static if (is(T U == enum))
6371         enum isNumeric = isNumeric!U;
6372     else
6373         enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6374             && !is(immutable T == immutable bool) && !is(T == __vector);
6375 }
6376 
6377 ///
6378 @safe unittest
6379 {
6380     static assert(
6381         isNumeric!byte &&
6382         isNumeric!short &&
6383         isNumeric!int &&
6384         isNumeric!long &&
6385         isNumeric!float &&
6386         isNumeric!double &&
6387         isNumeric!real &&
6388         isNumeric!(const(real)) &&
6389         isNumeric!(immutable(real))
6390     );
6391 
6392     static assert(
6393         !isNumeric!void &&
6394         !isNumeric!bool &&
6395         !isNumeric!char &&
6396         !isNumeric!wchar &&
6397         !isNumeric!dchar
6398     );
6399 
6400     // types which act as numeric values do not pass
6401     struct S
6402     {
6403         int val;
6404         alias val this;
6405     }
6406 
6407     static assert(!isNumeric!S);
6408 }
6409 
6410 @safe unittest
6411 {
6412     static foreach (T; AliasSeq!(NumericTypeList))
6413     {
6414         static foreach (Q; TypeQualifierList)
6415         {
6416             static assert( isNumeric!(Q!T));
6417             static assert(!isNumeric!(SubTypeOf!(Q!T)));
6418         }
6419     }
6420 
6421     static struct S(T)
6422     {
6423         T t;
6424         alias t this;
6425     }
6426     static assert(!isNumeric!(S!int));
6427 
6428     enum EChar : char { a = 0, }
6429     static assert(!isNumeric!EChar);
6430 
6431     static if (is(__vector(float[4])))
6432     {
6433         static assert(!isNumeric!(__vector(float[4])));
6434     }
6435     static if (is(__vector(int[4])))
6436     {
6437         static assert(!isNumeric!(__vector(int[4])));
6438     }
6439 
6440     static assert(!isNumeric!ifloat);
6441     static assert(!isNumeric!cfloat);
6442 }
6443 
6444 /**
6445  * Detect whether `T` is a scalar type (a built-in numeric, character or
6446  * boolean type).
6447  *
6448  * See also: $(DDSUBLINK spec/traits, isScalar, `__traits(isScalar, T)`)
6449  */
6450 // is(T : real) to discount complex types
6451 enum bool isScalarType(T) = __traits(isScalar, T) && is(T : real);
6452 
6453 ///
6454 @safe unittest
6455 {
6456     static assert(!isScalarType!void);
6457     static assert( isScalarType!(immutable(byte)));
6458     static assert( isScalarType!(immutable(ushort)));
6459     static assert( isScalarType!(immutable(int)));
6460     static assert( isScalarType!(ulong));
6461     static assert( isScalarType!(shared(float)));
6462     static assert( isScalarType!(shared(const bool)));
6463     static assert( isScalarType!(const(char)));
6464     static assert( isScalarType!(wchar));
6465     static assert( isScalarType!(const(dchar)));
6466     static assert( isScalarType!(const(double)));
6467     static assert( isScalarType!(const(real)));
6468 }
6469 
6470 @safe unittest
6471 {
6472     static struct S(T)
6473     {
6474         T t;
6475         alias t this;
6476     }
6477     static assert(!isScalarType!(S!int));
6478 }
6479 
6480 /**
6481  * Detect whether `T` is a basic type (scalar type or void).
6482  */
6483 enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void);
6484 
6485 ///
6486 @safe unittest
6487 {
6488     static assert(isBasicType!void);
6489     static assert(isBasicType!(const(void)));
6490     static assert(isBasicType!(shared(void)));
6491     static assert(isBasicType!(immutable(void)));
6492     static assert(isBasicType!(shared const(void)));
6493     static assert(isBasicType!(shared inout(void)));
6494     static assert(isBasicType!(shared inout const(void)));
6495     static assert(isBasicType!(inout(void)));
6496     static assert(isBasicType!(inout const(void)));
6497     static assert(isBasicType!(immutable(int)));
6498     static assert(isBasicType!(shared(float)));
6499     static assert(isBasicType!(shared(const bool)));
6500     static assert(isBasicType!(const(dchar)));
6501 }
6502 
6503 /**
6504  * Detect whether `T` is a built-in unsigned numeric type.
6505  */
6506 template isUnsigned(T)
6507 {
6508     static if (!__traits(isUnsigned, T))
6509         enum isUnsigned = false;
6510     else static if (is(T U == enum))
6511         enum isUnsigned = isUnsigned!U;
6512     else
6513         enum isUnsigned = __traits(isZeroInit, T) // Not char, wchar, or dchar.
6514             && !is(immutable T == immutable bool) && !is(T == __vector);
6515 }
6516 
6517 ///
6518 @safe unittest
6519 {
6520     static assert(
6521         isUnsigned!uint &&
6522         isUnsigned!ulong
6523     );
6524 
6525     static assert(
6526         !isUnsigned!char &&
6527         !isUnsigned!int &&
6528         !isUnsigned!long &&
6529         !isUnsigned!char &&
6530         !isUnsigned!wchar &&
6531         !isUnsigned!dchar
6532     );
6533 }
6534 
6535 @safe unittest
6536 {
6537     static foreach (T; AliasSeq!(UnsignedIntTypeList))
6538     {
6539         static foreach (Q; TypeQualifierList)
6540         {
6541             static assert( isUnsigned!(Q!T));
6542             static assert(!isUnsigned!(SubTypeOf!(Q!T)));
6543         }
6544     }
6545 
6546     static struct S(T)
6547     {
6548         T t;
6549         alias t this;
6550     }
6551     static assert(!isUnsigned!(S!uint));
6552 
6553     enum EChar : char { a = 0, }
6554     static assert(!isUnsigned!EChar);
6555 
6556     static if (is(__vector(uint[4])))
6557     {
6558         static assert(!isUnsigned!(__vector(uint[4])));
6559     }
6560 }
6561 
6562 /**
6563  * Detect whether `T` is a built-in signed numeric type.
6564  */
6565 enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T)
6566                                                   && is(T : real);
6567 
6568 ///
6569 @safe unittest
6570 {
6571     static assert(
6572         isSigned!int &&
6573         isSigned!long
6574     );
6575 
6576     static assert(
6577         !isSigned!uint &&
6578         !isSigned!ulong
6579     );
6580 }
6581 
6582 @safe unittest
6583 {
6584     enum E { e1 = 0 }
6585     static assert(isSigned!E);
6586 
6587     enum Eubyte : ubyte { e1 = 0 }
6588     static assert(!isSigned!Eubyte);
6589 
6590     static foreach (T; AliasSeq!(SignedIntTypeList))
6591     {
6592         static foreach (Q; TypeQualifierList)
6593         {
6594             static assert( isSigned!(Q!T));
6595             static assert(!isSigned!(SubTypeOf!(Q!T)));
6596         }
6597     }
6598 
6599     static struct S(T)
6600     {
6601         T t;
6602         alias t this;
6603     }
6604     static assert(!isSigned!(S!uint));
6605 
6606     static if (is(__vector(int[4])))
6607     {
6608         static assert(!isSigned!(__vector(int[4])));
6609     }
6610 
6611     static assert(!isSigned!ifloat);
6612     static assert(!isSigned!cfloat);
6613 }
6614 
6615 // https://issues.dlang.org/show_bug.cgi?id=17196
6616 @safe unittest
6617 {
6618     static assert(isUnsigned!bool == false);
6619     static assert(isSigned!bool == false);
6620 }
6621 
6622 /**
6623  * Detect whether `T` is one of the built-in character types.
6624  *
6625  * The built-in char types are any of `char`, `wchar` or `dchar`, with
6626  * or without qualifiers.
6627  */
6628 template isSomeChar(T)
6629 {
6630     static if (!__traits(isUnsigned, T))
6631         enum isSomeChar = false;
6632     else static if (is(T U == enum))
6633         enum isSomeChar = isSomeChar!U;
6634     else
6635         enum isSomeChar = !__traits(isZeroInit, T);
6636 }
6637 
6638 ///
6639 @safe unittest
6640 {
6641     //Char types
6642     static assert( isSomeChar!char);
6643     static assert( isSomeChar!wchar);
6644     static assert( isSomeChar!dchar);
6645     static assert( isSomeChar!(typeof('c')));
6646     static assert( isSomeChar!(immutable char));
6647     static assert( isSomeChar!(const dchar));
6648 
6649     //Non char types
6650     static assert(!isSomeChar!int);
6651     static assert(!isSomeChar!byte);
6652     static assert(!isSomeChar!string);
6653     static assert(!isSomeChar!wstring);
6654     static assert(!isSomeChar!dstring);
6655     static assert(!isSomeChar!(char[4]));
6656 }
6657 
6658 @safe unittest
6659 {
6660     enum EC : char { a = 'x', b = 'y' }
6661 
6662     static foreach (T; AliasSeq!(CharTypeList, EC))
6663     {
6664         static foreach (Q; TypeQualifierList)
6665         {
6666             static assert( isSomeChar!(            Q!T  ));
6667             static assert(!isSomeChar!( SubTypeOf!(Q!T) ));
6668         }
6669     }
6670 
6671     // alias-this types are not allowed
6672     static struct S(T)
6673     {
6674         T t;
6675         alias t this;
6676     }
6677     static assert(!isSomeChar!(S!char));
6678 }
6679 
6680 /**
6681 Detect whether `T` is one of the built-in string types.
6682 
6683 The built-in string types are `Char[]`, where `Char` is any of `char`,
6684 `wchar` or `dchar`, with or without qualifiers.
6685 
6686 Static arrays of characters (like `char[80]`) are not considered
6687 built-in string types.
6688  */
6689 enum bool isSomeString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar) || is(C == dchar));
6690 
6691 ///
6692 @safe unittest
6693 {
6694     //String types
6695     static assert( isSomeString!string);
6696     static assert( isSomeString!(wchar[]));
6697     static assert( isSomeString!(dchar[]));
6698     static assert( isSomeString!(typeof("aaa")));
6699     static assert( isSomeString!(const(char)[]));
6700 
6701     //Non string types
6702     static assert(!isSomeString!int);
6703     static assert(!isSomeString!(int[]));
6704     static assert(!isSomeString!(byte[]));
6705     static assert(!isSomeString!(typeof(null)));
6706     static assert(!isSomeString!(char[4]));
6707 
6708     enum ES : string { a = "aaa", b = "bbb" }
6709     static assert(!isSomeString!ES);
6710 
6711     static struct Stringish
6712     {
6713         string str;
6714         alias str this;
6715     }
6716     static assert(!isSomeString!Stringish);
6717 }
6718 
6719 @safe unittest
6720 {
6721     static foreach (T; AliasSeq!(char[], dchar[], string, wstring, dstring))
6722     {
6723         static assert( isSomeString!(           T ));
6724         static assert(!isSomeString!(SubTypeOf!(T)));
6725     }
6726     enum C : char { _ = 0 }
6727     static assert(!isSomeString!(C[]));
6728 }
6729 
6730 /**
6731  * Detect whether type `T` is a narrow string.
6732  *
6733  * All arrays that use char, wchar, and their qualified versions are narrow
6734  * strings. (Those include string and wstring).
6735  */
6736 enum bool isNarrowString(T) = is(immutable T == immutable C[], C) && (is(C == char) || is(C == wchar));
6737 
6738 ///
6739 @safe unittest
6740 {
6741     static assert(isNarrowString!string);
6742     static assert(isNarrowString!wstring);
6743     static assert(isNarrowString!(char[]));
6744     static assert(isNarrowString!(wchar[]));
6745 
6746     static assert(!isNarrowString!dstring);
6747     static assert(!isNarrowString!(dchar[]));
6748 
6749     static assert(!isNarrowString!(typeof(null)));
6750     static assert(!isNarrowString!(char[4]));
6751 
6752     enum ES : string { a = "aaa", b = "bbb" }
6753     static assert(!isNarrowString!ES);
6754 
6755     static struct Stringish
6756     {
6757         string str;
6758         alias str this;
6759     }
6760     static assert(!isNarrowString!Stringish);
6761 }
6762 
6763 @safe unittest
6764 {
6765     import std.meta : Alias;
6766     static foreach (T; AliasSeq!(char[], string, wstring))
6767     {
6768         static foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf)/*TypeQualifierList*/)
6769         {
6770             static assert( isNarrowString!(            Q!T  ));
6771             static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6772         }
6773     }
6774 
6775     static foreach (T; AliasSeq!(int, int[], byte[], dchar[], dstring, char[4]))
6776     {
6777         static foreach (Q; TypeQualifierList)
6778         {
6779             static assert(!isNarrowString!(            Q!T  ));
6780             static assert(!isNarrowString!( SubTypeOf!(Q!T) ));
6781         }
6782     }
6783     enum C : char { _ = 0 }
6784     static assert(!isNarrowString!(C[]));
6785 }
6786 
6787 /**
6788  * Detects whether `T` is a comparable type. Basic types and structs and
6789  * classes that implement opCmp are ordering comparable.
6790  */
6791 enum bool isOrderingComparable(T) = is(typeof((ref T a) => a < a ? 1 : 0));
6792 
6793 ///
6794 @safe unittest
6795 {
6796     static assert(isOrderingComparable!int);
6797     static assert(isOrderingComparable!string);
6798 
6799     static struct Foo {}
6800     static assert(!isOrderingComparable!Foo);
6801 
6802     static struct Bar
6803     {
6804         int a;
6805         auto opCmp(Bar b1) const { return a - b1.a; }
6806     }
6807 
6808     Bar b1 = Bar(5);
6809     Bar b2 = Bar(7);
6810     assert(isOrderingComparable!Bar && b2 > b1);
6811 }
6812 
6813 /// ditto
6814 enum bool isEqualityComparable(T) = is(typeof((ref T a) => a == a ? 1 : 0));
6815 
6816 @safe unittest
6817 {
6818     static assert(isEqualityComparable!int);
6819     static assert(isEqualityComparable!string);
6820     static assert(!isEqualityComparable!void);
6821 
6822     struct Foo {}
6823     static assert(isEqualityComparable!Foo);
6824 
6825     struct Bar
6826     {
6827         int a;
6828         auto opEquals(Bar b1) const { return a == b1.a; }
6829     }
6830 
6831     Bar b1 = Bar(5);
6832     Bar b2 = Bar(5);
6833     Bar b3 = Bar(7);
6834     static assert(isEqualityComparable!Bar);
6835     assert(b1 == b2);
6836     assert(b1 != b3);
6837 }
6838 
6839 /**
6840   $(RED Warning: This trait will be deprecated as soon as it is no longer used
6841                  in Phobos. For a function parameter to safely accept a type
6842                  that implicitly converts to string as a string, the conversion
6843                  needs to happen at the callsite; otherwise, the conversion is
6844                  done inside the function, and in many cases, that means that
6845                  local memory is sliced (e.g. if a static array is passed to
6846                  the function, then it's copied, and the resulting dynamic
6847                  array will be a slice of a local variable). So, if the
6848                  resulting string escapes the function, the string refers to
6849                  invalid memory, and accessing it would mean accessing invalid
6850                  memory. As such, the only safe way for a function to accept
6851                  types that implicitly convert to string is for the implicit
6852                  conversion to be done at the callsite, and that can only occur
6853                  if the parameter is explicitly typed as an array, whereas
6854                  using isConvertibleToString in a template constraint would
6855                  result in the conversion being done inside the function. As
6856                  such, isConvertibleToString is inherently unsafe and is going
6857                  to be deprecated.)
6858 
6859    Detect whether `T` is a struct, static array, or enum that is implicitly
6860    convertible to a string.
6861  */
6862 template isConvertibleToString(T)
6863 {
6864     enum isConvertibleToString =
6865         (isAggregateType!T || isStaticArray!T || is(T == enum))
6866         && is(StringTypeOf!T);
6867 }
6868 
6869 ///
6870 @safe unittest
6871 {
6872     static struct AliasedString
6873     {
6874         string s;
6875         alias s this;
6876     }
6877 
6878     enum StringEnum { a = "foo" }
6879 
6880     assert(!isConvertibleToString!string);
6881     assert(isConvertibleToString!AliasedString);
6882     assert(isConvertibleToString!StringEnum);
6883     assert(isConvertibleToString!(char[25]));
6884     assert(!isConvertibleToString!(char[]));
6885 }
6886 
6887 // https://issues.dlang.org/show_bug.cgi?id=16573
6888 @safe unittest
6889 {
6890     enum I : int { foo = 1 }
6891     enum S : string { foo = "foo" }
6892     assert(!isConvertibleToString!I);
6893     assert(isConvertibleToString!S);
6894 }
6895 
6896 package template convertToString(T)
6897 {
6898     static if (isConvertibleToString!T)
6899         alias convertToString = StringTypeOf!T;
6900     else
6901         alias convertToString = T;
6902 }
6903 
6904 /**
6905  * Detect whether type `T` is a string that will be autodecoded.
6906  *
6907  * Given a type `S` that is one of:
6908  * $(OL
6909  *  $(LI `const(char)[]`)
6910  *  $(LI `const(wchar)[]`)
6911  * )
6912  * Type `T` can be one of:
6913  * $(OL
6914  *    $(LI `S`)
6915  *    $(LI implicitly convertible to `T`)
6916  *    $(LI an enum with a base type `T`)
6917  *    $(LI an aggregate with a base type `T`)
6918  * )
6919  * with the proviso that `T` cannot be a static array.
6920  *
6921  * Params:
6922  *      T = type to be tested
6923  *
6924  * Returns:
6925  *      true if T represents a string that is subject to autodecoding
6926  *
6927  * See Also:
6928  *      $(LREF isNarrowString)
6929  */
6930 template isAutodecodableString(T)
6931 {
6932     import std.range.primitives : autodecodeStrings;
6933 
6934     enum isAutodecodableString = autodecodeStrings &&
6935         (is(T : const char[]) || is(T : const wchar[]))
6936         && !is(T : U[n], U, size_t n)
6937         && !is(immutable T : immutable noreturn[]);
6938 }
6939 
6940 ///
6941 @safe unittest
6942 {
6943     static struct Stringish
6944     {
6945         string s;
6946         alias s this;
6947     }
6948     static assert(isAutodecodableString!wstring);
6949     static assert(isAutodecodableString!Stringish);
6950     static assert(!isAutodecodableString!dstring);
6951 
6952     enum E : const(char)[3] { X = "abc" }
6953     enum F : const(char)[] { X = "abc" }
6954     enum G : F { X = F.init }
6955 
6956     static assert(isAutodecodableString!(char[]));
6957     static assert(!isAutodecodableString!(E));
6958     static assert(isAutodecodableString!(F));
6959     static assert(isAutodecodableString!(G));
6960 
6961     struct Stringish2
6962     {
6963         Stringish s;
6964         alias s this;
6965     }
6966 
6967     enum H : Stringish { X = Stringish() }
6968     enum I : Stringish2 { X = Stringish2() }
6969 
6970     static assert(isAutodecodableString!(H));
6971     static assert(isAutodecodableString!(I));
6972 
6973     static assert(!isAutodecodableString!(noreturn[]));
6974     static assert(!isAutodecodableString!(immutable(noreturn)[]));
6975 }
6976 
6977 /**
6978  * Detect whether type `T` is a static array.
6979  *
6980  * See also: $(DDSUBLINK spec/traits, isStaticArray, `__traits(isStaticArray, T)`)
6981  */
6982 enum bool isStaticArray(T) = __traits(isStaticArray, T);
6983 
6984 ///
6985 @safe unittest
6986 {
6987     static assert( isStaticArray!(int[3]));
6988     static assert( isStaticArray!(const(int)[5]));
6989     static assert( isStaticArray!(const(int)[][5]));
6990 
6991     static assert(!isStaticArray!(const(int)[]));
6992     static assert(!isStaticArray!(immutable(int)[]));
6993     static assert(!isStaticArray!(const(int)[4][]));
6994     static assert(!isStaticArray!(int[]));
6995     static assert(!isStaticArray!(int[char]));
6996     static assert(!isStaticArray!(int[1][]));
6997     static assert(!isStaticArray!(int[int]));
6998     static assert(!isStaticArray!int);
6999 }
7000 
7001 @safe unittest
7002 {
7003     static foreach (T; AliasSeq!(int[51], int[][2],
7004                            char[][int][11], immutable char[13u],
7005                            const(real)[1], const(real)[1][1], void[0]))
7006     {
7007         static foreach (Q; TypeQualifierList)
7008         {
7009             static assert( isStaticArray!(            Q!T  ));
7010             static assert(!isStaticArray!( SubTypeOf!(Q!T) ));
7011         }
7012     }
7013 
7014     //enum ESA : int[1] { a = [1], b = [2] }
7015     //static assert( isStaticArray!ESA);
7016 }
7017 
7018 /**
7019  * Detect whether type `T` is a dynamic array.
7020  */
7021 template isDynamicArray(T)
7022 {
7023     static if (is(T == U[], U))
7024         enum bool isDynamicArray = true;
7025     else static if (is(T U == enum))
7026         // BUG: isDynamicArray / isStaticArray considers enums
7027         // with appropriate base types as dynamic/static arrays
7028         // Retain old behaviour for now, see
7029         // https://github.com/dlang/phobos/pull/7574
7030         enum bool isDynamicArray = isDynamicArray!U;
7031     else
7032         enum bool isDynamicArray = false;
7033 }
7034 
7035 ///
7036 @safe unittest
7037 {
7038     static assert( isDynamicArray!(int[]));
7039     static assert( isDynamicArray!(string));
7040     static assert( isDynamicArray!(long[3][]));
7041 
7042     static assert(!isDynamicArray!(int[5]));
7043     static assert(!isDynamicArray!(typeof(null)));
7044 }
7045 
7046 @safe unittest
7047 {
7048     import std.meta : AliasSeq;
7049     static foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
7050     {
7051         static foreach (Q; TypeQualifierList)
7052         {
7053             static assert( isDynamicArray!(            Q!T  ));
7054             static assert(!isDynamicArray!( SubTypeOf!(Q!T) ));
7055         }
7056     }
7057 
7058     static assert(!isDynamicArray!(int[5]));
7059 
7060     static struct AliasThis
7061     {
7062         int[] values;
7063         alias values this;
7064     }
7065 
7066     static assert(!isDynamicArray!AliasThis);
7067 
7068     // https://github.com/dlang/phobos/pull/7574/files#r464115492
7069     enum E : string
7070     {
7071         a = "a",
7072         b = "b",
7073     }
7074     static assert( isDynamicArray!E);
7075 }
7076 
7077 /**
7078  * Detect whether type `T` is an array (static or dynamic; for associative
7079  *  arrays see $(LREF isAssociativeArray)).
7080  */
7081 enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;
7082 
7083 ///
7084 @safe unittest
7085 {
7086     static assert( isArray!(int[]));
7087     static assert( isArray!(int[5]));
7088     static assert( isArray!(string));
7089 
7090     static assert(!isArray!uint);
7091     static assert(!isArray!(uint[uint]));
7092     static assert(!isArray!(typeof(null)));
7093 }
7094 
7095 @safe unittest
7096 {
7097     import std.meta : AliasSeq;
7098     static foreach (T; AliasSeq!(int[], int[5], void[]))
7099     {
7100         static foreach (Q; TypeQualifierList)
7101         {
7102             static assert( isArray!(Q!T));
7103             static assert(!isArray!(SubTypeOf!(Q!T)));
7104         }
7105     }
7106 }
7107 
7108 /**
7109  * Detect whether `T` is an associative array type
7110  *
7111  * See also: $(DDSUBLINK spec/traits, isAssociativeArray, `__traits(isAssociativeArray, T)`)
7112  */
7113 enum bool isAssociativeArray(T) = __traits(isAssociativeArray, T);
7114 
7115 ///
7116 @safe unittest
7117 {
7118     struct S;
7119 
7120     static assert( isAssociativeArray!(int[string]));
7121     static assert( isAssociativeArray!(S[S]));
7122     static assert(!isAssociativeArray!(string[]));
7123     static assert(!isAssociativeArray!S);
7124     static assert(!isAssociativeArray!(int[4]));
7125 }
7126 
7127 @safe unittest
7128 {
7129     struct Foo
7130     {
7131         @property uint[] keys()   { return null; }
7132         @property uint[] values() { return null; }
7133     }
7134 
7135     static foreach (T; AliasSeq!(int[int], int[string], immutable(char[5])[int]))
7136     {
7137         static foreach (Q; TypeQualifierList)
7138         {
7139             static assert( isAssociativeArray!(Q!T));
7140             static assert(!isAssociativeArray!(SubTypeOf!(Q!T)));
7141         }
7142     }
7143 
7144     static assert(!isAssociativeArray!Foo);
7145     static assert(!isAssociativeArray!int);
7146     static assert(!isAssociativeArray!(int[]));
7147     static assert(!isAssociativeArray!(typeof(null)));
7148 
7149     //enum EAA : int[int] { a = [1:1], b = [2:2] }
7150     //static assert( isAssociativeArray!EAA);
7151 }
7152 
7153 /**
7154  * Detect whether type `T` is a builtin type.
7155  */
7156 enum bool isBuiltinType(T) = is(BuiltinTypeOf!T) && !isAggregateType!T;
7157 
7158 ///
7159 @safe unittest
7160 {
7161     class C;
7162     union U;
7163     struct S;
7164     interface I;
7165 
7166     static assert( isBuiltinType!void);
7167     static assert( isBuiltinType!string);
7168     static assert( isBuiltinType!(int[]));
7169     static assert( isBuiltinType!(C[string]));
7170     static assert( isBuiltinType!(typeof(null)));
7171     static assert(!isBuiltinType!C);
7172     static assert(!isBuiltinType!U);
7173     static assert(!isBuiltinType!S);
7174     static assert(!isBuiltinType!I);
7175     static assert(!isBuiltinType!(void delegate(int)));
7176 }
7177 
7178 /**
7179  * Detect whether type `T` is a SIMD vector type.
7180  */
7181 enum bool isSIMDVector(T) = is(T : __vector(V[N]), V, size_t N);
7182 
7183 ///
7184 @safe unittest
7185 {
7186     static if (is(__vector(float[4])))
7187     {
7188         alias SimdVec = __vector(float[4]);
7189         static assert(isSIMDVector!(__vector(float[4])));
7190         static assert(isSIMDVector!SimdVec);
7191     }
7192     static assert(!isSIMDVector!uint);
7193     static assert(!isSIMDVector!(float[4]));
7194 }
7195 
7196 /**
7197  * Detect whether type `T` is a pointer.
7198  */
7199 enum bool isPointer(T) = is(T == U*, U);
7200 
7201 ///
7202 @safe unittest
7203 {
7204     void fun();
7205 
7206     static assert( isPointer!(int*));
7207     static assert( isPointer!(int function()));
7208     static assert(!isPointer!int);
7209     static assert(!isPointer!string);
7210     static assert(!isPointer!(typeof(null)));
7211     static assert(!isPointer!(typeof(fun)));
7212     static assert(!isPointer!(int delegate()));
7213 }
7214 
7215 @safe unittest
7216 {
7217     static foreach (T; AliasSeq!(int*, void*, char[]*))
7218     {
7219         static foreach (Q; TypeQualifierList)
7220         {
7221             static assert( isPointer!(Q!T));
7222             static assert(!isPointer!(SubTypeOf!(Q!T)));
7223         }
7224     }
7225 
7226     static assert(!isPointer!uint);
7227     static assert(!isPointer!(uint[uint]));
7228     static assert(!isPointer!(char[]));
7229     static assert(!isPointer!(typeof(null)));
7230 }
7231 
7232 /**
7233 Returns the target type of a pointer.
7234 */
7235 alias PointerTarget(T : T*) = T;
7236 
7237 ///
7238 @safe unittest
7239 {
7240     static assert(is(PointerTarget!(int*) == int));
7241     static assert(is(PointerTarget!(void*) == void));
7242 }
7243 
7244 /**
7245  * Detect whether type `T` is an aggregate type.
7246  */
7247 enum bool isAggregateType(T) = is(T == struct) || is(T == union) ||
7248                                is(T == class) || is(T == interface);
7249 
7250 ///
7251 @safe unittest
7252 {
7253     class C;
7254     union U;
7255     struct S;
7256     interface I;
7257 
7258     static assert( isAggregateType!C);
7259     static assert( isAggregateType!U);
7260     static assert( isAggregateType!S);
7261     static assert( isAggregateType!I);
7262     static assert(!isAggregateType!void);
7263     static assert(!isAggregateType!string);
7264     static assert(!isAggregateType!(int[]));
7265     static assert(!isAggregateType!(C[string]));
7266     static assert(!isAggregateType!(void delegate(int)));
7267 }
7268 
7269 /**
7270  * Returns `true` if T can be iterated over using a `foreach` loop with
7271  * a single loop variable of automatically inferred type, regardless of how
7272  * the `foreach` loop is implemented.  This includes ranges, structs/classes
7273  * that define `opApply` with a single loop variable, and builtin dynamic,
7274  * static and associative arrays.
7275  */
7276 enum bool isIterable(T) = is(typeof({ foreach (elem; T.init) {} }));
7277 
7278 ///
7279 @safe unittest
7280 {
7281     struct OpApply
7282     {
7283         int opApply(scope int delegate(ref uint) dg) { assert(0); }
7284     }
7285 
7286     struct Range
7287     {
7288         @property uint front() { assert(0); }
7289         void popFront() { assert(0); }
7290         enum bool empty = false;
7291     }
7292 
7293     static assert( isIterable!(uint[]));
7294     static assert( isIterable!OpApply);
7295     static assert( isIterable!(uint[string]));
7296     static assert( isIterable!Range);
7297 
7298     static assert(!isIterable!uint);
7299 }
7300 
7301 /**
7302  * Returns true if T is not const or immutable.  Note that isMutable is true for
7303  * string, or immutable(char)[], because the 'head' is mutable.
7304  */
7305 enum bool isMutable(T) = !is(T == const) && !is(T == immutable) && !is(T == inout);
7306 
7307 ///
7308 @safe unittest
7309 {
7310     static assert( isMutable!int);
7311     static assert( isMutable!string);
7312     static assert( isMutable!(shared int));
7313     static assert( isMutable!(shared const(int)[]));
7314 
7315     static assert(!isMutable!(const int));
7316     static assert(!isMutable!(inout int));
7317     static assert(!isMutable!(shared(const int)));
7318     static assert(!isMutable!(shared(inout int)));
7319     static assert(!isMutable!(immutable string));
7320 }
7321 
7322 /**
7323  * Returns true if T is an instance of the template S.
7324  */
7325 enum bool isInstanceOf(alias S, T) = is(T == S!Args, Args...);
7326 /// ditto
7327 template isInstanceOf(alias S, alias T)
7328 {
7329     enum impl(alias T : S!Args, Args...) = true;
7330     enum impl(alias T) = false;
7331     enum isInstanceOf = impl!T;
7332 }
7333 
7334 ///
7335 @safe unittest
7336 {
7337     static struct Foo(T...) { }
7338     static struct Bar(T...) { }
7339     static struct Doo(T) { }
7340     static struct ABC(int x) { }
7341     static void fun(T)() { }
7342     template templ(T) { }
7343 
7344     static assert(isInstanceOf!(Foo, Foo!int));
7345     static assert(!isInstanceOf!(Foo, Bar!int));
7346     static assert(!isInstanceOf!(Foo, int));
7347     static assert(isInstanceOf!(Doo, Doo!int));
7348     static assert(isInstanceOf!(ABC, ABC!1));
7349     static assert(!isInstanceOf!(Foo, Foo));
7350     static assert(isInstanceOf!(fun, fun!int));
7351     static assert(isInstanceOf!(templ, templ!int));
7352 }
7353 
7354 /**
7355  * To use `isInstanceOf` to check the identity of a template while inside of said
7356  * template, use $(LREF TemplateOf).
7357  */
7358 @safe unittest
7359 {
7360     static struct A(T = void)
7361     {
7362         // doesn't work as expected, only accepts A when T = void
7363         void func(B)(B b) if (isInstanceOf!(A, B)) {}
7364 
7365         // correct behavior
7366         void method(B)(B b) if (isInstanceOf!(TemplateOf!(A), B)) {}
7367     }
7368 
7369     A!(void) a1;
7370     A!(void) a2;
7371     A!(int) a3;
7372 
7373     static assert(!__traits(compiles, a1.func(a3)));
7374     static assert( __traits(compiles, a1.method(a2)));
7375     static assert( __traits(compiles, a1.method(a3)));
7376 }
7377 
7378 @safe unittest
7379 {
7380     static void fun1(T)() { }
7381     static void fun2(T)() { }
7382     template templ1(T) { }
7383     template templ2(T) { }
7384 
7385     static assert(!isInstanceOf!(fun1, fun2!int));
7386     static assert(!isInstanceOf!(templ1, templ2!int));
7387 }
7388 
7389 /**
7390  * Check whether the tuple T is an expression tuple.
7391  * An expression tuple only contains expressions.
7392  *
7393  * See_Also: $(LREF isTypeTuple).
7394  */
7395 template isExpressions(T...)
7396 {
7397     static foreach (Ti; T)
7398     {
7399         static if (!is(typeof(isExpressions) == bool) && // not yet defined
7400                    (is(Ti) || !__traits(compiles, { auto ex = Ti; })))
7401         {
7402             enum isExpressions = false;
7403         }
7404     }
7405     static if (!is(typeof(isExpressions) == bool)) // if not yet defined
7406     {
7407         enum isExpressions = true;
7408     }
7409 }
7410 
7411 ///
7412 @safe unittest
7413 {
7414     static assert(isExpressions!(1, 2.0, "a"));
7415     static assert(!isExpressions!(int, double, string));
7416     static assert(!isExpressions!(int, 2.0, "a"));
7417 }
7418 
7419 /**
7420  * Alternate name for $(LREF isExpressions), kept for legacy compatibility.
7421  */
7422 
7423 alias isExpressionTuple = isExpressions;
7424 
7425 @safe unittest
7426 {
7427     void foo();
7428     static int bar() { return 42; }
7429     immutable aa = [ 1: -1 ];
7430     alias myint = int;
7431 
7432     static assert( isExpressionTuple!(42));
7433     static assert( isExpressionTuple!aa);
7434     static assert( isExpressionTuple!("cattywampus", 2.7, aa));
7435     static assert( isExpressionTuple!(bar()));
7436 
7437     static assert(!isExpressionTuple!isExpressionTuple);
7438     static assert(!isExpressionTuple!foo);
7439     static assert(!isExpressionTuple!( (a) { } ));
7440     static assert(!isExpressionTuple!int);
7441     static assert(!isExpressionTuple!myint);
7442 }
7443 
7444 
7445 /**
7446  * Check whether the tuple `T` is a type tuple.
7447  * A type tuple only contains types.
7448  *
7449  * See_Also: $(LREF isExpressions).
7450  */
7451 enum isTypeTuple(T...) =
7452 {
7453     static foreach (U; T)
7454         static if (!is(U))
7455             if (__ctfe)
7456                 return false;
7457     return true;
7458 }();
7459 
7460 ///
7461 @safe unittest
7462 {
7463     static assert(isTypeTuple!(int, float, string));
7464     static assert(!isTypeTuple!(1, 2.0, "a"));
7465     static assert(!isTypeTuple!(1, double, string));
7466 }
7467 
7468 @safe unittest
7469 {
7470     class C {}
7471     void func(int) {}
7472     auto c = new C;
7473     enum CONST = 42;
7474 
7475     static assert( isTypeTuple!int);
7476     static assert( isTypeTuple!string);
7477     static assert( isTypeTuple!C);
7478     static assert( isTypeTuple!(typeof(func)));
7479     static assert( isTypeTuple!(int, char, double));
7480 
7481     static assert(!isTypeTuple!c);
7482     static assert(!isTypeTuple!isTypeTuple);
7483     static assert(!isTypeTuple!CONST);
7484 }
7485 
7486 
7487 /**
7488 Detect whether symbol or type `T` is a function pointer.
7489  */
7490 enum bool isFunctionPointer(alias T) = is(typeof(*T) == function);
7491 
7492 ///
7493 @safe unittest
7494 {
7495     static void foo() {}
7496     void bar() {}
7497 
7498     auto fpfoo = &foo;
7499     static assert( isFunctionPointer!fpfoo);
7500     static assert( isFunctionPointer!(void function()));
7501 
7502     auto dgbar = &bar;
7503     static assert(!isFunctionPointer!dgbar);
7504     static assert(!isFunctionPointer!(void delegate()));
7505     static assert(!isFunctionPointer!foo);
7506     static assert(!isFunctionPointer!bar);
7507 
7508     static assert( isFunctionPointer!((int a) {}));
7509 }
7510 
7511 /**
7512 Detect whether symbol or type `T` is a delegate.
7513 */
7514 enum bool isDelegate(alias T) = is(typeof(T) == delegate) || is(T == delegate);
7515 
7516 ///
7517 @safe unittest
7518 {
7519     static void sfunc() { }
7520     int x;
7521     void func() { x++; }
7522 
7523     int delegate() dg;
7524     assert(isDelegate!dg);
7525     assert(isDelegate!(int delegate()));
7526     assert(isDelegate!(typeof(&func)));
7527 
7528     int function() fp;
7529     assert(!isDelegate!fp);
7530     assert(!isDelegate!(int function()));
7531     assert(!isDelegate!(typeof(&sfunc)));
7532 }
7533 
7534 /**
7535 Detect whether symbol or type `T` is a function, a function pointer or a delegate.
7536 
7537 Params:
7538     T = The type to check
7539 Returns:
7540     A `bool`
7541  */
7542 enum bool isSomeFunction(alias T) =
7543     is(T == return) ||
7544     is(typeof(T) == return) ||
7545     is(typeof(&T) == return); // @property
7546 
7547 ///
7548 @safe unittest
7549 {
7550     static real func(ref int) { return 0; }
7551     static void prop() @property { }
7552     class C
7553     {
7554         real method(ref int) { return 0; }
7555         real prop() @property { return 0; }
7556     }
7557     auto c = new C;
7558     auto fp = &func;
7559     auto dg = &c.method;
7560 
7561     static assert( isSomeFunction!func);
7562     static assert( isSomeFunction!prop);
7563     static assert( isSomeFunction!(C.method));
7564     static assert( isSomeFunction!(C.prop));
7565     static assert( isSomeFunction!(c.prop));
7566     static assert( isSomeFunction!fp);
7567     static assert( isSomeFunction!dg);
7568 
7569     real val;
7570     static assert(!isSomeFunction!int);
7571     static assert(!isSomeFunction!val);
7572 }
7573 
7574 @safe unittest
7575 {
7576     void nestedFunc() { }
7577     void nestedProp() @property { }
7578     static assert(isSomeFunction!nestedFunc);
7579     static assert(isSomeFunction!nestedProp);
7580     static assert(isSomeFunction!(real function(ref int)));
7581     static assert(isSomeFunction!(real delegate(ref int)));
7582     static assert(isSomeFunction!((int a) { return a; }));
7583     static assert(!isSomeFunction!isSomeFunction);
7584 }
7585 
7586 /**
7587 Detect whether `T` is a callable object, which can be called with the
7588 function call operator `$(LPAREN)...$(RPAREN)`.
7589  */
7590 template isCallable(alias callable)
7591 {
7592     static if (is(typeof(&callable.opCall) == delegate))
7593         // T is a object which has a member function opCall().
7594         enum bool isCallable = true;
7595     else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
7596         // T is a type which has a static member function opCall().
7597         enum bool isCallable = true;
7598     else static if (is(typeof(&callable.opCall!()) TemplateInstanceType))
7599     {
7600         enum bool isCallable = isCallable!TemplateInstanceType;
7601     }
7602     else static if (is(typeof(&callable!()) TemplateInstanceType))
7603     {
7604         enum bool isCallable = isCallable!TemplateInstanceType;
7605     }
7606     else
7607     {
7608         enum bool isCallable = isSomeFunction!callable;
7609     }
7610 }
7611 
7612 /// Functions, lambdas, and aggregate types with (static) opCall.
7613 @safe unittest
7614 {
7615     void f() { }
7616     int g(int x) { return x; }
7617 
7618     static assert( isCallable!f);
7619     static assert( isCallable!g);
7620 
7621     class C { int opCall(int) { return 0; } }
7622     auto c = new C;
7623     struct S { static int opCall(int) { return 0; } }
7624     interface I { real value() @property; }
7625 
7626     static assert( isCallable!c);
7627     static assert( isCallable!(c.opCall));
7628     static assert( isCallable!S);
7629     static assert( isCallable!(I.value));
7630     static assert( isCallable!((int a) { return a; }));
7631 
7632     static assert(!isCallable!I);
7633 }
7634 
7635 /// Templates
7636 @safe unittest
7637 {
7638     void f()() { }
7639     T g(T = int)(T x) { return x; }
7640     struct S1 { static void opCall()() { } }
7641     struct S2 { static T opCall(T = int)(T x) {return x; } }
7642 
7643     static assert( isCallable!f);
7644     static assert( isCallable!g);
7645     static assert( isCallable!S1);
7646     static assert( isCallable!S2);
7647 }
7648 
7649 /// Overloaded functions and function templates.
7650 @safe unittest
7651 {
7652     static struct Wrapper
7653     {
7654         void f() { }
7655         int f(int x) { return x; }
7656 
7657         void g()() { }
7658         T g(T = int)(T x) { return x; }
7659     }
7660 
7661     static assert(isCallable!(Wrapper.f));
7662     static assert(isCallable!(Wrapper.g));
7663 }
7664 
7665 
7666 /**
7667 Detect whether `S` is an abstract function.
7668 
7669 See also: $(DDSUBLINK spec/traits, isAbstractFunction, `__traits(isAbstractFunction, S)`)
7670 Params:
7671     S = The symbol to check
7672 Returns:
7673     A `bool`
7674  */
7675 enum isAbstractFunction(alias S) = __traits(isAbstractFunction, S);
7676 
7677 ///
7678 @safe unittest
7679 {
7680     struct S { void foo() { } }
7681     class C { void foo() { } }
7682     class AC { abstract void foo(); }
7683     static assert(!isAbstractFunction!(int));
7684     static assert(!isAbstractFunction!(S.foo));
7685     static assert(!isAbstractFunction!(C.foo));
7686     static assert( isAbstractFunction!(AC.foo));
7687 }
7688 
7689 /**
7690  * Detect whether `S` is a final function.
7691  *
7692  * See also: $(DDSUBLINK spec/traits, isFinalFunction, `__traits(isFinalFunction, S)`)
7693  */
7694 enum isFinalFunction(alias S) = __traits(isFinalFunction, S);
7695 
7696 ///
7697 @safe unittest
7698 {
7699     struct S { void bar() { } }
7700     final class FC { void foo(); }
7701     class C
7702     {
7703         void bar() { }
7704         final void foo();
7705     }
7706     static assert(!isFinalFunction!(int));
7707     static assert(!isFinalFunction!(S.bar));
7708     static assert( isFinalFunction!(FC.foo));
7709     static assert(!isFinalFunction!(C.bar));
7710     static assert( isFinalFunction!(C.foo));
7711 }
7712 
7713 /**
7714 Determines if `f` is a function that requires a context pointer.
7715 
7716 Params:
7717     f = The type to check
7718 Returns
7719     A `bool`
7720 */
7721 template isNestedFunction(alias f)
7722 {
7723     enum isNestedFunction = __traits(isNested, f) && isSomeFunction!(f);
7724 }
7725 
7726 ///
7727 @safe unittest
7728 {
7729     static void f() {}
7730     static void fun()
7731     {
7732         int i;
7733         int f() { return i; }
7734 
7735         static assert(isNestedFunction!(f));
7736     }
7737 
7738     static assert(!isNestedFunction!f);
7739 }
7740 
7741 // https://issues.dlang.org/show_bug.cgi?id=18669
7742 @safe unittest
7743 {
7744     static class Outer
7745     {
7746         class Inner
7747         {
7748         }
7749     }
7750     int i;
7751     struct SS
7752     {
7753         int bar() { return i; }
7754     }
7755     static assert(!isNestedFunction!(Outer.Inner));
7756     static assert(!isNestedFunction!(SS));
7757 }
7758 
7759 /**
7760  * Detect whether `S` is an abstract class.
7761  *
7762  * See also: $(DDSUBLINK spec/traits, isAbstractClass, `__traits(isAbstractClass, S)`)
7763  */
7764 enum isAbstractClass(alias S) = __traits(isAbstractClass, S);
7765 
7766 ///
7767 @safe unittest
7768 {
7769     struct S { }
7770     class C { }
7771     abstract class AC { }
7772     static assert(!isAbstractClass!S);
7773     static assert(!isAbstractClass!C);
7774     static assert( isAbstractClass!AC);
7775     C c;
7776     static assert(!isAbstractClass!c);
7777     AC ac;
7778     static assert( isAbstractClass!ac);
7779 }
7780 
7781 /**
7782  * Detect whether `S` is a final class.
7783  *
7784  * See also: $(DDSUBLINK spec/traits, isFinalClass, `__traits(isFinalClass, S)`)
7785  */
7786 enum isFinalClass(alias S) = __traits(isFinalClass, S);
7787 
7788 ///
7789 @safe unittest
7790 {
7791     class C { }
7792     abstract class AC { }
7793     final class FC1 : C { }
7794     final class FC2 { }
7795     static assert(!isFinalClass!C);
7796     static assert(!isFinalClass!AC);
7797     static assert( isFinalClass!FC1);
7798     static assert( isFinalClass!FC2);
7799     C c;
7800     static assert(!isFinalClass!c);
7801     FC1 fc1;
7802     static assert( isFinalClass!fc1);
7803 }
7804 
7805 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7806 // General Types
7807 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
7808 
7809 version (StdDdoc)
7810 {
7811     /**
7812        Removes `const`, `inout` and `immutable` qualifiers, if any, from type `T`.
7813     */
7814     template Unconst(T)
7815     {
7816         import core.internal.traits : CoreUnconst = Unconst;
7817         alias Unconst = CoreUnconst!(T);
7818     }
7819 }
7820 else
7821 {
7822     import core.internal.traits : CoreUnconst = Unconst;
7823     alias Unconst = CoreUnconst;
7824 }
7825 
7826 ///
7827 @safe unittest
7828 {
7829     static assert(is(Unconst!int == int));
7830     static assert(is(Unconst!(const int) == int));
7831     static assert(is(Unconst!(immutable int) == int));
7832     static assert(is(Unconst!(shared int) == shared int));
7833     static assert(is(Unconst!(shared(const int)) == shared int));
7834 }
7835 
7836 @safe unittest
7837 {
7838     static assert(is(Unconst!(                   int) == int));
7839     static assert(is(Unconst!(             const int) == int));
7840     static assert(is(Unconst!(       inout       int) == int));
7841     static assert(is(Unconst!(       inout const int) == int));
7842     static assert(is(Unconst!(shared             int) == shared int));
7843     static assert(is(Unconst!(shared       const int) == shared int));
7844     static assert(is(Unconst!(shared inout       int) == shared int));
7845     static assert(is(Unconst!(shared inout const int) == shared int));
7846     static assert(is(Unconst!(         immutable int) == int));
7847 
7848     alias ImmIntArr = immutable(int[]);
7849     static assert(is(Unconst!ImmIntArr == immutable(int)[]));
7850 }
7851 
7852 /++
7853     Removes `shared` qualifier, if any, from type `T`.
7854 
7855     Note that while `immutable` is implicitly `shared`, it is unaffected by
7856     Unshared. Only explict `shared` is removed.
7857   +/
7858 template Unshared(T)
7859 {
7860     static if (is(T == shared U, U))
7861         alias Unshared = U;
7862     else
7863         alias Unshared = T;
7864 }
7865 
7866 ///
7867 @safe unittest
7868 {
7869     static assert(is(Unshared!int == int));
7870     static assert(is(Unshared!(const int) == const int));
7871     static assert(is(Unshared!(immutable int) == immutable int));
7872 
7873     static assert(is(Unshared!(shared int) == int));
7874     static assert(is(Unshared!(shared(const int)) == const int));
7875 
7876     static assert(is(Unshared!(shared(int[])) == shared(int)[]));
7877 }
7878 
7879 @safe unittest
7880 {
7881     static assert(is(Unshared!(                   int) == int));
7882     static assert(is(Unshared!(             const int) == const int));
7883     static assert(is(Unshared!(       inout       int) == inout int));
7884     static assert(is(Unshared!(       inout const int) == inout const int));
7885     static assert(is(Unshared!(shared             int) == int));
7886     static assert(is(Unshared!(shared       const int) == const int));
7887     static assert(is(Unshared!(shared inout       int) == inout int));
7888     static assert(is(Unshared!(shared inout const int) == inout const int));
7889     static assert(is(Unshared!(         immutable int) == immutable int));
7890 }
7891 
7892 version (StdDdoc)
7893 {
7894     /**
7895        Removes all qualifiers, if any, from type `T`.
7896     */
7897     template Unqual(T)
7898     {
7899         import core.internal.traits : CoreUnqual = Unqual;
7900         alias Unqual = CoreUnqual!(T);
7901     }
7902 }
7903 else
7904 {
7905     import core.internal.traits : CoreUnqual = Unqual;
7906     alias Unqual = CoreUnqual;
7907 }
7908 
7909 ///
7910 @safe unittest
7911 {
7912     static assert(is(Unqual!int == int));
7913     static assert(is(Unqual!(const int) == int));
7914     static assert(is(Unqual!(immutable int) == int));
7915     static assert(is(Unqual!(shared int) == int));
7916     static assert(is(Unqual!(shared(const int)) == int));
7917 }
7918 
7919 @safe unittest
7920 {
7921     static assert(is(Unqual!(                   int) == int));
7922     static assert(is(Unqual!(             const int) == int));
7923     static assert(is(Unqual!(       inout       int) == int));
7924     static assert(is(Unqual!(       inout const int) == int));
7925     static assert(is(Unqual!(shared             int) == int));
7926     static assert(is(Unqual!(shared       const int) == int));
7927     static assert(is(Unqual!(shared inout       int) == int));
7928     static assert(is(Unqual!(shared inout const int) == int));
7929     static assert(is(Unqual!(         immutable int) == int));
7930 
7931     alias ImmIntArr = immutable(int[]);
7932     static assert(is(Unqual!ImmIntArr == immutable(int)[]));
7933 }
7934 
7935 // [For internal use]
7936 package template ModifyTypePreservingTQ(alias Modifier, T)
7937 {
7938     import core.internal.traits : _ModifyTypePreservingTQ = ModifyTypePreservingTQ;
7939     alias ModifyTypePreservingTQ = _ModifyTypePreservingTQ!(Modifier, T);
7940 }
7941 
7942 /**
7943  * Copies type qualifiers from `FromType` to `ToType`.
7944  *
7945  * Supported type qualifiers:
7946  * $(UL
7947  *     $(LI `const`)
7948  *     $(LI `inout`)
7949  *     $(LI `immutable`)
7950  *     $(LI `shared`)
7951  * )
7952  */
7953 template CopyTypeQualifiers(FromType, ToType)
7954 {
7955     alias T(U) = ToType;
7956     alias CopyTypeQualifiers = ModifyTypePreservingTQ!(T, FromType);
7957 }
7958 
7959 ///
7960 @safe unittest
7961 {
7962     static assert(is(CopyTypeQualifiers!(inout const real, int) == inout const int));
7963 }
7964 
7965 @safe unittest
7966 {
7967     static assert(is(CopyTypeQualifiers!(                   real, int) ==                    int));
7968     static assert(is(CopyTypeQualifiers!(             const real, int) ==              const int));
7969     static assert(is(CopyTypeQualifiers!(       inout       real, int) ==        inout       int));
7970     static assert(is(CopyTypeQualifiers!(       inout const real, int) ==        inout const int));
7971     static assert(is(CopyTypeQualifiers!(shared             real, int) == shared             int));
7972     static assert(is(CopyTypeQualifiers!(shared       const real, int) == shared       const int));
7973     static assert(is(CopyTypeQualifiers!(shared inout       real, int) == shared inout       int));
7974     static assert(is(CopyTypeQualifiers!(shared inout const real, int) == shared inout const int));
7975     static assert(is(CopyTypeQualifiers!(         immutable real, int) ==          immutable int));
7976 }
7977 
7978 /**
7979 Returns the type of `ToType` with the "constness" of `FromType`. A type's $(B constness)
7980 refers to whether it is `const`, `immutable`, or `inout`. If `FromType` has no constness, the
7981 returned type will be the same as `ToType`.
7982 */
7983 template CopyConstness(FromType, ToType)
7984 {
7985     alias Unshared(T) = T;
7986     alias Unshared(T: shared U, U) = U;
7987 
7988     alias CopyConstness = Unshared!(CopyTypeQualifiers!(FromType, ToType));
7989 }
7990 
7991 ///
7992 @safe unittest
7993 {
7994     const(int) i;
7995     CopyConstness!(typeof(i), float) f;
7996     assert( is(typeof(f) == const float));
7997 
7998     CopyConstness!(char, uint) u;
7999     assert( is(typeof(u) == uint));
8000 
8001     //The 'shared' qualifier will not be copied
8002     assert(!is(CopyConstness!(shared bool, int) == shared int));
8003 
8004     //But the constness will be
8005     assert( is(CopyConstness!(shared const real, double) == const double));
8006 
8007     //Careful, const(int)[] is a mutable array of const(int)
8008     alias MutT = CopyConstness!(const(int)[], int);
8009     assert(!is(MutT == const(int)));
8010 
8011     //Okay, const(int[]) applies to array and contained ints
8012     alias CstT = CopyConstness!(const(int[]), int);
8013     assert( is(CstT == const(int)));
8014 }
8015 
8016 @safe unittest
8017 {
8018     struct Test
8019     {
8020         void method1() {}
8021         void method2() const {}
8022         void method3() immutable {}
8023     }
8024 
8025     assert(is(CopyConstness!(typeof(Test.method1), real) == real));
8026 
8027     assert(is(CopyConstness!(typeof(Test.method2), byte) == const(byte)));
8028 
8029     assert(is(CopyConstness!(typeof(Test.method3), string) == immutable(string)));
8030 }
8031 
8032 @safe unittest
8033 {
8034     assert(is(CopyConstness!(inout(int)[], int[]) == int[]));
8035     assert(is(CopyConstness!(inout(int[]), int[]) == inout(int[])));
8036 }
8037 
8038 @safe unittest
8039 {
8040     static assert(is(CopyConstness!(                   int, real) ==             real));
8041     static assert(is(CopyConstness!(const              int, real) ==       const real));
8042     static assert(is(CopyConstness!(inout              int, real) ==       inout real));
8043     static assert(is(CopyConstness!(inout const        int, real) == inout const real));
8044     static assert(is(CopyConstness!(shared             int, real) ==             real));
8045     static assert(is(CopyConstness!(shared const       int, real) ==       const real));
8046     static assert(is(CopyConstness!(shared inout       int, real) == inout       real));
8047     static assert(is(CopyConstness!(shared inout const int, real) == inout const real));
8048     static assert(is(CopyConstness!(immutable          int, real) ==   immutable real));
8049 }
8050 
8051 /**
8052 Returns the inferred type of the loop variable when a variable of type T
8053 is iterated over using a `foreach` loop with a single loop variable and
8054 automatically inferred return type.  Note that this may not be the same as
8055 `std.range.ElementType!Range` in the case of narrow strings, or if T
8056 has both opApply and a range interface.
8057 */
8058 template ForeachType(T)
8059 {
8060     alias ForeachType = typeof(
8061     (inout int x = 0)
8062     {
8063         foreach (elem; T.init)
8064         {
8065             return elem;
8066         }
8067         assert(0);
8068     }());
8069 }
8070 
8071 ///
8072 @safe unittest
8073 {
8074     static assert(is(ForeachType!(uint[]) == uint));
8075     static assert(is(ForeachType!string == immutable(char)));
8076     static assert(is(ForeachType!(string[string]) == string));
8077     static assert(is(ForeachType!(inout(int)[]) == inout(int)));
8078 }
8079 
8080 
8081 /**
8082  * Strips off all `enum`s from type `T`.
8083  */
8084 template OriginalType(T)
8085 {
8086     import core.internal.traits : _OriginalType = OriginalType;
8087     alias OriginalType = _OriginalType!T;
8088 }
8089 
8090 ///
8091 @safe unittest
8092 {
8093     enum E : real { a = 0 } // NOTE: explicit initialization to 0 required during Enum init deprecation cycle
8094     enum F : E    { a = E.a }
8095     alias G = const(F);
8096     static assert(is(OriginalType!E == real));
8097     static assert(is(OriginalType!F == real));
8098     static assert(is(OriginalType!G == const real));
8099 }
8100 
8101 /**
8102  * Get the Key type of an Associative Array.
8103  */
8104 alias KeyType(V : V[K], K) = K;
8105 
8106 ///
8107 @safe unittest
8108 {
8109     alias Hash = int[string];
8110     static assert(is(KeyType!Hash == string));
8111     static assert(is(ValueType!Hash == int));
8112     KeyType!Hash str = "a"; // str is declared as string
8113     ValueType!Hash num = 1; // num is declared as int
8114 }
8115 
8116 /**
8117  * Get the Value type of an Associative Array.
8118  */
8119 alias ValueType(V : V[K], K) = V;
8120 
8121 ///
8122 @safe unittest
8123 {
8124     alias Hash = int[string];
8125     static assert(is(KeyType!Hash == string));
8126     static assert(is(ValueType!Hash == int));
8127     KeyType!Hash str = "a"; // str is declared as string
8128     ValueType!Hash num = 1; // num is declared as int
8129 }
8130 
8131 /**
8132 Params:
8133     T = A built in integral or vector type.
8134 
8135 Returns:
8136     The corresponding unsigned numeric type for `T` with the
8137     same type qualifiers.
8138 
8139     If `T` is not a integral or vector, a compile-time error is given.
8140  */
8141 template Unsigned(T)
8142 {
8143     template Impl(T)
8144     {
8145         static if (is(T : __vector(V[N]), V, size_t N))
8146             alias Impl = __vector(Impl!V[N]);
8147         else static if (isUnsigned!T)
8148             alias Impl = T;
8149         else static if (isSigned!T && !isFloatingPoint!T)
8150         {
8151             static if (is(T == byte )) alias Impl = ubyte;
8152             static if (is(T == short)) alias Impl = ushort;
8153             static if (is(T == int  )) alias Impl = uint;
8154             static if (is(T == long )) alias Impl = ulong;
8155             static if (is(ucent) && is(T == cent )) alias Impl = ucent;
8156         }
8157         else
8158             static assert(false, "Type " ~ T.stringof ~
8159                                  " does not have an Unsigned counterpart");
8160     }
8161 
8162     alias Unsigned = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8163 }
8164 
8165 ///
8166 @safe unittest
8167 {
8168     static assert(is(Unsigned!(int) == uint));
8169     static assert(is(Unsigned!(long) == ulong));
8170     static assert(is(Unsigned!(const short) == const ushort));
8171     static assert(is(Unsigned!(immutable byte) == immutable ubyte));
8172     static assert(is(Unsigned!(inout int) == inout uint));
8173 }
8174 
8175 
8176 /// Unsigned types are forwarded
8177 @safe unittest
8178 {
8179     static assert(is(Unsigned!(uint) == uint));
8180     static assert(is(Unsigned!(const uint) == const uint));
8181 
8182     static assert(is(Unsigned!(ubyte) == ubyte));
8183     static assert(is(Unsigned!(immutable uint) == immutable uint));
8184 }
8185 
8186 @safe unittest
8187 {
8188     alias U1 = Unsigned!int;
8189     alias U2 = Unsigned!(const(int));
8190     alias U3 = Unsigned!(immutable(int));
8191     static assert(is(U1 == uint));
8192     static assert(is(U2 == const(uint)));
8193     static assert(is(U3 == immutable(uint)));
8194     static if (is(__vector(int[4])) && is(__vector(uint[4])))
8195     {
8196         alias UV1 = Unsigned!(__vector(int[4]));
8197         alias UV2 = Unsigned!(const(__vector(int[4])));
8198         static assert(is(UV1 == __vector(uint[4])));
8199         static assert(is(UV2 == const(__vector(uint[4]))));
8200     }
8201     //struct S {}
8202     //alias U2 = Unsigned!S;
8203     //alias U3 = Unsigned!double;
8204     static if (is(ucent))
8205     {
8206         alias U4 = Unsigned!cent;
8207         alias U5 = Unsigned!(const(cent));
8208         alias U6 = Unsigned!(immutable(cent));
8209         static assert(is(U4 == ucent));
8210         static assert(is(U5 == const(ucent)));
8211         static assert(is(U6 == immutable(ucent)));
8212     }
8213 }
8214 
8215 /**
8216 Returns the largest type, i.e. T such that T.sizeof is the largest.  If more
8217 than one type is of the same size, the leftmost argument of these in will be
8218 returned.
8219 */
8220 template Largest(T...)
8221 if (T.length >= 1)
8222 {
8223     alias Largest = T[0];
8224     static foreach (U; T[1 .. $])
8225         Largest = Select!(U.sizeof > Largest.sizeof, U, Largest);
8226 }
8227 
8228 ///
8229 @safe unittest
8230 {
8231     static assert(is(Largest!(uint, ubyte, ushort, real) == real));
8232     static assert(is(Largest!(ulong, double) == ulong));
8233     static assert(is(Largest!(double, ulong) == double));
8234     static assert(is(Largest!(uint, byte, double, short) == double));
8235     static if (is(ucent))
8236         static assert(is(Largest!(uint, ubyte, ucent, ushort) == ucent));
8237 }
8238 
8239 /**
8240 Returns the corresponding signed type for T. T must be a numeric integral type,
8241 otherwise a compile-time error occurs.
8242  */
8243 template Signed(T)
8244 {
8245     template Impl(T)
8246     {
8247         static if (is(T : __vector(V[N]), V, size_t N))
8248             alias Impl = __vector(Impl!V[N]);
8249         else static if (isSigned!T)
8250             alias Impl = T;
8251         else static if (isUnsigned!T)
8252         {
8253             static if (is(T == ubyte )) alias Impl = byte;
8254             static if (is(T == ushort)) alias Impl = short;
8255             static if (is(T == uint  )) alias Impl = int;
8256             static if (is(T == ulong )) alias Impl = long;
8257             static if (is(ucent) && is(T == ucent )) alias Impl = cent;
8258         }
8259         else
8260             static assert(false, "Type " ~ T.stringof ~
8261                                  " does not have an Signed counterpart");
8262     }
8263 
8264     alias Signed = ModifyTypePreservingTQ!(Impl, OriginalType!T);
8265 }
8266 
8267 ///
8268 @safe unittest
8269 {
8270     alias S1 = Signed!uint;
8271     static assert(is(S1 == int));
8272     alias S2 = Signed!(const(uint));
8273     static assert(is(S2 == const(int)));
8274     alias S3 = Signed!(immutable(uint));
8275     static assert(is(S3 == immutable(int)));
8276     static if (is(ucent))
8277     {
8278         alias S4 = Signed!ucent;
8279         static assert(is(S4 == cent));
8280     }
8281 }
8282 
8283 @safe unittest
8284 {
8285     static assert(is(Signed!float == float));
8286     static if (is(__vector(int[4])) && is(__vector(uint[4])))
8287     {
8288         alias SV1 = Signed!(__vector(uint[4]));
8289         alias SV2 = Signed!(const(__vector(uint[4])));
8290         static assert(is(SV1 == __vector(int[4])));
8291         static assert(is(SV2 == const(__vector(int[4]))));
8292     }
8293 }
8294 
8295 
8296 /**
8297 Returns the most negative value of the numeric type T.
8298 */
8299 template mostNegative(T)
8300 if (isNumeric!T || isSomeChar!T || isBoolean!T)
8301 {
8302     static if (is(typeof(T.min_normal)))
8303         enum mostNegative = -T.max;
8304     else static if (T.min == 0)
8305         enum byte mostNegative = 0;
8306     else
8307         enum mostNegative = T.min;
8308 }
8309 
8310 ///
8311 @safe unittest
8312 {
8313     static assert(mostNegative!float == -float.max);
8314     static assert(mostNegative!double == -double.max);
8315     static assert(mostNegative!real == -real.max);
8316     static assert(mostNegative!bool == false);
8317 }
8318 
8319 ///
8320 @safe unittest
8321 {
8322     import std.meta : AliasSeq;
8323 
8324     static foreach (T; AliasSeq!(bool, byte, short, int, long))
8325         static assert(mostNegative!T == T.min);
8326 
8327     static foreach (T; AliasSeq!(ubyte, ushort, uint, ulong, char, wchar, dchar))
8328         static assert(mostNegative!T == 0);
8329 }
8330 
8331 /**
8332 Get the type that a scalar type `T` will $(LINK2 $(ROOT_DIR)spec/type.html#integer-promotions, promote)
8333 to in multi-term arithmetic expressions.
8334 */
8335 template Promoted(T)
8336 if (isScalarType!T)
8337 {
8338     alias Promoted = CopyTypeQualifiers!(T, typeof(T.init + T.init));
8339 }
8340 
8341 ///
8342 @safe unittest
8343 {
8344     ubyte a = 3, b = 5;
8345     static assert(is(typeof(a * b) == Promoted!ubyte));
8346     static assert(is(Promoted!ubyte == int));
8347 
8348     static assert(is(Promoted!(shared(bool)) == shared(int)));
8349     static assert(is(Promoted!(const(int)) == const(int)));
8350     static assert(is(Promoted!double == double));
8351 }
8352 
8353 @safe unittest
8354 {
8355     // promote to int:
8356     static foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, char, wchar))
8357     {
8358         static assert(is(Promoted!T == int));
8359         static assert(is(Promoted!(shared(const T)) == shared(const int)));
8360     }
8361 
8362     // already promoted:
8363     static foreach (T; AliasSeq!(int, uint, long, ulong, float, double, real))
8364     {
8365         static assert(is(Promoted!T == T));
8366         static assert(is(Promoted!(immutable(T)) == immutable(T)));
8367     }
8368 }
8369 
8370 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8371 // Misc.
8372 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::://
8373 
8374 /**
8375 Returns the mangled name of symbol or type `sth`.
8376 
8377 `mangledName` is the same as builtin `.mangleof` property, but
8378 might be more convenient in generic code, e.g. as a template argument
8379 when invoking staticMap.
8380  */
8381 enum mangledName(alias sth) = sth.mangleof;
8382 
8383 ///
8384 @safe unittest
8385 {
8386     import std.meta : AliasSeq;
8387     alias TL = staticMap!(mangledName, int, const int, immutable int);
8388     static assert(TL == AliasSeq!("i", "xi", "yi"));
8389 }
8390 
8391 version (StdUnittest) private void freeFunc(string);
8392 
8393 @safe unittest
8394 {
8395     class C { int value() @property { return 0; } }
8396     static assert(mangledName!int == int.mangleof);
8397     static assert(mangledName!C == C.mangleof);
8398     static assert(mangledName!(C.value) == C.value.mangleof);
8399     static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi");
8400     static assert(mangledName!mangledName == "3std6traits11mangledName");
8401     static assert(mangledName!freeFunc == "_D3std6traits8freeFuncFAyaZv");
8402     int x;
8403     // https://issues.dlang.org/show_bug.cgi?id=9148
8404   static if (is(typeof({ return x; }) : int delegate() pure))
8405     static assert(mangledName!((int a) { return a+x; }) == "DFNaNbNiNfiZi");  // pure nothrow @safe @nogc
8406   else
8407     static assert(mangledName!((int a) { return a+x; }) == "DFNbNiNfiZi");  // nothrow @safe @nnogc
8408 }
8409 
8410 @system unittest
8411 {
8412     // @system due to demangle
8413     // Test for https://issues.dlang.org/show_bug.cgi?id=5718
8414     import std.demangle : demangle;
8415     int foo;
8416     auto foo_demangled = demangle(mangledName!foo);
8417     assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo",
8418         foo_demangled);
8419 
8420     void bar();
8421     auto bar_demangled = demangle(mangledName!bar);
8422     assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()");
8423 }
8424 
8425 
8426 
8427 // XXX Select & select should go to another module. (functional or algorithm?)
8428 
8429 /**
8430 Aliases itself to `T[0]` if the boolean `condition` is `true`
8431 and to `T[1]` otherwise.
8432  */
8433 template Select(bool condition, T...)
8434 if (T.length == 2)
8435 {
8436     import std.meta : Alias;
8437     alias Select = Alias!(T[!condition]);
8438 }
8439 
8440 ///
8441 @safe unittest
8442 {
8443     // can select types
8444     static assert(is(Select!(true, int, long) == int));
8445     static assert(is(Select!(false, int, long) == long));
8446     static struct Foo {}
8447     static assert(is(Select!(false, const(int), const(Foo)) == const(Foo)));
8448 
8449     // can select symbols
8450     int a = 1;
8451     int b = 2;
8452     alias selA = Select!(true, a, b);
8453     alias selB = Select!(false, a, b);
8454     assert(selA == 1);
8455     assert(selB == 2);
8456 
8457     // can select (compile-time) expressions
8458     enum val = Select!(false, -4, 9 - 6);
8459     static assert(val == 3);
8460 }
8461 
8462 /**
8463 Select one of two functions to run via template parameter.
8464 
8465 Params:
8466     cond = A `bool` which determines which function is run
8467     a = The first function
8468     b = The second function
8469 
8470 Returns:
8471     `a` without evaluating `b` if `cond` is `true`.
8472     Otherwise, returns `b` without evaluating `a`.
8473  */
8474 A select(bool cond : true, A, B)(A a, lazy B b) { return a; }
8475 /// Ditto
8476 B select(bool cond : false, A, B)(lazy A a, B b) { return b; }
8477 
8478 ///
8479 @safe unittest
8480 {
8481     real run() { return 0; }
8482     int fail() { assert(0); }
8483     auto a = select!true(run(), fail());
8484     auto b = select!false(fail(), run());
8485     static assert(is(typeof(a) == real));
8486     static assert(is(typeof(b) == real));
8487 }
8488 
8489 /++
8490     Determine if a symbol has a given
8491     $(DDSUBLINK spec/attribute, uda, user-defined attribute).
8492 
8493     See_Also:
8494         $(LREF getUDAs)
8495   +/
8496 enum hasUDA(alias symbol, alias attribute) = getUDAs!(symbol, attribute).length != 0;
8497 
8498 ///
8499 @safe unittest
8500 {
8501     enum E;
8502     struct S {}
8503 
8504     @("alpha") int a;
8505     static assert(hasUDA!(a, "alpha"));
8506     static assert(!hasUDA!(a, S));
8507     static assert(!hasUDA!(a, E));
8508 
8509     @(E) int b;
8510     static assert(!hasUDA!(b, "alpha"));
8511     static assert(!hasUDA!(b, S));
8512     static assert(hasUDA!(b, E));
8513 
8514     @E int c;
8515     static assert(!hasUDA!(c, "alpha"));
8516     static assert(!hasUDA!(c, S));
8517     static assert(hasUDA!(c, E));
8518 
8519     @(S, E) int d;
8520     static assert(!hasUDA!(d, "alpha"));
8521     static assert(hasUDA!(d, S));
8522     static assert(hasUDA!(d, E));
8523 
8524     @S int e;
8525     static assert(!hasUDA!(e, "alpha"));
8526     static assert(hasUDA!(e, S));
8527     static assert(!hasUDA!(e, S()));
8528     static assert(!hasUDA!(e, E));
8529 
8530     @S() int f;
8531     static assert(!hasUDA!(f, "alpha"));
8532     static assert(hasUDA!(f, S));
8533     static assert(hasUDA!(f, S()));
8534     static assert(!hasUDA!(f, E));
8535 
8536     @(S, E, "alpha") int g;
8537     static assert(hasUDA!(g, "alpha"));
8538     static assert(hasUDA!(g, S));
8539     static assert(hasUDA!(g, E));
8540 
8541     @(100) int h;
8542     static assert(hasUDA!(h, 100));
8543 
8544     struct Named { string name; }
8545 
8546     @Named("abc") int i;
8547     static assert(hasUDA!(i, Named));
8548     static assert(hasUDA!(i, Named("abc")));
8549     static assert(!hasUDA!(i, Named("def")));
8550 
8551     struct AttrT(T)
8552     {
8553         string name;
8554         T value;
8555     }
8556 
8557     @AttrT!int("answer", 42) int j;
8558     static assert(hasUDA!(j, AttrT));
8559     static assert(hasUDA!(j, AttrT!int));
8560     static assert(!hasUDA!(j, AttrT!string));
8561 
8562     @AttrT!string("hello", "world") int k;
8563     static assert(hasUDA!(k, AttrT));
8564     static assert(!hasUDA!(k, AttrT!int));
8565     static assert(hasUDA!(k, AttrT!string));
8566 
8567     struct FuncAttr(alias f) { alias func = f; }
8568     static int fourtyTwo() { return 42; }
8569     static size_t getLen(string s) { return s.length; }
8570 
8571     @FuncAttr!getLen int l;
8572     static assert(hasUDA!(l, FuncAttr));
8573     static assert(!hasUDA!(l, FuncAttr!fourtyTwo));
8574     static assert(hasUDA!(l, FuncAttr!getLen));
8575     static assert(!hasUDA!(l, FuncAttr!fourtyTwo()));
8576     static assert(!hasUDA!(l, FuncAttr!getLen()));
8577 
8578     @FuncAttr!getLen() int m;
8579     static assert(hasUDA!(m, FuncAttr));
8580     static assert(!hasUDA!(m, FuncAttr!fourtyTwo));
8581     static assert(hasUDA!(m, FuncAttr!getLen));
8582     static assert(!hasUDA!(m, FuncAttr!fourtyTwo()));
8583     static assert(hasUDA!(m, FuncAttr!getLen()));
8584 }
8585 
8586 /++
8587     Gets the matching $(DDSUBLINK spec/attribute, uda, user-defined attributes)
8588     from the given symbol.
8589 
8590     If the UDA is a type, then any UDAs of the same type on the symbol will
8591     match. If the UDA is a template for a type, then any UDA which is an
8592     instantiation of that template will match. And if the UDA is a value,
8593     then any UDAs on the symbol which are equal to that value will match.
8594 
8595     See_Also:
8596         $(LREF hasUDA)
8597   +/
8598 template getUDAs(alias symbol, alias attribute)
8599 {
8600     import std.meta : Filter;
8601 
8602     alias getUDAs = Filter!(isDesiredUDA!attribute, __traits(getAttributes, symbol));
8603 }
8604 
8605 ///
8606 @safe unittest
8607 {
8608     struct Attr
8609     {
8610         string name;
8611         int value;
8612     }
8613 
8614     @Attr("Answer", 42) int a;
8615     static assert(getUDAs!(a, Attr).length == 1);
8616     static assert(getUDAs!(a, Attr)[0].name == "Answer");
8617     static assert(getUDAs!(a, Attr)[0].value == 42);
8618 
8619     @(Attr("Answer", 42), "string", 9999) int b;
8620     static assert(getUDAs!(b, Attr).length == 1);
8621     static assert(getUDAs!(b, Attr)[0].name == "Answer");
8622     static assert(getUDAs!(b, Attr)[0].value == 42);
8623 
8624     @Attr("Answer", 42) @Attr("Pi", 3) int c;
8625     static assert(getUDAs!(c, Attr).length == 2);
8626     static assert(getUDAs!(c, Attr)[0].name == "Answer");
8627     static assert(getUDAs!(c, Attr)[0].value == 42);
8628     static assert(getUDAs!(c, Attr)[1].name == "Pi");
8629     static assert(getUDAs!(c, Attr)[1].value == 3);
8630 
8631     static assert(getUDAs!(c, Attr("Answer", 42)).length == 1);
8632     static assert(getUDAs!(c, Attr("Answer", 42))[0].name == "Answer");
8633     static assert(getUDAs!(c, Attr("Answer", 42))[0].value == 42);
8634 
8635     static assert(getUDAs!(c, Attr("Answer", 99)).length == 0);
8636 
8637     struct AttrT(T)
8638     {
8639         string name;
8640         T value;
8641     }
8642 
8643     @AttrT!uint("Answer", 42) @AttrT!int("Pi", 3) @AttrT int d;
8644     static assert(getUDAs!(d, AttrT).length == 2);
8645     static assert(getUDAs!(d, AttrT)[0].name == "Answer");
8646     static assert(getUDAs!(d, AttrT)[0].value == 42);
8647     static assert(getUDAs!(d, AttrT)[1].name == "Pi");
8648     static assert(getUDAs!(d, AttrT)[1].value == 3);
8649 
8650     static assert(getUDAs!(d, AttrT!uint).length == 1);
8651     static assert(getUDAs!(d, AttrT!uint)[0].name == "Answer");
8652     static assert(getUDAs!(d, AttrT!uint)[0].value == 42);
8653 
8654     static assert(getUDAs!(d, AttrT!int).length == 1);
8655     static assert(getUDAs!(d, AttrT!int)[0].name == "Pi");
8656     static assert(getUDAs!(d, AttrT!int)[0].value == 3);
8657 
8658     struct SimpleAttr {}
8659 
8660     @SimpleAttr int e;
8661     static assert(getUDAs!(e, SimpleAttr).length == 1);
8662     static assert(is(getUDAs!(e, SimpleAttr)[0] == SimpleAttr));
8663 
8664     @SimpleAttr() int f;
8665     static assert(getUDAs!(f, SimpleAttr).length == 1);
8666     static assert(is(typeof(getUDAs!(f, SimpleAttr)[0]) == SimpleAttr));
8667 
8668     struct FuncAttr(alias f) { alias func = f; }
8669     static int add42(int v) { return v + 42; }
8670     static string concat(string l, string r) { return l ~ r; }
8671 
8672     @FuncAttr!add42 int g;
8673     static assert(getUDAs!(g, FuncAttr).length == 1);
8674     static assert(getUDAs!(g, FuncAttr)[0].func(5) == 47);
8675 
8676     static assert(getUDAs!(g, FuncAttr!add42).length == 1);
8677     static assert(getUDAs!(g, FuncAttr!add42)[0].func(5) == 47);
8678 
8679     static assert(getUDAs!(g, FuncAttr!add42()).length == 0);
8680 
8681     static assert(getUDAs!(g, FuncAttr!concat).length == 0);
8682     static assert(getUDAs!(g, FuncAttr!concat()).length == 0);
8683 
8684     @FuncAttr!add42() int h;
8685     static assert(getUDAs!(h, FuncAttr).length == 1);
8686     static assert(getUDAs!(h, FuncAttr)[0].func(5) == 47);
8687 
8688     static assert(getUDAs!(h, FuncAttr!add42).length == 1);
8689     static assert(getUDAs!(h, FuncAttr!add42)[0].func(5) == 47);
8690 
8691     static assert(getUDAs!(h, FuncAttr!add42()).length == 1);
8692     static assert(getUDAs!(h, FuncAttr!add42())[0].func(5) == 47);
8693 
8694     static assert(getUDAs!(h, FuncAttr!concat).length == 0);
8695     static assert(getUDAs!(h, FuncAttr!concat()).length == 0);
8696 
8697     @("alpha") @(42) int i;
8698     static assert(getUDAs!(i, "alpha").length == 1);
8699     static assert(getUDAs!(i, "alpha")[0] == "alpha");
8700 
8701     static assert(getUDAs!(i, 42).length == 1);
8702     static assert(getUDAs!(i, 42)[0] == 42);
8703 
8704     static assert(getUDAs!(i, 'c').length == 0);
8705 }
8706 
8707 private template isDesiredUDA(alias attribute)
8708 {
8709     template isDesiredUDA(alias toCheck)
8710     {
8711         static if (is(typeof(attribute)) && !__traits(isTemplate, attribute))
8712         {
8713             static if (__traits(compiles, toCheck == attribute))
8714                 enum isDesiredUDA = toCheck == attribute;
8715             else
8716                 enum isDesiredUDA = false;
8717         }
8718         else static if (is(typeof(toCheck)))
8719         {
8720             static if (__traits(isTemplate, attribute))
8721                 enum isDesiredUDA =  isInstanceOf!(attribute, typeof(toCheck));
8722             else
8723                 enum isDesiredUDA = is(typeof(toCheck) == attribute);
8724         }
8725         else static if (__traits(isTemplate, attribute))
8726             enum isDesiredUDA = isInstanceOf!(attribute, toCheck);
8727         else
8728             enum isDesiredUDA = is(toCheck == attribute);
8729     }
8730 }
8731 
8732 /**
8733 Params:
8734     symbol = The aggregate type or module to search
8735     attribute = The user-defined attribute to search for
8736 
8737 Returns:
8738     All symbols within `symbol` that have the given UDA `attribute`.
8739 
8740 Note:
8741     This is not recursive; it will not search for symbols within symbols such as
8742     nested structs or unions.
8743  */
8744 template getSymbolsByUDA(alias symbol, alias attribute)
8745 {
8746     alias membersWithUDA = getSymbolsByUDAImpl!(symbol, attribute, __traits(allMembers, symbol));
8747 
8748     // if the symbol itself has the UDA, tack it on to the front of the list
8749     static if (hasUDA!(symbol, attribute))
8750         alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
8751     else
8752         alias getSymbolsByUDA = membersWithUDA;
8753 }
8754 
8755 ///
8756 @safe unittest
8757 {
8758     enum Attr;
8759     struct A
8760     {
8761         @Attr int a;
8762         int b;
8763     }
8764 
8765     static assert(getSymbolsByUDA!(A, Attr).length == 1);
8766     static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8767 }
8768 
8769 ///
8770 @safe unittest
8771 {
8772     enum Attr;
8773 
8774     static struct A
8775     {
8776         @Attr int a;
8777         int b;
8778         @Attr void doStuff() {}
8779         void doOtherStuff() {}
8780         static struct Inner
8781         {
8782             // Not found by getSymbolsByUDA
8783             @Attr int c;
8784         }
8785     }
8786 
8787     // Finds both variables and functions with the attribute, but
8788     // doesn't include the variables and functions without it.
8789     static assert(getSymbolsByUDA!(A, Attr).length == 2);
8790     // Can access attributes on the symbols returned by getSymbolsByUDA.
8791     static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[0], Attr));
8792     static assert(hasUDA!(getSymbolsByUDA!(A, Attr)[1], Attr));
8793 }
8794 
8795 /// Finds multiple attributes
8796 @safe unittest
8797 {
8798     static struct UDA { string name; }
8799 
8800     static struct B
8801     {
8802         @UDA("X")
8803         int x;
8804         @UDA("Y")
8805         int y;
8806         @(100)
8807         int z;
8808     }
8809 
8810     // Finds both UDA attributes.
8811     static assert(getSymbolsByUDA!(B, UDA).length == 2);
8812     // Finds one `100` attribute.
8813     static assert(getSymbolsByUDA!(B, 100).length == 1);
8814     // Can get the value of the UDA from the return value
8815     static assert(getUDAs!(getSymbolsByUDA!(B, UDA)[0], UDA)[0].name == "X");
8816 }
8817 
8818 /// Checks for UDAs on the aggregate symbol itself
8819 @safe unittest
8820 {
8821     static struct UDA { string name; }
8822 
8823     @UDA("A")
8824     static struct C
8825     {
8826         @UDA("B")
8827         int d;
8828     }
8829 
8830     static assert(getSymbolsByUDA!(C, UDA).length == 2);
8831     static assert(getSymbolsByUDA!(C, UDA)[0].stringof == "C");
8832     static assert(getSymbolsByUDA!(C, UDA)[1].stringof == "d");
8833 }
8834 
8835 /// Finds nothing if there is no member with specific UDA
8836 @safe unittest
8837 {
8838     static struct UDA { string name; }
8839 
8840     static struct D
8841     {
8842         int x;
8843     }
8844 
8845     static assert(getSymbolsByUDA!(D, UDA).length == 0);
8846 }
8847 
8848 // https://issues.dlang.org/show_bug.cgi?id=18314
8849 @safe unittest
8850 {
8851     enum attr1;
8852     enum attr2;
8853 
8854     struct A
8855     {
8856         @attr1
8857         int n;
8858         // Removed due to https://issues.dlang.org/show_bug.cgi?id=16206
8859         //@attr1
8860         //void foo()(string){}
8861         @attr1
8862         void foo();
8863         @attr2
8864         void foo(int a);
8865     }
8866 
8867     static assert(getSymbolsByUDA!(A, attr1).length == 2);
8868     static assert(getSymbolsByUDA!(A, attr2).length == 1);
8869 }
8870 
8871 // getSymbolsByUDA fails if type has private members
8872 // https://issues.dlang.org/show_bug.cgi?id=15335
8873 @safe unittest
8874 {
8875     // HasPrivateMembers has, well, private members, one of which has a UDA.
8876     import std.internal.test.uda : Attr, HasPrivateMembers;
8877     // Trying access to private member from another file therefore we do not have access
8878     // for this otherwise we get deprecation warning - not visible from module
8879     // This line is commented because `__traits(getMember)` should also consider
8880     // private members; this is not currently the case, but the PR that
8881     // fixes `__traits(getMember)` is blocked by this specific test.
8882     //static assert(getSymbolsByUDA!(HasPrivateMembers, Attr).length == 1);
8883     static assert(hasUDA!(getSymbolsByUDA!(HasPrivateMembers, Attr)[0], Attr));
8884 }
8885 
8886 // getSymbolsByUDA works with structs but fails with classes
8887 // https://issues.dlang.org/show_bug.cgi?id=16387
8888 @safe unittest
8889 {
8890     enum Attr;
8891     class A
8892     {
8893         @Attr uint a;
8894     }
8895 
8896     alias res = getSymbolsByUDA!(A, Attr);
8897     static assert(res.length == 1);
8898     static assert(res[0].stringof == "a");
8899 }
8900 
8901 // getSymbolsByUDA fails on AliasSeq members
8902 // https://issues.dlang.org/show_bug.cgi?id=18884
8903 @safe unittest
8904 {
8905     struct X
8906     {
8907         alias A = AliasSeq!(ulong, uint);
8908     }
8909 
8910     static assert(is(getSymbolsByUDA!(X, X) == AliasSeq!()));
8911 }
8912 
8913 // https://issues.dlang.org/show_bug.cgi?id=23776
8914 @safe pure nothrow @nogc unittest
8915 {
8916     struct T
8917     {
8918         struct Tag {}
8919         @Tag struct MyStructA {}
8920         @Tag struct MyStructB {}
8921         @Tag struct MyStructC {}
8922     }
8923     alias tcomponents = getSymbolsByUDA!(T, T.Tag);
8924     static assert(tcomponents.length > 0);
8925 
8926     struct X
8927     {
8928         struct Tag {}
8929         @Tag enum MyEnumA;
8930         @Tag enum MyEnumB;
8931         @Tag enum MyEnumC;
8932     }
8933     alias xcomponents = getSymbolsByUDA!(X, X.Tag);
8934     static assert(xcomponents.length > 0);
8935 }
8936 
8937 // getSymbolsByUDA produces wrong result if one of the symbols having the UDA is a function
8938 // https://issues.dlang.org/show_bug.cgi?id=18624
8939 @safe unittest
8940 {
8941     enum Attr;
8942     struct A
8943     {
8944         @Attr void a();
8945         @Attr void a(int n);
8946               void b();
8947         @Attr void c();
8948     }
8949 
8950     alias ola = __traits(getOverloads, A, "a");
8951     static assert(__traits(isSame, getSymbolsByUDA!(A, Attr),
8952         AliasSeq!(ola[0], ola[1], A.c)));
8953 }
8954 
8955 // getSymbolsByUDA no longer works on modules
8956 // https://issues.dlang.org/show_bug.cgi?id=20054
8957 version (StdUnittest)
8958 {
8959     @("Issue20054")
8960     void issue20054() {}
8961     static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054")));
8962 }
8963 
8964 private template isAliasSeq(Args...)
8965 {
8966     static if (Args.length != 1)
8967         enum isAliasSeq = true;
8968     else
8969         enum isAliasSeq = false;
8970 }
8971 
8972 private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
8973 {
8974     import std.meta : Alias, AliasSeq, Filter;
8975     static if (names.length == 0)
8976     {
8977         alias getSymbolsByUDAImpl = AliasSeq!();
8978     }
8979     else
8980     {
8981         alias tail = getSymbolsByUDAImpl!(symbol, attribute, names[1 .. $]);
8982 
8983         // Filtering inaccessible members.
8984         static if (!__traits(compiles, __traits(getMember, symbol, names[0])))
8985         {
8986             alias getSymbolsByUDAImpl = tail;
8987         }
8988         else
8989         {
8990             alias member = __traits(getMember, symbol, names[0]);
8991 
8992             // Filtering not compiled members such as alias of basic types.
8993             static if (isAliasSeq!member ||
8994                        (isType!member && !isAggregateType!member && !is(member == enum)))
8995             {
8996                 alias getSymbolsByUDAImpl = tail;
8997             }
8998             // If a symbol is overloaded, get UDAs for each overload (including templated overlaods).
8999             else static if (__traits(getOverloads, symbol, names[0], true).length > 0)
9000             {
9001                 enum hasSpecificUDA(alias member) = hasUDA!(member, attribute);
9002                 alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0]));
9003                 alias getSymbolsByUDAImpl = AliasSeq!(overloadsWithUDA, tail);
9004             }
9005             else static if (hasUDA!(member, attribute))
9006             {
9007                 alias getSymbolsByUDAImpl = AliasSeq!(member, tail);
9008             }
9009             else
9010             {
9011                 alias getSymbolsByUDAImpl = tail;
9012             }
9013         }
9014     }
9015 }
9016 
9017 /**
9018    Returns: `true` iff all types `Ts` are the same.
9019 */
9020 enum bool allSameType(Ts...) =
9021 {
9022     static foreach (T; Ts[Ts.length > 1 .. $])
9023         static if (!is(Ts[0] == T))
9024             if (__ctfe)  // Dodge the "statement is unreachable" warning
9025                 return false;
9026     return true;
9027 }();
9028 
9029 ///
9030 @safe unittest
9031 {
9032     static assert(allSameType!());
9033     static assert(allSameType!(int));
9034     static assert(allSameType!(int, int));
9035     static assert(allSameType!(int, int, int));
9036     static assert(allSameType!(float, float, float));
9037     static assert(!allSameType!(int, double));
9038     static assert(!allSameType!(int, float, double));
9039     static assert(!allSameType!(int, float, double, real));
9040     static assert(!allSameType!(short, int, float, double, real));
9041 }
9042 
9043 /**
9044    Returns: `true` iff the type `T` can be tested in an $(D
9045    if)-expression, that is if $(D if (pred(T.init)) {}) is compilable.
9046 */
9047 enum ifTestable(T, alias pred = a => a) = __traits(compiles, { if (pred(T.init)) {} });
9048 
9049 ///
9050 @safe unittest
9051 {
9052     class C;
9053     struct S1;
9054     struct S2
9055     {
9056         T opCast(T)() const;
9057     }
9058 
9059     static assert( ifTestable!bool);
9060     static assert( ifTestable!int);
9061     static assert( ifTestable!(S1*));
9062     static assert( ifTestable!(typeof(null)));
9063     static assert( ifTestable!(int[]));
9064     static assert( ifTestable!(int[string]));
9065     static assert( ifTestable!S2);
9066     static assert( ifTestable!C);
9067     static assert(!ifTestable!S1);
9068 }
9069 
9070 @safe unittest
9071 {
9072     import std.meta : AliasSeq, allSatisfy;
9073     static assert(allSatisfy!(ifTestable, AliasSeq!(bool, int, float, double, string)));
9074     struct BoolWrapper { bool value; }
9075     static assert(!ifTestable!(bool, a => BoolWrapper(a)));
9076 }
9077 
9078 /**
9079  * Detect whether `X` is a type. Analogous to `is(X)`. This is useful when used
9080  * in conjunction with other templates, e.g. `allSatisfy!(isType, X)`.
9081  *
9082  * Returns:
9083  *      `true` if `X` is a type, `false` otherwise
9084  */
9085 enum isType(alias X) = is(X);
9086 
9087 ///
9088 @safe unittest
9089 {
9090     struct S {
9091         template Test() {}
9092     }
9093     class C {}
9094     interface I {}
9095     union U {}
9096     static assert(isType!int);
9097     static assert(isType!string);
9098     static assert(isType!(int[int]));
9099     static assert(isType!S);
9100     static assert(isType!C);
9101     static assert(isType!I);
9102     static assert(isType!U);
9103 
9104     int n;
9105     void func(){}
9106     static assert(!isType!n);
9107     static assert(!isType!func);
9108     static assert(!isType!(S.Test));
9109     static assert(!isType!(S.Test!()));
9110 }
9111 
9112 /**
9113  * Detect whether symbol or type `X` is a function. This is different that finding
9114  * if a symbol is callable or satisfying `is(X == function)`, it finds
9115  * specifically if the symbol represents a normal function declaration, i.e.
9116  * not a delegate or a function pointer.
9117  *
9118  * Returns:
9119  *     `true` if `X` is a function, `false` otherwise
9120  *
9121  * See_Also:
9122  *     Use $(LREF isFunctionPointer) or $(LREF isDelegate) for detecting those types
9123  *     respectively.
9124  */
9125 template isFunction(alias X)
9126 {
9127     static if (is(typeof(&X) U : U*) && is(U == function) ||
9128                is(typeof(&X) U == delegate))
9129     {
9130         // x is a (nested) function symbol.
9131         enum isFunction = true;
9132     }
9133     else static if (is(X T))
9134     {
9135         // x is a type.  Take the type of it and examine.
9136         enum isFunction = is(T == function);
9137     }
9138     else
9139         enum isFunction = false;
9140 }
9141 
9142 ///
9143 @safe unittest
9144 {
9145     static void func(){}
9146     static assert(isFunction!func);
9147 
9148     struct S
9149     {
9150         void func(){}
9151     }
9152     static assert(isFunction!(S.func));
9153 }
9154 
9155 /**
9156  * Detect whether `X` is a final method or class.
9157  *
9158  * Returns:
9159  *     `true` if `X` is final, `false` otherwise
9160  */
9161 template isFinal(alias X)
9162 {
9163     static if (is(X == class))
9164         enum isFinal = __traits(isFinalClass, X);
9165     else static if (isFunction!X)
9166         enum isFinal = __traits(isFinalFunction, X);
9167     else
9168         enum isFinal = false;
9169 }
9170 
9171 ///
9172 @safe unittest
9173 {
9174     class C
9175     {
9176         void nf() {}
9177         static void sf() {}
9178         final void ff() {}
9179     }
9180     final class FC { }
9181 
9182     static assert(!isFinal!(C));
9183     static assert( isFinal!(FC));
9184 
9185     static assert(!isFinal!(C.nf));
9186     static assert(!isFinal!(C.sf));
9187     static assert( isFinal!(C.ff));
9188 }
9189 
9190 /++
9191  + Determines whether the type `S` can be copied.
9192  + If a type cannot be copied, then code such as `MyStruct x; auto y = x;` will fail to compile.
9193  + Copying for structs can be disabled by using `@disable this(this)`.
9194  +
9195  + See also: $(DDSUBLINK spec/traits, isCopyable, `__traits(isCopyable, S)`)
9196  + Params:
9197  +  S = The type to check.
9198  +
9199  + Returns:
9200  +  `true` if `S` can be copied. `false` otherwise.
9201  +/
9202 enum isCopyable(S) = __traits(isCopyable, S);
9203 
9204 ///
9205 @safe unittest
9206 {
9207     struct S1 {}                        // Fine. Can be copied
9208     struct S2 {         this(this) {}}  // Fine. Can be copied
9209     struct S3 {@disable this(this);  }  // Not fine. Copying is disabled.
9210     struct S4 {S3 s;}                   // Not fine. A field has copying disabled.
9211 
9212     class C1 {}
9213 
9214     static assert( isCopyable!S1);
9215     static assert( isCopyable!S2);
9216     static assert(!isCopyable!S3);
9217     static assert(!isCopyable!S4);
9218 
9219     static assert(isCopyable!C1);
9220     static assert(isCopyable!int);
9221     static assert(isCopyable!(int[]));
9222 }
9223 
9224 /**
9225  * The parameter type deduced by IFTI when an expression of type T is passed as
9226  * an argument to a template function.
9227  *
9228  * For all types other than pointer and slice types, `DeducedParameterType!T`
9229  * is the same as `T`. For pointer and slice types, it is `T` with the
9230  * outer-most layer of qualifiers dropped.
9231  */
9232 package(std) template DeducedParameterType(T)
9233 {
9234     static if (is(T == U*, U) || is(T == U[], U))
9235         alias DeducedParameterType = Unqual!T;
9236     else
9237         alias DeducedParameterType = T;
9238 }
9239 
9240 @safe unittest
9241 {
9242     static assert(is(DeducedParameterType!(const(int)) == const(int)));
9243     static assert(is(DeducedParameterType!(const(int[2])) == const(int[2])));
9244 
9245     static assert(is(DeducedParameterType!(const(int*)) == const(int)*));
9246     static assert(is(DeducedParameterType!(const(int[])) == const(int)[]));
9247 }
9248 
9249 @safe unittest
9250 {
9251     static struct NoCopy
9252     {
9253         @disable this(this);
9254     }
9255 
9256     static assert(is(DeducedParameterType!NoCopy == NoCopy));
9257 }
9258 
9259 @safe unittest
9260 {
9261     static assert(is(DeducedParameterType!(inout(int[])) == inout(int)[]));
9262 }
9263 
9264 private auto dip1000Test(int x) {return *&x;}
9265 // We don't use isSafe, because betterC client code needs to instantiate
9266 // core.internal.array.comparison.__cmp in the client side. isSafe uses
9267 // __cmp of two strings, so using it would instantate that here instead. That
9268 // won't do because betterC compilations do not link the Phobos binary in.
9269 package(std) enum dip1000Enabled
9270     = is(typeof(&dip1000Test) : int function(int) @safe);