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