1 // Written in the D programming language
2 /++
3     Templates which extract information about types and symbols at compile time.
4 
5     In the context of phobos.sys.traits, a "trait" is a template which provides
6     information about a type or symbol. Most traits evaluate to
7     $(D true) or $(D false), telling the code using it whether the given
8     arguments match / have that specific trait (e.g. whether the given type is
9     a dynamic array or whether the given function is $(D @safe)). However, some
10     traits may provide other kinds of information about a type (e.g. the trait
11     could evaluate to the base type for an enum type, or it could strip
12     $(D const) from the type to provide the mutable version of that type).
13 
14     These traits are then used primarily in template constraints so that they
15     can test that the template arguments meet the criteria required by those
16     templates, though they can be useful in a variety of compile-time contexts
17     (e.g. the condition of a $(D static if)).
18 
19     Note that unless otherwise specified, the isXXXX and hasXXX traits in this
20     module are checking for exact matches, so base types (e.g. with enums) and
21     other implicit conversions do not factor into whether such traits are true
22     or false. The type itself is being checked, not what it can be converted
23     to.
24 
25     This is because these traits are often used in templated constraints, and
26     having a type pass a template constraint based on an implicit conversion
27     but then not have the implicit conversion actually take place (which it
28     won't unless the template does something to force it internally) can lead
29     to either compilation errors or subtle behavioral differences - and even
30     when the conversion is done explicitly within a templated function, since
31     it's not done at the call site, it can still lead to subtle bugs in some
32     cases (e.g. if slicing a static array is involved).
33 
34     So, it's typically best to be explicit and clear about a template constraint
35     accepting any kind of implicit conversion rather than having it buried in a
36     trait where programmers stand a good chance of using the trait without
37     realizing that enums might pass based on their base type - or that a type
38     might pass based on some other implicit conversion.
39 
40     Regardless of what a trait is testing for, the documentation strives to be
41     $(I very) clear about what the trait does, and of course, the names do try
42     to make it clear as well - though obviously, only so much information can
43     be put into a name, and some folks will misintrepret some symbols no matter
44     how well they're named. So, please be sure that you clearly understand what
45     these traits do when using them, since messing up template constraints can
46     unfortunately be a great way to introduce subtle bugs into your program.
47     Either way, of course, unit tests are your friends.
48 
49     $(SCRIPT inhibitQuickIndex = 1;)
50 
51     $(BOOKTABLE ,
52     $(TR $(TH Category) $(TH Templates))
53     $(TR $(TD Categories of types) $(TD
54               $(LREF isAggregateType)
55               $(LREF isDynamicArray)
56               $(LREF isFloatingPoint)
57               $(LREF isInstantiationOf)
58               $(LREF isInteger)
59               $(LREF isNumeric)
60               $(LREF isPointer)
61               $(LREF isSignedInteger)
62               $(LREF isStaticArray)
63               $(LREF isUnsignedInteger)
64     ))
65     $(TR $(TD Aggregate Type traits) $(TD
66               $(LREF EnumMembers)
67     ))
68     $(TR $(TD Traits testing for type conversions) $(TD
69               $(LREF isImplicitlyConvertible)
70               $(LREF isQualifierConvertible)
71     ))
72     $(TR $(TD Traits for comparisons) $(TD
73               $(LREF isEqual)
74               $(LREF isSameSymbol)
75               $(LREF isSameType)
76     ))
77     $(TR $(TD Aggregate Type Traits) $(TD
78               $(LREF FieldNames)
79               $(LREF FieldSymbols)
80               $(LREF FieldTypes)
81               $(LREF hasComplexAssignment)
82               $(LREF hasComplexCopying)
83               $(LREF hasComplexDestruction)
84               $(LREF hasIndirections)
85     ))
86     $(TR $(TD General Types) $(TD
87               $(LREF KeyType)
88               $(LREF OriginalType)
89               $(LREF ValueType)
90     ))
91     $(TR $(TD Traits for removing type qualfiers) $(TD
92               $(LREF Unconst)
93               $(LREF Unshared)
94               $(LREF Unqualified)
95     ))
96     $(TR $(TD Type Constructors) $(TD
97               $(LREF ConstOf)
98               $(LREF ImmutableOf)
99               $(LREF InoutOf)
100               $(LREF SharedOf)
101     ))
102     $(TR $(TD Misc) $(TD
103               $(LREF lvalueOf)
104               $(LREF rvalueOf)
105     ))
106     )
107 
108     Copyright: Copyright The D Language Foundation 2005 - 2024.
109     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
110     Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis)
111                $(HTTP digitalmars.com, Walter Bright),
112                Tomasz Stachowiak (`isExpressions`),
113                $(HTTP erdani.org, Andrei Alexandrescu),
114                Shin Fujishiro,
115                $(HTTP octarineparrot.com, Robert Clipsham),
116                $(HTTP klickverbot.at, David Nadlinger),
117                Kenji Hara,
118                Shoichi Kato
119     Source:    $(PHOBOSSRC phobos/sys/traits)
120 +/
121 module phobos.sys.traits;
122 
123 /++
124     Whether the given type is an "aggregate type" - i.e. a struct, class,
125     interface, or union. Enum types whose base type is an aggregate type are
126     also considered aggregate types.
127   +/
128 template isAggregateType(T)
129 {
130     static if (is(T == enum))
131         enum isAggregateType = isAggregateType!(OriginalType!T);
132     else
133         enum isAggregateType = is(T == struct) || is(T == class) || is(T == interface) || is(T == union);
134 }
135 
136 ///
137 @safe unittest
138 {
139     struct S {}
140     class C {}
141     interface I {}
142     union U {}
143 
144     static assert( isAggregateType!S);
145     static assert( isAggregateType!C);
146     static assert( isAggregateType!I);
147     static assert( isAggregateType!U);
148     static assert( isAggregateType!(const S));
149     static assert( isAggregateType!(shared C));
150 
151     static assert(!isAggregateType!int);
152     static assert(!isAggregateType!string);
153     static assert(!isAggregateType!(S*));
154     static assert(!isAggregateType!(C[]));
155     static assert(!isAggregateType!(I[string]));
156 
157     enum ES : S { a = S.init }
158     enum EC : C { a = C.init }
159     enum EI : I { a = I.init }
160     enum EU : U { a = U.init }
161 
162     static assert( isAggregateType!ES);
163     static assert( isAggregateType!EC);
164     static assert( isAggregateType!EI);
165     static assert( isAggregateType!EU);
166     static assert( isAggregateType!(const ES));
167     static assert( isAggregateType!(const EC));
168 }
169 
170 /++
171     Whether the given type is a dynamic array (or what is sometimes referred to
172     as a slice, since a dynamic array in D is a slice of memory).
173 
174     Note that this does not include implicit conversions or enum types. The
175     type itself must be a dynamic array.
176 
177     Remember that D's dynamic arrays are essentially:
178     ---
179     struct DynamicArray(T)
180     {
181         size_t length;
182         T* ptr;
183     }
184     ---
185     where $(D ptr) points to the first element in the array, and $(D length) is
186     the number of elements in the array.
187 
188     A dynamic array is not a pointer (unlike arrays in C/C++), and its elements
189     do not live inside the dynamic array itself. The dynamic array is simply a
190     slice of memory and does not own or manage its own memory. It can be a
191     slice of any piece of memory, including GC-allocated memory, the stack,
192     malloc-ed memory, etc. (with what kind of memory it is of course being
193     determined by how the dynamic array was created in the first place)
194     - though if you do any operations on it which end up requiring allocation
195     (e.g. appending to it if it doesn't have the capacity to expand in-place,
196     which it won't if it isn't a slice of GC-allocated memory), then that
197     reallocation will result in the dynamic array being a slice of newly
198     allocated, GC-backed memory (regardless of what it was a slice of before),
199     since it's the GC that deals with those allocations.
200 
201     As long as code just accesses the elements or members of the dynamic array
202     - or reduces its length so that it's a smaller slice - it will continue to
203     point to whatever block of memory it pointed to originally. And because the
204     GC makes sure that appending to a dynamic array does not stomp on the
205     memory of any other dynamic arrays, appending to a dynamic array will not
206     affect any other dynamic array which is a slice of that same block of
207     memory whether a reallocation occurs or not.
208 
209     Regardless, since what allocated the memory that the dynamic array is a
210     slice of is irrevelant to the type of the dynamic array, whether a given
211     type is a dynamic array has nothing to do with the kind of memory that's
212     backing it. A dynamic array which is a slice of a static array of $(D int)
213     is the the same type as a dynamic array of $(D int) allocated with $(D new)
214     - i.e. both are $(D int[]). So, this trait will not tell you anything about
215     what kind of memory a dynamic array is a slice of. It just tells you
216     whether the type is a dynamic array or not.
217 
218     If for some reason, it matters for a function what kind of memory backs one
219     of its parameters which is a dynamic array, or it needs to be made clear
220     whether the function will possibly cause that dynamic array to be
221     reallocated, then that needs to be indicated by the documentation and
222     cannot be enforced with a template constraint. A template constraint can
223     enforce that a type used with a template meets certain criteria (e.g. that
224     it's a dynamic array), but it cannot enforce anything about how the
225     template actually uses the type.
226 
227     However, it $(D is) possible to enforce that a function doesn't use any
228     operations on a dynamic array which might cause it to be reallocated by
229     marking that function as $(D @nogc).
230 
231     In most cases though, code can be written to not care what kind of memory
232     backs a dynamic array, because none of the operations on a dynamic array
233     actually care what kind of memory it's a slice of. It mostly just matters
234     when you need to track the lifetime of the memory, because it wasn't
235     allocated by the GC, or when it matters whether a dynamic array could be
236     reallocated or not (e.g. because the code needs to have that dynamic array
237     continue to point to the same block of memory).
238 
239     See_Also:
240         $(LREF isPointer)
241         $(LREF isStaticArray)
242         $(DDSUBLINK spec/arrays, , The language spec for arrays)
243   +/
244 enum isDynamicArray(T) = is(T == U[], U);
245 
246 ///
247 @safe unittest
248 {
249     // Some types which are dynamic arrays.
250     static assert( isDynamicArray!(int[]));
251     static assert( isDynamicArray!(const int[]));
252     static assert( isDynamicArray!(inout int[]));
253     static assert( isDynamicArray!(shared(int)[]));
254     static assert( isDynamicArray!string);
255 
256     static assert( isDynamicArray!(typeof([1, 2, 3])));
257     static assert( isDynamicArray!(typeof("dlang")));
258 
259     int[] arr;
260     static assert( isDynamicArray!(typeof(arr)));
261 
262     // Some types which aren't dynamic arrays.
263     static assert(!isDynamicArray!int);
264     static assert(!isDynamicArray!(int*));
265     static assert(!isDynamicArray!real);
266 
267     static struct S
268     {
269         int[] arr;
270     }
271     static assert(!isDynamicArray!S);
272 
273     // The struct itself isn't considered a dynamic array,
274     // but its member variable is when checked directly.
275     static assert( isDynamicArray!(typeof(S.arr)));
276 
277     // Static arrays.
278     static assert(!isDynamicArray!(int[5]));
279     static assert(!isDynamicArray!(const(int)[5]));
280 
281     int[2] sArr = [42, 97];
282     static assert(!isDynamicArray!(typeof(sArr)));
283 
284     // While a static array is not a dynamic array,
285     // a slice of a static array is a dynamic array.
286     static assert( isDynamicArray!(typeof(sArr[])));
287 
288     // Dynamic array of static arrays.
289     static assert( isDynamicArray!(long[3][]));
290 
291     // Static array of dynamic arrays.
292     static assert(!isDynamicArray!(long[][3]));
293 
294     // Associative array.
295     static assert(!isDynamicArray!(int[string]));
296 
297     // While typeof(null) gets treated as void[] in some contexts, it is
298     // distinct from void[] and is not considered to be a dynamic array.
299     static assert(!isDynamicArray!(typeof(null)));
300 
301     // However, naturally, if null is cast to a dynamic array, it's a
302     // dynamic array, since the cast forces the type.
303     static assert( isDynamicArray!(typeof(cast(int[]) null)));
304 
305     enum E : int[]
306     {
307         a = [1, 2, 3],
308     }
309 
310     // Enums do not count.
311     static assert(!isDynamicArray!E);
312 
313     static struct AliasThis
314     {
315         int[] arr;
316         alias this = arr;
317     }
318 
319     // Other implicit conversions do not count.
320     static assert(!isDynamicArray!AliasThis);
321 }
322 
323 @safe unittest
324 {
325     import phobos.sys.meta : Alias, AliasSeq;
326 
327     static struct AliasThis(T)
328     {
329         T member;
330         alias this = member;
331     }
332 
333     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
334     {
335         foreach (T; AliasSeq!(int[], char[], string, long[3][], double[string][]))
336         {
337             enum E : Q!T { a = Q!T.init }
338 
339             static assert( isDynamicArray!(Q!T));
340             static assert(!isDynamicArray!E);
341             static assert(!isDynamicArray!(AliasThis!(Q!T)));
342         }
343 
344         foreach (T; AliasSeq!(int, int[51], int[][2],
345                               char[][int][11], immutable char[13u],
346                               const(real)[1], const(real)[1][1], void[0]))
347         {
348             enum E : Q!T { a = Q!T.init }
349 
350             static assert(!isDynamicArray!(Q!T));
351             static assert(!isDynamicArray!E);
352             static assert(!isDynamicArray!(AliasThis!(Q!T)));
353         }
354     }
355 }
356 
357 /++
358     Whether type $(D T) is a static array.
359 
360     Note that this does not include implicit conversions or enum types. The
361     type itself must be a static array. This is in contrast to
362     $(D __traits(isStaticArray, T)) which is true for enums (but not for other
363     implict conversions to static arrays).
364 
365     As explained in the module documentation, traits like this one are not true
366     for enums (unlike most of the $(D __traits) traits) in order to avoid
367     testing for implicit conversions by default with template constraints,
368     since that tends to lead to subtle bugs when the code isn't carefully
369     written to take implicit conversions into account.
370 
371     See also:
372         $(DDSUBLINK spec/traits, isStaticArray, $(D __traits(isStaticArray, T)))
373         $(DDSUBLINK spec/arrays, , The language spec for arrays)
374   +/
375 enum isStaticArray(T) = is(T == U[n], U, size_t n);
376 
377 ///
378 @safe unittest
379 {
380     // Some types which are static arrays.
381     static assert( isStaticArray!(int[12]));
382     static assert( isStaticArray!(const int[42]));
383     static assert( isStaticArray!(inout int[0]));
384     static assert( isStaticArray!(shared(int)[907]));
385     static assert( isStaticArray!(immutable(char)[5]));
386 
387     // D doesn't have static array literals, but you get the same effect
388     // by casting a dynamic array literal to a static array, and of course,
389     // the result is typed as a static array.
390     static assert( isStaticArray!(typeof(cast(int[3]) [1, 2, 3])));
391 
392     int[2] sArr = [1, 2];
393     static assert( isStaticArray!(typeof(sArr)));
394 
395     // Some types which are not static arrays.
396     static assert(!isStaticArray!int);
397     static assert(!isStaticArray!(int*));
398     static assert(!isStaticArray!real);
399 
400     static struct S
401     {
402         int[4] arr;
403     }
404     static assert(!isStaticArray!S);
405 
406     // The struct itself isn't considered a static array,
407     // but its member variable is when checked directly.
408     static assert( isStaticArray!(typeof(S.arr)));
409 
410     // Dynamic arrays.
411     static assert(!isStaticArray!(int[]));
412     static assert(!isStaticArray!(const(int)[]));
413     static assert(!isStaticArray!string);
414 
415     int[] arr;
416     static assert(!isStaticArray!(typeof(arr)));
417 
418     // A slice of a static array is of course not a static array,
419     // because it's a dynamic array.
420     static assert(!isStaticArray!(typeof(sArr[])));
421 
422     // Static array of dynamic arrays.
423     static assert( isStaticArray!(long[][3]));
424 
425     // Dynamic array of static arrays.
426     static assert(!isStaticArray!(long[3][]));
427 
428     // Associative array.
429     static assert(!isStaticArray!(int[string]));
430 
431     // Of course, null is not considered to be a static array.
432     static assert(!isStaticArray!(typeof(null)));
433 
434     enum E : int[3]
435     {
436         a = [1, 2, 3],
437     }
438 
439     // Enums do not count.
440     static assert(!isStaticArray!E);
441 
442     // This is where isStaticArray differs from __traits(isStaticArray, ...)
443     static assert( __traits(isStaticArray, E));
444 
445     static struct AliasThis
446     {
447         int[] arr;
448         alias this = arr;
449     }
450 
451     // Other implicit conversions do not count.
452     static assert(!isStaticArray!AliasThis);
453 
454     static assert(!__traits(isStaticArray, AliasThis));
455 }
456 
457 @safe unittest
458 {
459     import phobos.sys.meta : Alias, AliasSeq;
460 
461     static struct AliasThis(T)
462     {
463         T member;
464         alias this = member;
465     }
466 
467     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
468     {
469         foreach (T; AliasSeq!(int[51], int[][2],
470                               char[][int][11], immutable char[13u],
471                               const(real)[1], const(real)[1][1], void[0]))
472         {
473             enum E : Q!T { a = Q!T.init, }
474 
475             static assert( isStaticArray!(Q!T));
476             static assert(!isStaticArray!E);
477             static assert(!isStaticArray!(AliasThis!(Q!T)));
478         }
479 
480         foreach (T; AliasSeq!(int, int[], char[], string, long[3][], double[string][]))
481         {
482             enum E : Q!T { a = Q!T.init, }
483 
484             static assert(!isStaticArray!(Q!T));
485             static assert(!isStaticArray!E);
486             static assert(!isStaticArray!(AliasThis!(Q!T)));
487         }
488     }
489 }
490 
491 /++
492     Whether the given type is one of the built-in integer types, ignoring all
493     qualifiers.
494 
495     $(TABLE
496         $(TR $(TH Integer Types))
497         $(TR $(TD byte))
498         $(TR $(TD ubyte))
499         $(TR $(TD short))
500         $(TR $(TD ushort))
501         $(TR $(TD int))
502         $(TR $(TD uint))
503         $(TR $(TD long))
504         $(TR $(TD ulong))
505     )
506 
507     Note that this does not include implicit conversions or enum types. The
508     type itself must be one of the built-in integer types.
509 
510     This trait does have some similarities with $(D __traits(isIntegral, T)),
511     but $(D isIntegral) accepts a $(I lot) more types than isInteger does.
512     isInteger is specifically for testing for the built-in integer types,
513     whereas $(D isIntegral) tests for a whole set of types that are vaguely
514     integer-like (including $(D bool), the three built-in character types, and
515     some of the vector types from core.simd). So, for most code, isInteger is
516     going to be more appropriate, but obviously, it depends on what the code is
517     trying to do.
518 
519     See also:
520         $(DDSUBLINK spec/traits, isIntegral, $(D __traits(isIntegral, T)))
521         $(LREF isFloatingPoint)
522         $(LREF isSignedInteger)
523         $(LREF isNumeric)
524         $(LREF isUnsignedInteger)
525   +/
526 enum isInteger(T) = is(immutable T == immutable byte) ||
527                     is(immutable T == immutable ubyte) ||
528                     is(immutable T == immutable short) ||
529                     is(immutable T == immutable ushort) ||
530                     is(immutable T == immutable int) ||
531                     is(immutable T == immutable uint) ||
532                     is(immutable T == immutable long) ||
533                     is(immutable T == immutable ulong);
534 
535 ///
536 @safe unittest
537 {
538     // Some types which are integer types.
539     static assert( isInteger!byte);
540     static assert( isInteger!ubyte);
541     static assert( isInteger!short);
542     static assert( isInteger!ushort);
543     static assert( isInteger!int);
544     static assert( isInteger!uint);
545     static assert( isInteger!long);
546     static assert( isInteger!ulong);
547 
548     static assert( isInteger!(const ubyte));
549     static assert( isInteger!(immutable short));
550     static assert( isInteger!(inout int));
551     static assert( isInteger!(shared uint));
552     static assert( isInteger!(const shared ulong));
553 
554     static assert( isInteger!(typeof(42)));
555     static assert( isInteger!(typeof(1234567890L)));
556 
557     int i;
558     static assert( isInteger!(typeof(i)));
559 
560     // Some types which aren't integer types.
561     static assert(!isInteger!bool);
562     static assert(!isInteger!char);
563     static assert(!isInteger!wchar);
564     static assert(!isInteger!dchar);
565     static assert(!isInteger!(int[]));
566     static assert(!isInteger!(ubyte[4]));
567     static assert(!isInteger!(int*));
568     static assert(!isInteger!double);
569     static assert(!isInteger!string);
570 
571     static struct S
572     {
573         int i;
574     }
575     static assert(!isInteger!S);
576 
577     // The struct itself isn't considered an integer,
578     // but its member variable is when checked directly.
579     static assert( isInteger!(typeof(S.i)));
580 
581     enum E : int
582     {
583         a = 42
584     }
585 
586     // Enums do not count.
587     static assert(!isInteger!E);
588 
589     static struct AliasThis
590     {
591         int i;
592         alias this = i;
593     }
594 
595     // Other implicit conversions do not count.
596     static assert(!isInteger!AliasThis);
597 }
598 
599 @safe unittest
600 {
601     import phobos.sys.meta : Alias, AliasSeq;
602 
603     static struct AliasThis(T)
604     {
605         T member;
606         alias this = member;
607     }
608 
609     // The actual core.simd types available vary from system to system, so we
610     // have to be a bit creative here. The reason that we're testing these types
611     // is because __traits(isIntegral, T) accepts them, but isInteger is not
612     // supposed to.
613     template SIMDTypes()
614     {
615         import core.simd;
616 
617         alias SIMDTypes = AliasSeq!();
618         static if (is(ubyte16))
619             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
620         static if (is(int4))
621             SIMDTypes = AliasSeq!(SIMDTypes, int4);
622         static if (is(double2))
623             SIMDTypes = AliasSeq!(SIMDTypes, double2);
624         static if (is(void16))
625             SIMDTypes = AliasSeq!(SIMDTypes, void16);
626     }
627 
628     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
629     {
630         foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
631         {
632             enum E : Q!T { a = Q!T.init }
633 
634             static assert( isInteger!(Q!T));
635             static assert(!isInteger!E);
636             static assert(!isInteger!(AliasThis!(Q!T)));
637         }
638 
639         foreach (T; AliasSeq!(bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
640                               int[], ubyte[8], dchar[], void[], long*))
641         {
642             enum E : Q!T { a = Q!T.init }
643 
644             static assert(!isInteger!(Q!T));
645             static assert(!isInteger!E);
646             static assert(!isInteger!(AliasThis!(Q!T)));
647         }
648     }
649 }
650 
651 /++
652     Whether the given type is one of the built-in signed integer types, ignoring
653     all qualifiers.
654 
655     $(TABLE
656         $(TR $(TH Signed Integer Types))
657         $(TR $(TD byte))
658         $(TR $(TD short))
659         $(TR $(TD int))
660         $(TR $(TD long))
661     )
662 
663     Note that this does not include implicit conversions or enum types. The
664     type itself must be one of the built-in signed integer types.
665 
666     See also:
667         $(LREF isFloatingPoint)
668         $(LREF isInteger)
669         $(LREF isNumeric)
670         $(LREF isUnsignedInteger)
671   +/
672 enum isSignedInteger(T) = is(immutable T == immutable byte) ||
673                           is(immutable T == immutable short) ||
674                           is(immutable T == immutable int) ||
675                           is(immutable T == immutable long);
676 
677 ///
678 @safe unittest
679 {
680     // Some types which are signed integer types.
681     static assert( isSignedInteger!byte);
682     static assert( isSignedInteger!short);
683     static assert( isSignedInteger!int);
684     static assert( isSignedInteger!long);
685 
686     static assert( isSignedInteger!(const byte));
687     static assert( isSignedInteger!(immutable short));
688     static assert( isSignedInteger!(inout int));
689     static assert( isSignedInteger!(shared int));
690     static assert( isSignedInteger!(const shared long));
691 
692     static assert( isSignedInteger!(typeof(42)));
693     static assert( isSignedInteger!(typeof(1234567890L)));
694 
695     int i;
696     static assert( isSignedInteger!(typeof(i)));
697 
698     // Some types which aren't signed integer types.
699     static assert(!isSignedInteger!ubyte);
700     static assert(!isSignedInteger!ushort);
701     static assert(!isSignedInteger!uint);
702     static assert(!isSignedInteger!ulong);
703 
704     static assert(!isSignedInteger!bool);
705     static assert(!isSignedInteger!char);
706     static assert(!isSignedInteger!wchar);
707     static assert(!isSignedInteger!dchar);
708     static assert(!isSignedInteger!(int[]));
709     static assert(!isSignedInteger!(ubyte[4]));
710     static assert(!isSignedInteger!(int*));
711     static assert(!isSignedInteger!double);
712     static assert(!isSignedInteger!string);
713 
714     static struct S
715     {
716         int i;
717     }
718     static assert(!isSignedInteger!S);
719 
720     // The struct itself isn't considered a signed integer,
721     // but its member variable is when checked directly.
722     static assert( isSignedInteger!(typeof(S.i)));
723 
724     enum E : int
725     {
726         a = 42
727     }
728 
729     // Enums do not count.
730     static assert(!isSignedInteger!E);
731 
732     static struct AliasThis
733     {
734         int i;
735         alias this = i;
736     }
737 
738     // Other implicit conversions do not count.
739     static assert(!isSignedInteger!AliasThis);
740 }
741 
742 @safe unittest
743 {
744     import phobos.sys.meta : Alias, AliasSeq;
745 
746     static struct AliasThis(T)
747     {
748         T member;
749         alias this = member;
750     }
751 
752     // The actual core.simd types available vary from system to system, so we
753     // have to be a bit creative here. The reason that we're testing these types
754     // is because __traits(isIntegral, T) accepts them, but isSignedInteger is
755     // not supposed to.
756     template SIMDTypes()
757     {
758         import core.simd;
759 
760         alias SIMDTypes = AliasSeq!();
761         static if (is(ubyte16))
762             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
763         static if (is(int4))
764             SIMDTypes = AliasSeq!(SIMDTypes, int4);
765         static if (is(double2))
766             SIMDTypes = AliasSeq!(SIMDTypes, double2);
767         static if (is(void16))
768             SIMDTypes = AliasSeq!(SIMDTypes, void16);
769     }
770 
771     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
772     {
773         foreach (T; AliasSeq!(byte, short, int, long))
774         {
775             enum E : Q!T { a = Q!T.init }
776 
777             static assert( isSignedInteger!(Q!T));
778             static assert(!isSignedInteger!E);
779             static assert(!isSignedInteger!(AliasThis!(Q!T)));
780         }
781 
782         foreach (T; AliasSeq!(ubyte, ushort, uint, ulong,
783                               bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
784                               int[], ubyte[8], dchar[], void[], long*))
785         {
786             enum E : Q!T { a = Q!T.init }
787 
788             static assert(!isSignedInteger!(Q!T));
789             static assert(!isSignedInteger!E);
790             static assert(!isSignedInteger!(AliasThis!(Q!T)));
791         }
792     }
793 }
794 
795 /++
796     Whether the given type is one of the built-in unsigned integer types,
797     ignoring all qualifiers.
798 
799     $(TABLE
800         $(TR $(TH Integer Types))
801         $(TR $(TD ubyte))
802         $(TR $(TD ushort))
803         $(TR $(TD uint))
804         $(TR $(TD ulong))
805     )
806 
807     Note that this does not include implicit conversions or enum types. The
808     type itself must be one of the built-in unsigned integer types.
809 
810     This trait does have some similarities with $(D __traits(isUnsigned, T)),
811     but $(D isUnsigned) accepts a $(I lot) more types than isUnsignedInteger
812     does. isUnsignedInteger is specifically for testing for the built-in
813     unsigned integer types, whereas $(D isUnsigned) tests for a whole set of
814     types that are unsigned and vaguely integer-like (including $(D bool), the
815     three built-in character types, and some of the vector types from
816     core.simd). So, for most code, isUnsignedInteger is going to be more
817     appropriate, but obviously, it depends on what the code is trying to do.
818 
819     See also:
820         $(DDSUBLINK spec/traits, isUnsigned, $(D __traits(isUnsigned, T)))
821         $(LREF isFloatingPoint)
822         $(LREF isInteger)
823         $(LREF isSignedInteger)
824         $(LREF isNumeric)
825   +/
826 enum isUnsignedInteger(T) = is(immutable T == immutable ubyte) ||
827                             is(immutable T == immutable ushort) ||
828                             is(immutable T == immutable uint) ||
829                             is(immutable T == immutable ulong);
830 
831 ///
832 @safe unittest
833 {
834     // Some types which are unsigned integer types.
835     static assert( isUnsignedInteger!ubyte);
836     static assert( isUnsignedInteger!ushort);
837     static assert( isUnsignedInteger!uint);
838     static assert( isUnsignedInteger!ulong);
839 
840     static assert( isUnsignedInteger!(const ubyte));
841     static assert( isUnsignedInteger!(immutable ushort));
842     static assert( isUnsignedInteger!(inout uint));
843     static assert( isUnsignedInteger!(shared uint));
844     static assert( isUnsignedInteger!(const shared ulong));
845 
846     static assert( isUnsignedInteger!(typeof(42u)));
847     static assert( isUnsignedInteger!(typeof(1234567890UL)));
848 
849     uint u;
850     static assert( isUnsignedInteger!(typeof(u)));
851 
852     // Some types which aren't unsigned integer types.
853     static assert(!isUnsignedInteger!byte);
854     static assert(!isUnsignedInteger!short);
855     static assert(!isUnsignedInteger!int);
856     static assert(!isUnsignedInteger!long);
857 
858     static assert(!isUnsignedInteger!bool);
859     static assert(!isUnsignedInteger!char);
860     static assert(!isUnsignedInteger!wchar);
861     static assert(!isUnsignedInteger!dchar);
862     static assert(!isUnsignedInteger!(int[]));
863     static assert(!isUnsignedInteger!(ubyte[4]));
864     static assert(!isUnsignedInteger!(int*));
865     static assert(!isUnsignedInteger!double);
866     static assert(!isUnsignedInteger!string);
867 
868     static struct S
869     {
870         uint u;
871     }
872     static assert(!isUnsignedInteger!S);
873 
874     // The struct itself isn't considered an unsigned integer,
875     // but its member variable is when checked directly.
876     static assert( isUnsignedInteger!(typeof(S.u)));
877 
878     enum E : uint
879     {
880         a = 42
881     }
882 
883     // Enums do not count.
884     static assert(!isUnsignedInteger!E);
885 
886     static struct AliasThis
887     {
888         uint u;
889         alias this = u;
890     }
891 
892     // Other implicit conversions do not count.
893     static assert(!isUnsignedInteger!AliasThis);
894 }
895 
896 @safe unittest
897 {
898     import phobos.sys.meta : Alias, AliasSeq;
899 
900     static struct AliasThis(T)
901     {
902         T member;
903         alias this = member;
904     }
905 
906     // The actual core.simd types available vary from system to system, so we
907     // have to be a bit creative here. The reason that we're testing these types
908     // is because __traits(isIntegral, T) and __traits(isUnsigned, T) accept
909     // them, but isUnsignedInteger is not supposed to.
910     template SIMDTypes()
911     {
912         import core.simd;
913 
914         alias SIMDTypes = AliasSeq!();
915         static if (is(ubyte16))
916             SIMDTypes = AliasSeq!(SIMDTypes, ubyte16);
917         static if (is(int4))
918             SIMDTypes = AliasSeq!(SIMDTypes, int4);
919         static if (is(double2))
920             SIMDTypes = AliasSeq!(SIMDTypes, double2);
921         static if (is(void16))
922             SIMDTypes = AliasSeq!(SIMDTypes, void16);
923     }
924 
925     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
926     {
927         foreach (T; AliasSeq!(ubyte, ushort, uint, ulong))
928         {
929             enum E : Q!T { a = Q!T.init }
930 
931             static assert( isUnsignedInteger!(Q!T));
932             static assert(!isUnsignedInteger!E);
933             static assert(!isUnsignedInteger!(AliasThis!(Q!T)));
934         }
935 
936         foreach (T; AliasSeq!(byte, short, int, long,
937                               bool, char, wchar, dchar, float, double, real, SIMDTypes!(),
938                               int[], ubyte[8], dchar[], void[], long*))
939         {
940             enum E : Q!T { a = Q!T.init }
941 
942             static assert(!isUnsignedInteger!(Q!T));
943             static assert(!isUnsignedInteger!E);
944             static assert(!isUnsignedInteger!(AliasThis!(Q!T)));
945         }
946     }
947 }
948 
949 /++
950     Whether the given type is one of the built-in floating-point types, ignoring
951     all qualifiers.
952 
953     $(TABLE
954         $(TR $(TH Floating-Point Types))
955         $(TR $(TD float))
956         $(TR $(TD double))
957         $(TR $(TD real))
958     )
959 
960     Note that this does not include implicit conversions or enum types. The
961     type itself must be one of the built-in floating-point types.
962 
963     This trait does have some similarities with $(D __traits(isFloating, T)),
964     but $(D isFloating) accepts more types than isFloatingPoint does.
965     isFloatingPoint is specifically for testing for the built-in floating-point
966     types, whereas $(D isFloating) tests for a whole set of types that are
967     vaguely float-like (including enums with a base type which is a
968     floating-point type and some of the vector types from core.simd). So, for
969     most code, isFloatingPoint is going to be more appropriate, but obviously,
970     it depends on what the code is trying to do.
971 
972     See also:
973         $(DDSUBLINK spec/traits, isFloating, $(D __traits(isFloating, T)))
974         $(LREF isInteger)
975         $(LREF isSignedInteger)
976         $(LREF isNumeric)
977         $(LREF isUnsignedInteger)
978   +/
979 enum isFloatingPoint(T) = is(immutable T == immutable float) ||
980                           is(immutable T == immutable double) ||
981                           is(immutable T == immutable real);
982 
983 ///
984 @safe unittest
985 {
986     // Some types which are floating-point types.
987     static assert( isFloatingPoint!float);
988     static assert( isFloatingPoint!double);
989     static assert( isFloatingPoint!real);
990 
991     static assert( isFloatingPoint!(const float));
992     static assert( isFloatingPoint!(immutable float));
993     static assert( isFloatingPoint!(inout double));
994     static assert( isFloatingPoint!(shared double));
995     static assert( isFloatingPoint!(const shared real));
996 
997     static assert( isFloatingPoint!(typeof(42.0)));
998     static assert( isFloatingPoint!(typeof(42f)));
999     static assert( isFloatingPoint!(typeof(1e5)));
1000     static assert( isFloatingPoint!(typeof(97.4L)));
1001 
1002     double d;
1003     static assert( isFloatingPoint!(typeof(d)));
1004 
1005     // Some types which aren't floating-point types.
1006     static assert(!isFloatingPoint!bool);
1007     static assert(!isFloatingPoint!char);
1008     static assert(!isFloatingPoint!dchar);
1009     static assert(!isFloatingPoint!int);
1010     static assert(!isFloatingPoint!long);
1011     static assert(!isFloatingPoint!(float[]));
1012     static assert(!isFloatingPoint!(double[4]));
1013     static assert(!isFloatingPoint!(real*));
1014     static assert(!isFloatingPoint!string);
1015 
1016     static struct S
1017     {
1018         double d;
1019     }
1020     static assert(!isFloatingPoint!S);
1021 
1022     // The struct itself isn't considered a floating-point type,
1023     // but its member variable is when checked directly.
1024     static assert( isFloatingPoint!(typeof(S.d)));
1025 
1026     enum E : double
1027     {
1028         a = 12.34
1029     }
1030 
1031     // Enums do not count.
1032     static assert(!isFloatingPoint!E);
1033 
1034     static struct AliasThis
1035     {
1036         double d;
1037         alias this = d;
1038     }
1039 
1040     // Other implicit conversions do not count.
1041     static assert(!isFloatingPoint!AliasThis);
1042 }
1043 
1044 @safe unittest
1045 {
1046     import phobos.sys.meta : Alias, AliasSeq;
1047 
1048     static struct AliasThis(T)
1049     {
1050         T member;
1051         alias this = member;
1052     }
1053 
1054     // The actual core.simd types available vary from system to system, so we
1055     // have to be a bit creative here. The reason that we're testing these types
1056     // is because __traits(isFloating, T) accepts them, but isFloatingPoint is
1057     // not supposed to.
1058     template SIMDTypes()
1059     {
1060         import core.simd;
1061 
1062         alias SIMDTypes = AliasSeq!();
1063         static if (is(int4))
1064             SIMDTypes = AliasSeq!(SIMDTypes, int4);
1065         static if (is(double2))
1066             SIMDTypes = AliasSeq!(SIMDTypes, double2);
1067         static if (is(void16))
1068             SIMDTypes = AliasSeq!(SIMDTypes, void16);
1069     }
1070 
1071     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1072     {
1073         foreach (T; AliasSeq!(float, double, real))
1074         {
1075             enum E : Q!T { a = Q!T.init }
1076 
1077             static assert( isFloatingPoint!(Q!T));
1078             static assert(!isFloatingPoint!E);
1079             static assert(!isFloatingPoint!(AliasThis!(Q!T)));
1080         }
1081 
1082         foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, ubyte, short, ushort,
1083                               int, uint, long, ulong, SIMDTypes!(),
1084                               int[], float[8], real[], void[], double*))
1085         {
1086             enum E : Q!T { a = Q!T.init }
1087 
1088             static assert(!isFloatingPoint!(Q!T));
1089             static assert(!isFloatingPoint!E);
1090             static assert(!isFloatingPoint!(AliasThis!(Q!T)));
1091         }
1092     }
1093 }
1094 
1095 /++
1096     Whether the given type is one of the built-in numeric types, ignoring all
1097     qualifiers. It's equivalent to $(D isInteger!T || isFloatingPoint!T), but
1098     it only involves a single template instantation instead of two.
1099 
1100     $(TABLE
1101         $(TR $(TH Numeric Types))
1102         $(TR $(TD byte))
1103         $(TR $(TD ubyte))
1104         $(TR $(TD short))
1105         $(TR $(TD ushort))
1106         $(TR $(TD int))
1107         $(TR $(TD uint))
1108         $(TR $(TD long))
1109         $(TR $(TD ulong))
1110         $(TR $(TD float))
1111         $(TR $(TD double))
1112         $(TR $(TD real))
1113     )
1114 
1115     Note that this does not include implicit conversions or enum types. The
1116     type itself must be one of the built-in numeric types.
1117 
1118     See_Also:
1119         $(LREF isFloatingPoint)
1120         $(LREF isInteger)
1121         $(LREF isSignedInteger)
1122         $(LREF isUnsignedInteger)
1123   +/
1124 enum isNumeric(T) = is(immutable T == immutable byte) ||
1125                     is(immutable T == immutable ubyte) ||
1126                     is(immutable T == immutable short) ||
1127                     is(immutable T == immutable ushort) ||
1128                     is(immutable T == immutable int) ||
1129                     is(immutable T == immutable uint) ||
1130                     is(immutable T == immutable long) ||
1131                     is(immutable T == immutable ulong) ||
1132                     is(immutable T == immutable float) ||
1133                     is(immutable T == immutable double) ||
1134                     is(immutable T == immutable real);
1135 
1136 ///
1137 @safe unittest
1138 {
1139     // Some types which are numeric types.
1140     static assert( isNumeric!byte);
1141     static assert( isNumeric!ubyte);
1142     static assert( isNumeric!short);
1143     static assert( isNumeric!ushort);
1144     static assert( isNumeric!int);
1145     static assert( isNumeric!uint);
1146     static assert( isNumeric!long);
1147     static assert( isNumeric!ulong);
1148     static assert( isNumeric!float);
1149     static assert( isNumeric!double);
1150     static assert( isNumeric!real);
1151 
1152     static assert( isNumeric!(const short));
1153     static assert( isNumeric!(immutable int));
1154     static assert( isNumeric!(inout uint));
1155     static assert( isNumeric!(shared long));
1156     static assert( isNumeric!(const shared real));
1157 
1158     static assert( isNumeric!(typeof(42)));
1159     static assert( isNumeric!(typeof(1234657890L)));
1160     static assert( isNumeric!(typeof(42.0)));
1161     static assert( isNumeric!(typeof(42f)));
1162     static assert( isNumeric!(typeof(1e5)));
1163     static assert( isNumeric!(typeof(97.4L)));
1164 
1165     int i;
1166     static assert( isNumeric!(typeof(i)));
1167 
1168     // Some types which aren't numeric types.
1169     static assert(!isNumeric!bool);
1170     static assert(!isNumeric!char);
1171     static assert(!isNumeric!dchar);
1172     static assert(!isNumeric!(int[]));
1173     static assert(!isNumeric!(double[4]));
1174     static assert(!isNumeric!(real*));
1175     static assert(!isNumeric!string);
1176 
1177     static struct S
1178     {
1179         int i;
1180     }
1181     static assert(!isNumeric!S);
1182 
1183     // The struct itself isn't considered a numeric type,
1184     // but its member variable is when checked directly.
1185     static assert( isNumeric!(typeof(S.i)));
1186 
1187     enum E : int
1188     {
1189         a = 42
1190     }
1191 
1192     // Enums do not count.
1193     static assert(!isNumeric!E);
1194 
1195     static struct AliasThis
1196     {
1197         int i;
1198         alias this = i;
1199     }
1200 
1201     // Other implicit conversions do not count.
1202     static assert(!isNumeric!AliasThis);
1203 }
1204 
1205 @safe unittest
1206 {
1207     import phobos.sys.meta : Alias, AliasSeq;
1208 
1209     static struct AliasThis(T)
1210     {
1211         T member;
1212         alias this = member;
1213     }
1214 
1215     // The actual core.simd types available vary from system to system, so we
1216     // have to be a bit creative here. The reason that we're testing these types
1217     // is because __traits(isInteger, T) and __traits(isFloating, T) accept
1218     // them, but isNumeric is not supposed to.
1219     template SIMDTypes()
1220     {
1221         import core.simd;
1222 
1223         alias SIMDTypes = AliasSeq!();
1224         static if (is(int4))
1225             SIMDTypes = AliasSeq!(SIMDTypes, int4);
1226         static if (is(double2))
1227             SIMDTypes = AliasSeq!(SIMDTypes, double2);
1228         static if (is(void16))
1229             SIMDTypes = AliasSeq!(SIMDTypes, void16);
1230     }
1231 
1232     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1233     {
1234         foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real))
1235         {
1236             enum E : Q!T { a = Q!T.init }
1237 
1238             static assert( isNumeric!(Q!T));
1239             static assert(!isNumeric!E);
1240             static assert(!isNumeric!(AliasThis!(Q!T)));
1241         }
1242 
1243         foreach (T; AliasSeq!(bool, char, wchar, dchar, SIMDTypes!(),
1244                               int[], float[8], real[], void[], double*))
1245         {
1246             enum E : Q!T { a = Q!T.init }
1247 
1248             static assert(!isNumeric!(Q!T));
1249             static assert(!isNumeric!E);
1250             static assert(!isNumeric!(AliasThis!(Q!T)));
1251         }
1252     }
1253 }
1254 
1255 /++
1256     Whether the given type is a pointer.
1257 
1258     Note that this does not include implicit conversions or enum types. The
1259     type itself must be a pointer.
1260 
1261     Also, remember that unlike C/C++, D's arrays are not pointers. Rather, a
1262     dynamic array in D is a slice of memory which has a member which is a
1263     pointer to its first element and another member which is the length of the
1264     array as $(D size_t). So, a dynamic array / slice has a $(D ptr) member
1265     which is a pointer, but the dynamic array itself is not a pointer.
1266 
1267     See_Also:
1268         $(LREF isDynamicArray)
1269   +/
1270 enum isPointer(T) = is(T == U*, U);
1271 
1272 ///
1273 @system unittest
1274 {
1275     // Some types which are pointers.
1276     static assert( isPointer!(bool*));
1277     static assert( isPointer!(int*));
1278     static assert( isPointer!(int**));
1279     static assert( isPointer!(real*));
1280     static assert( isPointer!(string*));
1281 
1282     static assert( isPointer!(const int*));
1283     static assert( isPointer!(immutable int*));
1284     static assert( isPointer!(inout int*));
1285     static assert( isPointer!(shared int*));
1286     static assert( isPointer!(const shared int*));
1287 
1288     static assert( isPointer!(typeof("foobar".ptr)));
1289 
1290     int* ptr;
1291     static assert( isPointer!(typeof(ptr)));
1292 
1293     int i;
1294     static assert( isPointer!(typeof(&i)));
1295 
1296     // Some types which aren't pointers.
1297     static assert(!isPointer!bool);
1298     static assert(!isPointer!int);
1299     static assert(!isPointer!dchar);
1300     static assert(!isPointer!(int[]));
1301     static assert(!isPointer!(double[4]));
1302     static assert(!isPointer!string);
1303 
1304     static struct S
1305     {
1306         int* ptr;
1307     }
1308     static assert(!isPointer!S);
1309 
1310     // The struct itself isn't considered a numeric type,
1311     // but its member variable is when checked directly.
1312     static assert( isPointer!(typeof(S.ptr)));
1313 
1314     enum E : immutable(char*)
1315     {
1316         a = "foobar".ptr
1317     }
1318 
1319     // Enums do not count.
1320     static assert(!isPointer!E);
1321 
1322     static struct AliasThis
1323     {
1324         int* ptr;
1325         alias this = ptr;
1326     }
1327 
1328     // Other implicit conversions do not count.
1329     static assert(!isPointer!AliasThis);
1330 }
1331 
1332 @safe unittest
1333 {
1334     import phobos.sys.meta : Alias, AliasSeq;
1335 
1336     static struct AliasThis(T)
1337     {
1338         T member;
1339         alias this = member;
1340     }
1341 
1342     static struct S
1343     {
1344         int i;
1345     }
1346 
1347     foreach (Q; AliasSeq!(Alias, ConstOf, ImmutableOf, SharedOf))
1348     {
1349         foreach (T; AliasSeq!(long*, S*, S**, S***, double[]*))
1350         {
1351             enum E : Q!T { a = Q!T.init }
1352 
1353             static assert( isPointer!(Q!T));
1354             static assert(!isPointer!E);
1355             static assert(!isPointer!(AliasThis!(Q!T)));
1356         }
1357 
1358         foreach (T; AliasSeq!(bool, char, wchar, dchar, byte, int, uint, long,
1359                               int[], float[8], real[], void[]))
1360         {
1361             enum E : Q!T { a = Q!T.init }
1362 
1363             static assert(!isPointer!(Q!T));
1364             static assert(!isPointer!E);
1365             static assert(!isPointer!(AliasThis!(Q!T)));
1366         }
1367     }
1368 }
1369 
1370 /++
1371     Evaluates to $(D true) if the given type or symbol is an instantiation of
1372     the given template.
1373 
1374     The overload which takes $(D T) operates on types and indicates whether an
1375     aggregate type (i.e. struct, class, interface, or union) is an
1376     instantiation of the given template.
1377 
1378     The overload which takes $(D Symbol) operates on function templates,
1379     because unlike with aggregate types, the type of a function does not retain
1380     the fact that it was instantiated from a template. So, for functions, it's
1381     necessary to pass the function itself as a symbol rather than pass the type
1382     of the function.
1383 
1384     The overload which takes $(D Symbol) also works with templates which are
1385     not types or functions.
1386 
1387     The single-argument overload makes it so that it can be partially
1388     instantiated with the first argument, which will often be necessary with
1389     template predicates.
1390   +/
1391 template isInstantiationOf(alias Template, T)
1392 if (__traits(isTemplate, Template))
1393 {
1394     enum isInstantiationOf = is(T == Template!Args, Args...);
1395 }
1396 
1397 /++ Ditto +/
1398 template isInstantiationOf(alias Template, alias Symbol)
1399 if (__traits(isTemplate, Template))
1400 {
1401     enum impl(alias T : Template!Args, Args...) = true;
1402     enum impl(alias T) = false;
1403     enum isInstantiationOf = impl!Symbol;
1404 }
1405 
1406 /++ Ditto +/
1407 template isInstantiationOf(alias Template)
1408 if (__traits(isTemplate, Template))
1409 {
1410     enum isInstantiationOf(T) = is(T == Template!Args, Args...);
1411 
1412     template isInstantiationOf(alias Symbol)
1413     {
1414         enum impl(alias T : Template!Args, Args...) = true;
1415         enum impl(alias T) = false;
1416         enum isInstantiationOf = impl!Symbol;
1417     }
1418 }
1419 
1420 /// Examples of templated types.
1421 @safe unittest
1422 {
1423     static struct S(T) {}
1424     static class C(T) {}
1425 
1426     static assert( isInstantiationOf!(S, S!int));
1427     static assert( isInstantiationOf!(S, S!int));
1428     static assert( isInstantiationOf!(S, S!string));
1429     static assert( isInstantiationOf!(S, const S!string));
1430     static assert( isInstantiationOf!(S, shared S!string));
1431     static assert(!isInstantiationOf!(S, int));
1432     static assert(!isInstantiationOf!(S, C!int));
1433     static assert(!isInstantiationOf!(S, C!string));
1434     static assert(!isInstantiationOf!(S, C!(S!int)));
1435 
1436     static assert( isInstantiationOf!(C, C!int));
1437     static assert( isInstantiationOf!(C, C!string));
1438     static assert( isInstantiationOf!(C, const C!string));
1439     static assert( isInstantiationOf!(C, shared C!string));
1440     static assert(!isInstantiationOf!(C, int));
1441     static assert(!isInstantiationOf!(C, S!int));
1442     static assert(!isInstantiationOf!(C, S!string));
1443     static assert(!isInstantiationOf!(C, S!(C!int)));
1444 
1445     static struct Variadic(T...) {}
1446 
1447     static assert( isInstantiationOf!(Variadic, Variadic!()));
1448     static assert( isInstantiationOf!(Variadic, Variadic!int));
1449     static assert( isInstantiationOf!(Variadic, Variadic!(int, string)));
1450     static assert( isInstantiationOf!(Variadic, Variadic!(int, string, int)));
1451     static assert( isInstantiationOf!(Variadic, const Variadic!(int, short)));
1452     static assert( isInstantiationOf!(Variadic, shared Variadic!(int, short)));
1453     static assert(!isInstantiationOf!(Variadic, int));
1454     static assert(!isInstantiationOf!(Variadic, S!int));
1455     static assert(!isInstantiationOf!(Variadic, C!int));
1456 
1457     static struct ValueArg(int i) {}
1458     static assert( isInstantiationOf!(ValueArg, ValueArg!42));
1459     static assert( isInstantiationOf!(ValueArg, ValueArg!256));
1460     static assert( isInstantiationOf!(ValueArg, const ValueArg!1024));
1461     static assert( isInstantiationOf!(ValueArg, shared ValueArg!1024));
1462     static assert(!isInstantiationOf!(ValueArg, int));
1463     static assert(!isInstantiationOf!(ValueArg, S!int));
1464 
1465     int i;
1466 
1467     static struct AliasArg(alias Symbol) {}
1468     static assert( isInstantiationOf!(AliasArg, AliasArg!42));
1469     static assert( isInstantiationOf!(AliasArg, AliasArg!int));
1470     static assert( isInstantiationOf!(AliasArg, AliasArg!i));
1471     static assert( isInstantiationOf!(AliasArg, const AliasArg!i));
1472     static assert( isInstantiationOf!(AliasArg, shared AliasArg!i));
1473     static assert(!isInstantiationOf!(AliasArg, int));
1474     static assert(!isInstantiationOf!(AliasArg, S!int));
1475 
1476     // An uninstantiated template is not an instance of any template,
1477     // not even itself.
1478     static assert(!isInstantiationOf!(S, S));
1479     static assert(!isInstantiationOf!(S, C));
1480     static assert(!isInstantiationOf!(C, C));
1481     static assert(!isInstantiationOf!(C, S));
1482 
1483     // Variables of a templated type are not considered instantiations of that
1484     // type. For templated types, the overload which takes a type must be used.
1485     S!int s;
1486     C!string c;
1487     static assert(!isInstantiationOf!(S, s));
1488     static assert(!isInstantiationOf!(C, c));
1489 }
1490 
1491 // Examples of templated functions.
1492 @safe unittest
1493 {
1494     static int foo(T...)() { return 42; }
1495     static void bar(T...)(T var) {}
1496     static void baz(T)(T var) {}
1497     static bool frobozz(alias pred)(int) { return true; }
1498 
1499     static assert( isInstantiationOf!(foo, foo!int));
1500     static assert( isInstantiationOf!(foo, foo!string));
1501     static assert( isInstantiationOf!(foo, foo!(int, string)));
1502     static assert(!isInstantiationOf!(foo, bar!int));
1503     static assert(!isInstantiationOf!(foo, bar!string));
1504     static assert(!isInstantiationOf!(foo, bar!(int, string)));
1505 
1506     static assert( isInstantiationOf!(bar, bar!int));
1507     static assert( isInstantiationOf!(bar, bar!string));
1508     static assert( isInstantiationOf!(bar, bar!(int, string)));
1509     static assert(!isInstantiationOf!(bar, foo!int));
1510     static assert(!isInstantiationOf!(bar, foo!string));
1511     static assert(!isInstantiationOf!(bar, foo!(int, string)));
1512 
1513     static assert( isInstantiationOf!(baz, baz!int));
1514     static assert( isInstantiationOf!(baz, baz!string));
1515     static assert(!isInstantiationOf!(baz, foo!(int, string)));
1516 
1517     static assert( isInstantiationOf!(frobozz, frobozz!(a => a)));
1518     static assert( isInstantiationOf!(frobozz, frobozz!(a => a > 2)));
1519     static assert(!isInstantiationOf!(frobozz, baz!int));
1520 
1521     // Unfortunately, the function type is not considered an instantiation of
1522     // the template, because that information is not part of the type, unlike
1523     // with templated structs or classes.
1524     static assert(!isInstantiationOf!(foo, typeof(foo!int)));
1525     static assert(!isInstantiationOf!(bar, typeof(bar!int)));
1526 }
1527 
1528 // Examples of templates which aren't types or functions.
1529 @safe unittest
1530 {
1531     template SingleArg(T) {}
1532     template Variadic(T...) {}
1533     template ValueArg(string s) {}
1534     template Alias(alias symbol) {}
1535 
1536     static assert( isInstantiationOf!(SingleArg, SingleArg!int));
1537     static assert( isInstantiationOf!(SingleArg, SingleArg!string));
1538     static assert(!isInstantiationOf!(SingleArg, int));
1539     static assert(!isInstantiationOf!(SingleArg, Variadic!int));
1540 
1541     static assert( isInstantiationOf!(Variadic, Variadic!()));
1542     static assert( isInstantiationOf!(Variadic, Variadic!int));
1543     static assert( isInstantiationOf!(Variadic, Variadic!string));
1544     static assert( isInstantiationOf!(Variadic, Variadic!(short, int, long)));
1545     static assert(!isInstantiationOf!(Variadic, int));
1546     static assert(!isInstantiationOf!(Variadic, SingleArg!int));
1547 
1548     static assert( isInstantiationOf!(ValueArg, ValueArg!"dlang"));
1549     static assert( isInstantiationOf!(ValueArg, ValueArg!"foobar"));
1550     static assert(!isInstantiationOf!(ValueArg, string));
1551     static assert(!isInstantiationOf!(ValueArg, Variadic!string));
1552 
1553     int i;
1554 
1555     static assert( isInstantiationOf!(Alias, Alias!int));
1556     static assert( isInstantiationOf!(Alias, Alias!42));
1557     static assert( isInstantiationOf!(Alias, Alias!i));
1558     static assert(!isInstantiationOf!(Alias, int));
1559     static assert(!isInstantiationOf!(Alias, SingleArg!int));
1560 }
1561 
1562 /// Examples of partial instantation.
1563 @safe unittest
1564 {
1565     static struct SingleArg(T) {}
1566     static struct Variadic(T...) {}
1567 
1568     alias isSingleArg = isInstantiationOf!SingleArg;
1569     alias isVariadic = isInstantiationOf!Variadic;
1570 
1571     static assert( isSingleArg!(SingleArg!int));
1572     static assert( isSingleArg!(const SingleArg!int));
1573     static assert(!isSingleArg!int);
1574     static assert(!isSingleArg!(Variadic!int));
1575 
1576     static assert( isVariadic!(Variadic!()));
1577     static assert( isVariadic!(Variadic!int));
1578     static assert( isVariadic!(shared Variadic!int));
1579     static assert( isVariadic!(Variadic!(int, string)));
1580     static assert(!isVariadic!int);
1581     static assert(!isVariadic!(SingleArg!int));
1582 
1583     T foo(T)(T t) { return t; }
1584     T likeFoo(T)(T t) { return t; }
1585     bool bar(alias pred)(int i) { return pred(i); }
1586 
1587     alias isFoo = isInstantiationOf!foo;
1588     alias isBar = isInstantiationOf!bar;
1589 
1590     static assert( isFoo!(foo!int));
1591     static assert( isFoo!(foo!string));
1592     static assert(!isFoo!int);
1593     static assert(!isFoo!(likeFoo!int));
1594     static assert(!isFoo!(bar!(a => true)));
1595 
1596     static assert( isBar!(bar!(a => true)));
1597     static assert( isBar!(bar!(a => a > 2)));
1598     static assert(!isBar!int);
1599     static assert(!isBar!(foo!int));
1600     static assert(!isBar!(likeFoo!int));
1601 }
1602 
1603 /++
1604     Evaluates to an $(D AliasSeq) containing the members of an enum type.
1605 
1606     The elements of the $(D AliasSeq) are in the same order as they are in the
1607     enum declaration.
1608 
1609     An enum can have multiple members with the same value, so if code needs the
1610     enum values to be unique (e.g. if it's generating a switch statement from
1611     them), then $(REF Unique, phobos, sys, meta) can be used to filter out the
1612     duplicate values - e.g. $(D Unique!(isEqual, EnumMembers!E)).
1613   +/
1614 template EnumMembers(E)
1615 if (is(E == enum))
1616 {
1617     import phobos.sys.meta : AliasSeq;
1618 
1619     alias EnumMembers = AliasSeq!();
1620     static foreach (member; __traits(allMembers, E))
1621         EnumMembers = AliasSeq!(EnumMembers, __traits(getMember, E, member));
1622 }
1623 
1624 /// Create an array of enum values.
1625 @safe unittest
1626 {
1627     enum Sqrts : real
1628     {
1629         one = 1,
1630         two = 1.41421,
1631         three = 1.73205
1632     }
1633     auto sqrts = [EnumMembers!Sqrts];
1634     assert(sqrts == [Sqrts.one, Sqrts.two, Sqrts.three]);
1635 }
1636 
1637 /++
1638     A generic function $(D rank(v)) in the following example uses this template
1639     for finding a member $(D e) in an enum type $(D E).
1640  +/
1641 @safe unittest
1642 {
1643     // Returns i if e is the i-th member of E.
1644     static size_t rank(E)(E e)
1645     if (is(E == enum))
1646     {
1647         static foreach (i, member; EnumMembers!E)
1648         {
1649             if (e == member)
1650                 return i;
1651         }
1652         assert(0, "Not an enum member");
1653     }
1654 
1655     enum Mode
1656     {
1657         read = 1,
1658         write = 2,
1659         map = 4
1660     }
1661     assert(rank(Mode.read) == 0);
1662     assert(rank(Mode.write) == 1);
1663     assert(rank(Mode.map) == 2);
1664 }
1665 
1666 /// Use EnumMembers to generate a switch statement using static foreach.
1667 @safe unittest
1668 {
1669     static class Foo
1670     {
1671         string calledMethod;
1672         void foo() @safe { calledMethod = "foo"; }
1673         void bar() @safe { calledMethod = "bar"; }
1674         void baz() @safe { calledMethod = "baz"; }
1675     }
1676 
1677     enum FuncName : string { foo = "foo", bar = "bar", baz = "baz" }
1678 
1679     auto foo = new Foo;
1680 
1681     s: final switch (FuncName.bar)
1682     {
1683         static foreach (member; EnumMembers!FuncName)
1684         {
1685             // Generate a case for each enum value.
1686             case member:
1687             {
1688                 // Call foo.{enum value}().
1689                 __traits(getMember, foo, member)();
1690                 break s;
1691             }
1692         }
1693     }
1694 
1695     // Since we passed FuncName.bar to the switch statement, the bar member
1696     // function was called.
1697     assert(foo.calledMethod == "bar");
1698 }
1699 
1700 @safe unittest
1701 {
1702     {
1703         enum A { a }
1704         static assert([EnumMembers!A] == [A.a]);
1705         enum B { a, b, c, d, e }
1706         static assert([EnumMembers!B] == [B.a, B.b, B.c, B.d, B.e]);
1707     }
1708     {
1709         enum A : string { a = "alpha", b = "beta" }
1710         static assert([EnumMembers!A] == [A.a, A.b]);
1711 
1712         static struct S
1713         {
1714             int value;
1715             int opCmp(S rhs) const nothrow { return value - rhs.value; }
1716         }
1717         enum B : S { a = S(1), b = S(2), c = S(3) }
1718         static assert([EnumMembers!B] == [B.a, B.b, B.c]);
1719     }
1720     {
1721         enum A { a = 0, b = 0, c = 1, d = 1, e }
1722         static assert([EnumMembers!A] == [A.a, A.b, A.c, A.d, A.e]);
1723     }
1724     {
1725         enum E { member, a = 0, b = 0 }
1726 
1727         static assert(__traits(isSame, EnumMembers!E[0], E.member));
1728         static assert(__traits(isSame, EnumMembers!E[1], E.a));
1729         static assert(__traits(isSame, EnumMembers!E[2], E.b));
1730 
1731         static assert(__traits(identifier, EnumMembers!E[0]) == "member");
1732         static assert(__traits(identifier, EnumMembers!E[1]) == "a");
1733         static assert(__traits(identifier, EnumMembers!E[2]) == "b");
1734     }
1735 }
1736 
1737 // https://issues.dlang.org/show_bug.cgi?id=14561: huge enums
1738 @safe unittest
1739 {
1740     static string genEnum()
1741     {
1742         string result = "enum TLAs {";
1743         foreach (c0; '0' .. '2' + 1)
1744         {
1745             foreach (c1; '0' .. '9' + 1)
1746             {
1747                 foreach (c2; '0' .. '9' + 1)
1748                 {
1749                     foreach (c3; '0' .. '9' + 1)
1750                     {
1751                         result ~= '_';
1752                         result ~= c0;
1753                         result ~= c1;
1754                         result ~= c2;
1755                         result ~= c3;
1756                         result ~= ',';
1757                     }
1758                 }
1759             }
1760         }
1761         result ~= '}';
1762         return result;
1763     }
1764     mixin(genEnum);
1765     static assert(EnumMembers!TLAs[0] == TLAs._0000);
1766     static assert(EnumMembers!TLAs[$ - 1] == TLAs._2999);
1767 }
1768 
1769 /++
1770     Whether the type $(D From) is implicitly convertible to the type $(D To).
1771 
1772     Note that template constraints should be very careful about when they test
1773     for implicit conversions and in general should prefer to either test for an
1774     exact set of types or for types which compile with a particular piece of
1775     code rather than being designed to accept any type which implicitly converts
1776     to a particular type.
1777 
1778     This is because having a type pass a template constraint based on an
1779     implicit conversion but then not have the implicit conversion actually take
1780     place (which it won't unless the template does something to force it
1781     internally) can lead to either compilation errors or subtle behavioral
1782     differences - and even when the conversion is done explicitly within a
1783     templated function, since it's not done at the call site, it can still lead
1784     to subtle bugs in some cases (e.g. if slicing a static array is involved).
1785 
1786     For situations where code needs to verify that a type is implicitly
1787     convertible based solely on its qualifiers, $(LREF isQualifierConvertible)
1788     would be a more appropriate choice than isImplicitlyConvertible.
1789 
1790     Given how trivial the $(D is) expression for isImplicitlyConvertible is -
1791     $(D is(To : From)) - this trait is provided primarily so that it can be
1792     used in conjunction with templates that use a template predicate (such as
1793     many of the templates in phobos.sys.meta).
1794 
1795     The single-argument overload makes it so that it can be partially
1796     instantiated with the first argument, which will often be necessary with
1797     template predicates.
1798 
1799     See_Also:
1800         $(DDSUBLINK dlang.org/spec/type, implicit-conversions, Spec on implicit conversions)
1801         $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions)
1802         $(LREF isQualifierConvertible)
1803   +/
1804 enum isImplicitlyConvertible(From, To) = is(From : To);
1805 
1806 /++ Ditto +/
1807 template isImplicitlyConvertible(From)
1808 {
1809     enum isImplicitlyConvertible(To) = is(From : To);
1810 }
1811 
1812 ///
1813 @safe unittest
1814 {
1815     static assert( isImplicitlyConvertible!(byte, long));
1816     static assert( isImplicitlyConvertible!(ushort, long));
1817     static assert( isImplicitlyConvertible!(int, long));
1818     static assert( isImplicitlyConvertible!(long, long));
1819     static assert( isImplicitlyConvertible!(ulong, long));
1820 
1821     static assert( isImplicitlyConvertible!(ubyte, int));
1822     static assert( isImplicitlyConvertible!(short, int));
1823     static assert( isImplicitlyConvertible!(int, int));
1824     static assert( isImplicitlyConvertible!(uint, int));
1825     static assert(!isImplicitlyConvertible!(long, int));
1826     static assert(!isImplicitlyConvertible!(ulong, int));
1827 
1828     static assert(!isImplicitlyConvertible!(int, string));
1829     static assert(!isImplicitlyConvertible!(int, int[]));
1830     static assert(!isImplicitlyConvertible!(int, int*));
1831 
1832     static assert(!isImplicitlyConvertible!(string, int));
1833     static assert(!isImplicitlyConvertible!(int[], int));
1834     static assert(!isImplicitlyConvertible!(int*, int));
1835 
1836     // For better or worse, bool and the built-in character types will
1837     // implicitly convert to integer or floating-point types if the target type
1838     // is large enough. Sometimes, this is desirable, whereas at other times,
1839     // it can have very surprising results, so it's one reason why code should
1840     // be very careful when testing for implicit conversions.
1841     static assert( isImplicitlyConvertible!(bool, int));
1842     static assert( isImplicitlyConvertible!(char, int));
1843     static assert( isImplicitlyConvertible!(wchar, int));
1844     static assert( isImplicitlyConvertible!(dchar, int));
1845 
1846     static assert( isImplicitlyConvertible!(bool, ubyte));
1847     static assert( isImplicitlyConvertible!(char, ubyte));
1848     static assert(!isImplicitlyConvertible!(wchar, ubyte));
1849     static assert(!isImplicitlyConvertible!(dchar, ubyte));
1850 
1851     static assert( isImplicitlyConvertible!(bool, double));
1852     static assert( isImplicitlyConvertible!(char, double));
1853     static assert( isImplicitlyConvertible!(wchar, double));
1854     static assert( isImplicitlyConvertible!(dchar, double));
1855 
1856     // Value types can be implicitly converted regardless of their qualifiers
1857     // thanks to the fact that they're copied.
1858     static assert( isImplicitlyConvertible!(int, int));
1859     static assert( isImplicitlyConvertible!(const int, int));
1860     static assert( isImplicitlyConvertible!(immutable int, int));
1861     static assert( isImplicitlyConvertible!(inout int, int));
1862 
1863     static assert( isImplicitlyConvertible!(int, const int));
1864     static assert( isImplicitlyConvertible!(int, immutable int));
1865     static assert( isImplicitlyConvertible!(int, inout int));
1866 
1867     // Reference types are far more restrictive about which implicit conversions
1868     // they allow, because qualifiers in D are transitive.
1869     static assert( isImplicitlyConvertible!(int*, int*));
1870     static assert(!isImplicitlyConvertible!(const int*, int*));
1871     static assert(!isImplicitlyConvertible!(immutable int*, int*));
1872 
1873     static assert( isImplicitlyConvertible!(int*, const int*));
1874     static assert( isImplicitlyConvertible!(const int*, const int*));
1875     static assert( isImplicitlyConvertible!(immutable int*, const int*));
1876 
1877     static assert(!isImplicitlyConvertible!(int*, immutable int*));
1878     static assert(!isImplicitlyConvertible!(const int*, immutable int*));
1879     static assert( isImplicitlyConvertible!(immutable int*, immutable int*));
1880 
1881     // Note that inout gets a bit weird, since it's only used with function
1882     // parameters, and it's a stand-in for whatever mutability qualifiers the
1883     // type actually has. So, a function parameter that's inout accepts any
1884     // mutability, but you can't actually implicitly convert to inout, because
1885     // it's unknown within the function what the actual mutability of the type
1886     // is. It will differ depending on the function arguments of a specific
1887     // call to that function, so the same code has to work with all combinations
1888     // of mutability qualifiers.
1889     static assert(!isImplicitlyConvertible!(int*, inout int*));
1890     static assert(!isImplicitlyConvertible!(const int*, inout int*));
1891     static assert(!isImplicitlyConvertible!(immutable int*, inout int*));
1892     static assert( isImplicitlyConvertible!(inout int*, inout int*));
1893 
1894     static assert(!isImplicitlyConvertible!(inout int*, int*));
1895     static assert( isImplicitlyConvertible!(inout int*, const int*));
1896     static assert(!isImplicitlyConvertible!(inout int*, immutable int*));
1897 
1898     // Enums implicitly convert to their base type.
1899     enum E : int
1900     {
1901         a = 42
1902     }
1903     static assert( isImplicitlyConvertible!(E, int));
1904     static assert( isImplicitlyConvertible!(E, long));
1905     static assert(!isImplicitlyConvertible!(E, int[]));
1906 
1907     // Structs only implicit convert to another type via declaring an
1908     // alias this.
1909     static struct S
1910     {
1911         int i;
1912     }
1913     static assert(!isImplicitlyConvertible!(S, int));
1914     static assert(!isImplicitlyConvertible!(S, long));
1915     static assert(!isImplicitlyConvertible!(S, string));
1916 
1917     static struct AliasThis
1918     {
1919         int i;
1920         alias this = i;
1921     }
1922     static assert( isImplicitlyConvertible!(AliasThis, int));
1923     static assert( isImplicitlyConvertible!(AliasThis, long));
1924     static assert(!isImplicitlyConvertible!(AliasThis, string));
1925 
1926     static struct AliasThis2
1927     {
1928         AliasThis at;
1929         alias this = at;
1930     }
1931     static assert( isImplicitlyConvertible!(AliasThis2, AliasThis));
1932     static assert( isImplicitlyConvertible!(AliasThis2, int));
1933     static assert( isImplicitlyConvertible!(AliasThis2, long));
1934     static assert(!isImplicitlyConvertible!(AliasThis2, string));
1935 
1936     static struct AliasThis3
1937     {
1938         AliasThis2 at;
1939         alias this = at;
1940     }
1941     static assert( isImplicitlyConvertible!(AliasThis3, AliasThis2));
1942     static assert( isImplicitlyConvertible!(AliasThis3, AliasThis));
1943     static assert( isImplicitlyConvertible!(AliasThis3, int));
1944     static assert( isImplicitlyConvertible!(AliasThis3, long));
1945     static assert(!isImplicitlyConvertible!(AliasThis3, string));
1946 
1947     // D does not support implicit conversions via construction.
1948     static struct Cons
1949     {
1950         this(int i)
1951         {
1952             this.i = i;
1953         }
1954 
1955         int i;
1956     }
1957     static assert(!isImplicitlyConvertible!(int, Cons));
1958 
1959     // Classes support implicit conversion based on their class and
1960     // interface hierarchies.
1961     static interface I1 {}
1962     static class Base : I1 {}
1963 
1964     static interface I2 {}
1965     static class Foo : Base, I2 {}
1966 
1967     static class Bar : Base {}
1968 
1969     static assert( isImplicitlyConvertible!(Base, Base));
1970     static assert(!isImplicitlyConvertible!(Base, Foo));
1971     static assert(!isImplicitlyConvertible!(Base, Bar));
1972     static assert( isImplicitlyConvertible!(Base, I1));
1973     static assert(!isImplicitlyConvertible!(Base, I2));
1974 
1975     static assert( isImplicitlyConvertible!(Foo, Base));
1976     static assert( isImplicitlyConvertible!(Foo, Foo));
1977     static assert(!isImplicitlyConvertible!(Foo, Bar));
1978     static assert( isImplicitlyConvertible!(Foo, I1));
1979     static assert( isImplicitlyConvertible!(Foo, I2));
1980 
1981     static assert( isImplicitlyConvertible!(Bar, Base));
1982     static assert(!isImplicitlyConvertible!(Bar, Foo));
1983     static assert( isImplicitlyConvertible!(Bar, Bar));
1984     static assert( isImplicitlyConvertible!(Bar, I1));
1985     static assert(!isImplicitlyConvertible!(Bar, I2));
1986 
1987     static assert(!isImplicitlyConvertible!(I1, Base));
1988     static assert(!isImplicitlyConvertible!(I1, Foo));
1989     static assert(!isImplicitlyConvertible!(I1, Bar));
1990     static assert( isImplicitlyConvertible!(I1, I1));
1991     static assert(!isImplicitlyConvertible!(I1, I2));
1992 
1993     static assert(!isImplicitlyConvertible!(I2, Base));
1994     static assert(!isImplicitlyConvertible!(I2, Foo));
1995     static assert(!isImplicitlyConvertible!(I2, Bar));
1996     static assert(!isImplicitlyConvertible!(I2, I1));
1997     static assert( isImplicitlyConvertible!(I2, I2));
1998 
1999     // Note that arrays are not implicitly convertible even when their elements
2000     // are implicitly convertible.
2001     static assert(!isImplicitlyConvertible!(ubyte[], uint[]));
2002     static assert(!isImplicitlyConvertible!(Foo[], Base[]));
2003     static assert(!isImplicitlyConvertible!(Bar[], Base[]));
2004 
2005     // However, like with pointers, dynamic arrays are convertible based on
2006     // constness.
2007     static assert( isImplicitlyConvertible!(Base[], const Base[]));
2008     static assert( isImplicitlyConvertible!(Base[], const(Base)[]));
2009     static assert(!isImplicitlyConvertible!(Base[], immutable(Base)[]));
2010     static assert(!isImplicitlyConvertible!(const Base[], immutable Base[]));
2011     static assert( isImplicitlyConvertible!(const Base[], const Base[]));
2012     static assert(!isImplicitlyConvertible!(const Base[], immutable Base[]));
2013 }
2014 
2015 /++
2016     isImplicitlyConvertible can be used with partial instantiation so that it
2017     can be passed to a template which takes a unary predicate.
2018   +/
2019 @safe unittest
2020 {
2021     import phobos.sys.meta : AliasSeq, all, indexOf;
2022 
2023     // byte is implicitly convertible to byte, short, int, and long.
2024     static assert(all!(isImplicitlyConvertible!byte, short, int, long));
2025 
2026     // const(char)[] at index 2 is the first type in the AliasSeq which string
2027     // can be implicitly converted to.
2028     alias Types = AliasSeq!(int, char[], const(char)[], string, int*);
2029     static assert(indexOf!(isImplicitlyConvertible!string, Types) == 2);
2030 }
2031 
2032 /++
2033     Whether $(D From) is
2034     $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible)
2035     to $(D To).
2036 
2037     This is testing whether $(D From) and $(D To) are the same type - minus the
2038     qualifiers - and whether the qualifiers on $(D From) can be implicitly
2039     converted to the qualifiers on $(D To). No other implicit conversions are
2040     taken into account.
2041 
2042     For instance, $(D const int*) is not implicitly convertible to $(D int*),
2043     because that would violate $(D const). That means that $(D const) is not
2044     qualifier convertible to mutable. And as such, $(I any) $(D const) type
2045     is not qualifier convertible to a mutable type even if it's implicitly
2046     convertible. E.G. $(D const int) is implicitly convertible to $(D int),
2047     because it can be copied to avoid violating $(D const), but it's still not
2048     qualifier convertible, because $(D const) types in general cannot be
2049     implicitly converted to mutable.
2050 
2051     The exact types being tested matter, because they need to be the same
2052     (minus the qualifiers) in order to be considered convertible, but beyond
2053     that, all that matters for the conversion is whether those qualifers would
2054     be convertible regardless of which types they were on. So, if you're having
2055     trouble picturing whether $(D From) would be qualifier convertible to
2056     $(D To), then consider which conversions would be allowed from $(D From[])
2057     to $(D To[]) (and remember that dynamic arrays are only implicitly
2058     convertible based on their qualifers).
2059 
2060     The $(DDSUBLINK spec/const3, implicit_qualifier_conversions, spec) provides
2061     a table of which qualifiers can be implcitly converted to which other
2062     qualifers (and of course, there a bunch of examples below).
2063 
2064     So, isQualifierConvertible can be used in a case like
2065     $(D isQualifierConvertible!(ReturnType!(typeof(foo(bar))), const char),
2066     which would be testing that the return type of $(D foo(bar)) was $(D char),
2067     $(D const char), or $(D immutable char) (since those are the only types
2068     which are qualifier convertible to $(D const char)).
2069 
2070     This is in contrast to
2071     $(D isImplicitlyConvertible!(ReturnType!(typeof(foo(bar))), const char),
2072     which would be $(D true) for $(I any) type which was implicitly convertible
2073     to $(D const char) rather than just $(D char), $(D const char), and
2074     $(D immutable char).
2075 
2076     The single-argument overload makes it so that it can be partially
2077     instantiated with the first argument, which will often be necessary with
2078     template predicates.
2079 
2080     See_Also:
2081         $(DDSUBLINK spec/const3, implicit_qualifier_conversions, Spec for implicit qualifier conversions)
2082         $(LREF isImplicitlyConvertible)
2083   +/
2084 enum isQualifierConvertible(From, To) = is(immutable From == immutable To) && is(From* : To*);
2085 
2086 /++ Ditto +/
2087 template isQualifierConvertible(From)
2088 {
2089     enum isQualifierConvertible(To) =  is(immutable From == immutable To) && is(From* : To*);
2090 }
2091 
2092 ///
2093 @safe unittest
2094 {
2095     // i.e. char* -> const char*
2096     static assert( isQualifierConvertible!(char, const char));
2097 
2098     // i.e. const char* -> char*
2099     static assert(!isQualifierConvertible!(const char, char));
2100 
2101     static assert( isQualifierConvertible!(int, int));
2102     static assert( isQualifierConvertible!(int, const int));
2103     static assert(!isQualifierConvertible!(int, immutable int));
2104 
2105     static assert(!isQualifierConvertible!(const int, int));
2106     static assert( isQualifierConvertible!(const int, const int));
2107     static assert(!isQualifierConvertible!(const int, immutable int));
2108 
2109     static assert(!isQualifierConvertible!(immutable int, int));
2110     static assert( isQualifierConvertible!(immutable int, const int));
2111     static assert( isQualifierConvertible!(immutable int, immutable int));
2112 
2113     // Note that inout gets a bit weird, since it's only used with function
2114     // parameters, and it's a stand-in for whatever mutability qualifiers the
2115     // type actually has. So, a function parameter that's inout accepts any
2116     // mutability, but you can't actually implicitly convert to inout, because
2117     // it's unknown within the function what the actual mutability of the type
2118     // is. It will differ depending on the function arguments of a specific
2119     // call to that function, so the same code has to work with all combinations
2120     // of mutability qualifiers.
2121     static assert(!isQualifierConvertible!(int, inout int));
2122     static assert(!isQualifierConvertible!(const int, inout int));
2123     static assert(!isQualifierConvertible!(immutable int, inout int));
2124     static assert( isQualifierConvertible!(inout int, inout int));
2125 
2126     static assert(!isQualifierConvertible!(inout int, int));
2127     static assert( isQualifierConvertible!(inout int, const int));
2128     static assert(!isQualifierConvertible!(inout int, immutable int));
2129 
2130     // shared is of course also a qualifier.
2131     static assert(!isQualifierConvertible!(int, shared int));
2132     static assert(!isQualifierConvertible!(int, const shared int));
2133     static assert(!isQualifierConvertible!(const int, shared int));
2134     static assert(!isQualifierConvertible!(const int, const shared int));
2135     static assert(!isQualifierConvertible!(immutable int, shared int));
2136     static assert( isQualifierConvertible!(immutable int, const shared int));
2137 
2138     static assert(!isQualifierConvertible!(shared int, int));
2139     static assert(!isQualifierConvertible!(shared int, const int));
2140     static assert(!isQualifierConvertible!(shared int, immutable int));
2141     static assert( isQualifierConvertible!(shared int, shared int));
2142     static assert( isQualifierConvertible!(shared int, const shared int));
2143 
2144     static assert(!isQualifierConvertible!(const shared int, int));
2145     static assert(!isQualifierConvertible!(const shared int, const int));
2146     static assert(!isQualifierConvertible!(const shared int, immutable int));
2147     static assert(!isQualifierConvertible!(const shared int, shared int));
2148     static assert( isQualifierConvertible!(const shared int, const shared int));
2149 
2150     // Implicit conversions don't count unless they're based purely on
2151     // qualifiers.
2152     enum E : int
2153     {
2154         a = 1
2155     }
2156 
2157     static assert(!isQualifierConvertible!(E, int));
2158     static assert(!isQualifierConvertible!(E, const int));
2159     static assert( isQualifierConvertible!(E, E));
2160     static assert( isQualifierConvertible!(E, const E));
2161     static assert(!isQualifierConvertible!(E, immutable E));
2162 
2163     static struct AliasThis
2164     {
2165         int i;
2166         alias this = i;
2167     }
2168 
2169     static assert(!isQualifierConvertible!(AliasThis, int));
2170     static assert(!isQualifierConvertible!(AliasThis, const int));
2171     static assert( isQualifierConvertible!(AliasThis, AliasThis));
2172     static assert( isQualifierConvertible!(AliasThis, const AliasThis));
2173     static assert(!isQualifierConvertible!(AliasThis, immutable AliasThis));
2174 
2175     // The qualifiers are irrelevant if the types aren't the same when
2176     // stripped of all qualifers.
2177     static assert(!isQualifierConvertible!(int, long));
2178     static assert(!isQualifierConvertible!(int, const long));
2179     static assert(!isQualifierConvertible!(string, const(ubyte)[]));
2180 }
2181 
2182 /++
2183     isQualifierConvertible can be used with partial instantiation so that it
2184     can be passed to a template which takes a unary predicate.
2185   +/
2186 @safe unittest
2187 {
2188     import phobos.sys.meta : AliasSeq, all, indexOf;
2189 
2190     // byte is qualifier convertible to byte and const byte.
2191     static assert(all!(isQualifierConvertible!byte, byte, const byte));
2192 
2193     // const(char[]) at index 2 is the first type in the AliasSeq which string
2194     // is qualifier convertible to.
2195     alias Types = AliasSeq!(int, char[], const(char[]), string, int*);
2196     static assert(indexOf!(isQualifierConvertible!string, Types) == 2);
2197 }
2198 
2199 @safe unittest
2200 {
2201     import phobos.sys.meta : AliasSeq;
2202 
2203     alias Types = AliasSeq!(int, const int, shared int, inout int, const shared int,
2204                             const inout int, inout shared int, const inout shared int, immutable int);
2205 
2206     // https://dlang.org/spec/const3.html#implicit_qualifier_conversions
2207     enum _ = 0;
2208     static immutable bool[Types.length][Types.length] conversions = [
2209     //   m   c   s   i   cs  ci  is  cis im
2210         [1,  1,  _,  _,  _,  _,  _,  _,  _],  // mutable
2211         [_,  1,  _,  _,  _,  _,  _,  _,  _],  // const
2212         [_,  _,  1,  _,  1,  _,  _,  _,  _],  // shared
2213         [_,  1,  _,  1,  _,  1,  _,  _,  _],  // inout
2214         [_,  _,  _,  _,  1,  _,  _,  _,  _],  // const shared
2215         [_,  1,  _,  _,  _,  1,  _,  _,  _],  // const inout
2216         [_,  _,  _,  _,  1,  _,  1,  1,  _],  // inout shared
2217         [_,  _,  _,  _,  1,  _,  _,  1,  _],  // const inout shared
2218         [_,  1,  _,  _,  1,  1,  _,  1,  1],  // immutable
2219     ];
2220 
2221     foreach (i, From; Types)
2222     {
2223         foreach (j, To; Types)
2224         {
2225             static assert(isQualifierConvertible!(From, To) == conversions[i][j],
2226                           "`isQualifierConvertible!(" ~ From.stringof ~ ", " ~ To.stringof ~ ")`" ~
2227                           " should be `" ~ (conversions[i][j] ? "true`" : "false`"));
2228         }
2229     }
2230 }
2231 
2232 /++
2233     Whether the given values are equal per $(D ==).
2234 
2235     All this does is $(D lhs == rhs) but in an eponymous template, so most code
2236     shouldn't use it. It's intended to be used in conjunction with templates
2237     that take a template predicate - such as those in phobos.sys.meta.
2238 
2239     The single-argument overload makes it so that it can be partially
2240     instantiated with the first argument, which will often be necessary with
2241     template predicates.
2242 
2243     Note that in most cases, even when comparing values at compile time, using
2244     isEqual makes no sense, because you can use CTFE to just compare two values
2245     (or expressions which evaluate to values), but in rare cases where you need
2246     to compare symbols in an $(D AliasSeq) by value with a template predicate
2247     while still leaving them as symbols in an $(D AliasSeq), then isEqual would
2248     be needed.
2249 
2250     A prime example of this would be $(D Unique!(isEqual, EnumMembers!MyEnum)),
2251     which results in an $(D AliasSeq) containing the list of members of
2252     $(D MyEnum) but without any duplicate values (e.g. to use when doing code
2253     generation to create a final switch).
2254 
2255     Alternatively, code such as $(D [EnumMembers!MyEnum].sort().unique()) could
2256     be used to get a dynamic array of the enum members with no duplicate values
2257     via CTFE, thus avoiding the need for template predicates or anything from
2258     phobos.sys.meta. However, you then have a dynamic array of enum values
2259     rather than an $(D AliasSeq) of symbols for those enum members, which
2260     affects what you can do with type introspection. So, which approach is
2261     better depends on what the code needs to do with the enum members.
2262 
2263     In general, however, if code doesn't need an $(D AliasSeq), and an array of
2264     values will do the trick, then it's more efficient to operate on an array of
2265     values with CTFE and avoid using isEqual or other templates to operate on
2266     the values as an $(D AliasSeq).
2267 
2268     See_Also:
2269         $(LREF isSameSymbol)
2270         $(LREF isSameType)
2271   +/
2272 enum isEqual(alias lhs, alias rhs) = lhs == rhs;
2273 
2274 /++ Ditto +/
2275 template isEqual(alias lhs)
2276 {
2277     enum isEqual(alias rhs) = lhs == rhs;
2278 }
2279 
2280 /// It acts just like ==, but it's a template.
2281 @safe unittest
2282 {
2283     enum a = 42;
2284 
2285     static assert( isEqual!(a, 42));
2286     static assert( isEqual!(20, 10 + 10));
2287 
2288     static assert(!isEqual!(a, 120));
2289     static assert(!isEqual!(77, 19 * 7 + 2));
2290 
2291     // b cannot be read at compile time, so it won't work with isEqual.
2292     int b = 99;
2293     static assert(!__traits(compiles, isEqual!(b, 99)));
2294 }
2295 
2296 /++
2297     Comparing some of the differences between an $(D AliasSeq) of enum members
2298     and an array of enum values created from an $(D AliasSeq) of enum members.
2299   +/
2300 @safe unittest
2301 {
2302     import phobos.sys.meta : AliasSeq, Unique;
2303 
2304     enum E
2305     {
2306         a = 0,
2307         b = 22,
2308         c = 33,
2309         d = 0,
2310         e = 256,
2311         f = 33,
2312         g = 7
2313     }
2314 
2315     alias uniqueMembers = Unique!(isEqual, EnumMembers!E);
2316     static assert(uniqueMembers.length == 5);
2317 
2318     static assert(__traits(isSame, uniqueMembers[0], E.a));
2319     static assert(__traits(isSame, uniqueMembers[1], E.b));
2320     static assert(__traits(isSame, uniqueMembers[2], E.c));
2321     static assert(__traits(isSame, uniqueMembers[3], E.e));
2322     static assert(__traits(isSame, uniqueMembers[4], E.g));
2323 
2324     static assert(__traits(identifier, uniqueMembers[0]) == "a");
2325     static assert(__traits(identifier, uniqueMembers[1]) == "b");
2326     static assert(__traits(identifier, uniqueMembers[2]) == "c");
2327     static assert(__traits(identifier, uniqueMembers[3]) == "e");
2328     static assert(__traits(identifier, uniqueMembers[4]) == "g");
2329 
2330     // Same value but different symbol.
2331     static assert(uniqueMembers[0] == E.d);
2332     static assert(!__traits(isSame, uniqueMembers[0], E.d));
2333 
2334     // is expressions compare types, not symbols or values, and these AliasSeqs
2335     // contain the list of symbols for the enum members, not types, so the is
2336     // expression evaluates to false even though the symbols are the same.
2337     static assert(!is(uniqueMembers == AliasSeq!(E.a, E.b, E.c, E.e, E.g)));
2338 
2339     // Once the members are converted to an array, the types are the same, and
2340     // the values are the same, but the symbols are not the same. Instead of
2341     // being the symbols E.a, E.b, etc., they're just values with the type E
2342     // which match the values of E.a, E.b, etc.
2343     enum arr = [uniqueMembers];
2344     static assert(is(typeof(arr) == E[]));
2345 
2346     static assert(arr == [E.a, E.b, E.c, E.e, E.g]);
2347     static assert(arr == [E.d, E.b, E.f, E.e, E.g]);
2348 
2349     static assert(!__traits(isSame, arr[0], E.a));
2350     static assert(!__traits(isSame, arr[1], E.b));
2351     static assert(!__traits(isSame, arr[2], E.c));
2352     static assert(!__traits(isSame, arr[3], E.e));
2353     static assert(!__traits(isSame, arr[4], E.g));
2354 
2355     // Since arr[0] is just a value of type E, it's no longer the symbol, E.a,
2356     // even though its type is E, and its value is the same as that of E.a. And
2357     // unlike the actual members of an enum, an element of an array does not
2358     // have an identifier, so __traits(identifier, ...) doesn't work with it.
2359     static assert(!__traits(compiles, __traits(identifier, arr[0])));
2360 
2361     // Similarly, once an enum member from the AliasSeq is assigned to a
2362     // variable, __traits(identifer, ...) operates on the variable, not the
2363     // symbol from the AliasSeq or the value of the variable.
2364     auto var = uniqueMembers[0];
2365     static assert(__traits(identifier, var) == "var");
2366 
2367     // The same with a manifest constant.
2368     enum constant = uniqueMembers[0];
2369     static assert(__traits(identifier, constant) == "constant");
2370 }
2371 
2372 /++
2373     Whether the given symbols are the same symbol.
2374 
2375     All this does is $(D __traits(isSame, lhs, rhs)), so most code shouldn't
2376     use it. It's intended to be used in conjunction with templates that take a
2377     template predicate - such as those in phobos.sys.meta.
2378 
2379     The single-argument overload makes it so that it can be partially
2380     instantiated with the first argument, which will often be necessary with
2381     template predicates.
2382 
2383     See_Also:
2384         $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, lhs, rhs)))
2385         $(LREF isEqual)
2386         $(LREF isSameType)
2387   +/
2388 enum isSameSymbol(alias lhs, alias rhs) = __traits(isSame, lhs, rhs);
2389 
2390 /++ Ditto +/
2391 template isSameSymbol(alias lhs)
2392 {
2393     enum isSameSymbol(alias rhs) = __traits(isSame, lhs, rhs);
2394 }
2395 
2396 ///
2397 @safe unittest
2398 {
2399     int i;
2400     int j;
2401     real r;
2402 
2403     static assert( isSameSymbol!(i, i));
2404     static assert(!isSameSymbol!(i, j));
2405     static assert(!isSameSymbol!(i, r));
2406 
2407     static assert(!isSameSymbol!(j, i));
2408     static assert( isSameSymbol!(j, j));
2409     static assert(!isSameSymbol!(j, r));
2410 
2411     static assert(!isSameSymbol!(r, i));
2412     static assert(!isSameSymbol!(r, j));
2413     static assert( isSameSymbol!(r, r));
2414 
2415     auto foo() { return 0; }
2416     auto bar() { return 0; }
2417 
2418     static assert( isSameSymbol!(foo, foo));
2419     static assert(!isSameSymbol!(foo, bar));
2420     static assert(!isSameSymbol!(foo, i));
2421 
2422     static assert(!isSameSymbol!(bar, foo));
2423     static assert( isSameSymbol!(bar, bar));
2424     static assert(!isSameSymbol!(bar, i));
2425 
2426     // Types are symbols too. However, in most cases, they should be compared
2427     // as types, not symbols (be it with is expressions or with isSameType),
2428     // because the results aren't consistent between scalar types and
2429     // user-defined types with regards to type qualifiers when they're compared
2430     // as symbols.
2431     static assert( isSameSymbol!(double, double));
2432     static assert(!isSameSymbol!(double, const double));
2433     static assert(!isSameSymbol!(double, int));
2434     static assert( isSameSymbol!(Object, Object));
2435     static assert( isSameSymbol!(Object, const Object));
2436 
2437     static assert(!isSameSymbol!(i, int));
2438     static assert( isSameSymbol!(typeof(i), int));
2439 
2440     // Lambdas can be compared with __traits(isSame, ...),
2441     // so they can be compared with isSameSymbol.
2442     static assert( isSameSymbol!(a => a + 42, a => a + 42));
2443     static assert(!isSameSymbol!(a => a + 42, a => a + 99));
2444 
2445     // Partial instantiation allows it to be used with templates that expect
2446     // a predicate that takes only a single argument.
2447     import phobos.sys.meta : AliasSeq, indexOf;
2448     alias Types = AliasSeq!(i, j, r, int, long, foo);
2449     static assert(indexOf!(isSameSymbol!j, Types) == 1);
2450     static assert(indexOf!(isSameSymbol!int, Types) == 3);
2451     static assert(indexOf!(isSameSymbol!bar, Types) == -1);
2452 }
2453 
2454 /++
2455     Whether the given types are the same type.
2456 
2457     All this does is $(D is(T == U)), so most code shouldn't use it. It's
2458     intended to be used in conjunction with templates that take a template
2459     predicate - such as those in phobos.sys.meta.
2460 
2461     The single-argument overload makes it so that it can be partially
2462     instantiated with the first argument, which will often be necessary with
2463     template predicates.
2464 
2465     See_Also:
2466         $(LREF isEqual)
2467         $(LREF isSameSymbol)
2468   +/
2469 enum isSameType(T, U) = is(T == U);
2470 
2471 /++ Ditto +/
2472 template isSameType(T)
2473 {
2474     enum isSameType(U) = is(T == U);
2475 }
2476 
2477 ///
2478 @safe unittest
2479 {
2480     static assert( isSameType!(long, long));
2481     static assert(!isSameType!(long, const long));
2482     static assert(!isSameType!(long, string));
2483     static assert( isSameType!(string, string));
2484 
2485     int i;
2486     real r;
2487     static assert( isSameType!(int, typeof(i)));
2488     static assert(!isSameType!(int, typeof(r)));
2489 
2490     static assert(!isSameType!(real, typeof(i)));
2491     static assert( isSameType!(real, typeof(r)));
2492 
2493     // Partial instantiation allows it to be used with templates that expect
2494     // a predicate that takes only a single argument.
2495     import phobos.sys.meta : AliasSeq, indexOf;
2496     alias Types = AliasSeq!(float, string, int, double);
2497     static assert(indexOf!(isSameType!int, Types) == 2);
2498 }
2499 
2500 /++
2501     Evaluates to an $(D AliasSeq) of the names (as $(D string)s) of the member
2502     variables of an aggregate type (i.e. a struct, class, interface, or union).
2503 
2504     These are fields which take up memory space within an instance of the type
2505     (i.e. not enums / manifest constants, since they don't take up memory
2506     space, and not static member variables, since they don't take up memory
2507     space within an instance).
2508 
2509     Hidden fields (like the virtual function table pointer or the context
2510     pointer for nested types) are not included.
2511 
2512     For classes, only the direct member variables are included and not those
2513     of any base classes.
2514 
2515     For interfaces, the result of FieldNames is always empty, because
2516     interfaces cannot have member variables. However, because interfaces are
2517     aggregate types, they work with FieldNames for consistency so that code
2518     that's written to work on aggregate types doesn't have to worry about
2519     whether it's dealing with an interface.
2520 
2521     See_Also:
2522         $(LREF FieldSymbols)
2523         $(LREF FieldTypes)
2524         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
2525   +/
2526 template FieldNames(T)
2527 if (isAggregateType!T)
2528 {
2529     import phobos.sys.meta : AliasSeq;
2530 
2531     static if (is(T == struct) && __traits(isNested, T))
2532         private alias Fields = AliasSeq!(T.tupleof[0 .. $ - 1]);
2533     else
2534         private alias Fields = T.tupleof;
2535 
2536     alias FieldNames = AliasSeq!();
2537     static foreach (Field; Fields)
2538         FieldNames = AliasSeq!(FieldNames, Field.stringof);
2539 }
2540 
2541 ///
2542 @safe unittest
2543 {
2544     import phobos.sys.meta : AliasSeq;
2545 
2546     struct S
2547     {
2548         int x;
2549         float y;
2550     }
2551     static assert(FieldNames!S == AliasSeq!("x", "y"));
2552 
2553     // Since the AliasSeq contains values, all of which are of the same type,
2554     // it can be used to create a dynamic array, which would be more
2555     // efficient than operating on an AliasSeq in the cases where an
2556     // AliasSeq is not necessary.
2557     static assert([FieldNames!S] == ["x", "y"]);
2558 
2559     class C
2560     {
2561         // static variables are not included.
2562         static int var;
2563 
2564         // Manifest constants are not included.
2565         enum lang = "dlang";
2566 
2567         // Functions are not included, even if they're @property functions.
2568         @property int foo() { return 42; }
2569 
2570         string s;
2571         int i;
2572         int[] arr;
2573     }
2574     static assert(FieldNames!C == AliasSeq!("s", "i", "arr"));
2575 
2576     static assert([FieldNames!C] == ["s", "i", "arr"]);
2577 
2578     // Only direct member variables are included. Member variables from any base
2579     // classes are not.
2580     class D : C
2581     {
2582         real r;
2583     }
2584     static assert(FieldNames!D == AliasSeq!"r");
2585 
2586     static assert([FieldNames!D] == ["r"]);
2587 
2588     // FieldNames will always be empty for an interface, since it's not legal
2589     // for interfaces to have member variables.
2590     interface I
2591     {
2592     }
2593     static assert(FieldNames!I.length == 0);
2594 
2595     union U
2596     {
2597         int i;
2598         double d;
2599         long l;
2600         S s;
2601     }
2602     static assert(FieldNames!U == AliasSeq!("i", "d", "l", "s"));
2603 
2604     static assert([FieldNames!U] == ["i", "d", "l", "s"]);;
2605 
2606     // FieldNames only operates on aggregate types.
2607     static assert(!__traits(compiles, FieldNames!int));
2608     static assert(!__traits(compiles, FieldNames!(S*)));
2609     static assert(!__traits(compiles, FieldNames!(C[])));
2610 }
2611 
2612 @safe unittest
2613 {
2614     import phobos.sys.meta : AliasSeq;
2615 
2616     {
2617         static struct S0 {}
2618         static assert(FieldNames!S0.length == 0);
2619 
2620         static struct S1 { int a; }
2621         static assert(FieldNames!S1 == AliasSeq!"a");
2622 
2623         static struct S2 { int a; string b; }
2624         static assert(FieldNames!S2 == AliasSeq!("a", "b"));
2625 
2626         static struct S3 { int a; string b; real c; }
2627         static assert(FieldNames!S3 == AliasSeq!("a", "b", "c"));
2628     }
2629     {
2630         int i;
2631         struct S0 { void foo() { i = 0; }}
2632         static assert(FieldNames!S0.length == 0);
2633         static assert(__traits(isNested, S0));
2634 
2635         struct S1 { int a; void foo() { i = 0; } }
2636         static assert(FieldNames!S1 == AliasSeq!"a");
2637         static assert(__traits(isNested, S1));
2638 
2639         struct S2 { int a; string b; void foo() { i = 0; } }
2640         static assert(FieldNames!S2 == AliasSeq!("a", "b"));
2641         static assert(__traits(isNested, S2));
2642 
2643         struct S3 { int a; string b; real c; void foo() { i = 0; } }
2644         static assert(FieldNames!S3 == AliasSeq!("a", "b", "c"));
2645         static assert(__traits(isNested, S3));
2646     }
2647     {
2648         static class C0 {}
2649         static assert(FieldNames!C0.length == 0);
2650 
2651         static class C1 { int a; }
2652         static assert(FieldNames!C1 == AliasSeq!"a");
2653 
2654         static class C2 { int a; string b; }
2655         static assert(FieldNames!C2 == AliasSeq!("a", "b"));
2656 
2657         static class C3 { int a; string b; real c; }
2658         static assert(FieldNames!C3 == AliasSeq!("a", "b", "c"));
2659 
2660         static class D0 : C3 {}
2661         static assert(FieldNames!D0.length == 0);
2662 
2663         static class D1 : C3 { bool x; }
2664         static assert(FieldNames!D1 == AliasSeq!"x");
2665 
2666         static class D2 : C3 { bool x; int* y; }
2667         static assert(FieldNames!D2 == AliasSeq!("x", "y"));
2668 
2669         static class D3 : C3 { bool x; int* y; short[] z; }
2670         static assert(FieldNames!D3 == AliasSeq!("x", "y", "z"));
2671     }
2672     {
2673         int i;
2674         class C0 { void foo() { i = 0; }}
2675         static assert(FieldNames!C0.length == 0);
2676         static assert(__traits(isNested, C0));
2677 
2678         class C1 { int a; void foo() { i = 0; } }
2679         static assert(FieldNames!C1 == AliasSeq!"a");
2680         static assert(__traits(isNested, C1));
2681 
2682         class C2 { int a; string b; void foo() { i = 0; } }
2683         static assert(FieldNames!C2 == AliasSeq!("a", "b"));
2684         static assert(__traits(isNested, C2));
2685 
2686         class C3 { int a; string b; real c; void foo() { i = 0; } }
2687         static assert(FieldNames!C3 == AliasSeq!("a", "b", "c"));
2688         static assert(__traits(isNested, C3));
2689 
2690         class D0 : C3 {}
2691         static assert(FieldNames!D0.length == 0);
2692         static assert(__traits(isNested, D0));
2693 
2694         class D1 : C3 { bool x; }
2695         static assert(FieldNames!D1 == AliasSeq!"x");
2696         static assert(__traits(isNested, D1));
2697 
2698         class D2 : C3 { bool x; int* y; }
2699         static assert(FieldNames!D2 == AliasSeq!("x", "y"));
2700         static assert(__traits(isNested, D2));
2701 
2702         class D3 : C3 { bool x; int* y; short[] z; }
2703         static assert(FieldNames!D3 == AliasSeq!("x", "y", "z"));
2704         static assert(__traits(isNested, D3));
2705     }
2706     {
2707         static union U0 {}
2708         static assert(FieldNames!U0.length == 0);
2709 
2710         static union U1 { int a; }
2711         static assert(FieldNames!U1 == AliasSeq!"a");
2712 
2713         static union U2 { int a; string b; }
2714         static assert(FieldNames!U2 == AliasSeq!("a", "b"));
2715 
2716         static union U3 { int a; string b; real c; }
2717         static assert(FieldNames!U3 == AliasSeq!("a", "b", "c"));
2718     }
2719     {
2720         static struct S
2721         {
2722             enum e = 42;
2723             static str = "foobar";
2724 
2725             string name() { return "foo"; }
2726 
2727             int[] arr;
2728 
2729             struct Inner1 { int i; }
2730 
2731             static struct Inner2 { long gnol; }
2732 
2733             union { int a; string b; }
2734 
2735             alias Foo = Inner1;
2736         }
2737 
2738         static assert(FieldNames!S == AliasSeq!("arr", "a", "b"));
2739         static assert(FieldNames!(const S) == AliasSeq!("arr", "a", "b"));
2740         static assert(FieldNames!(S.Inner1) == AliasSeq!"i");
2741         static assert(FieldNames!(S.Inner2) == AliasSeq!"gnol");
2742     }
2743 }
2744 
2745 /++
2746     Evaluates to an $(D AliasSeq) of the symbols for the member variables of an
2747     aggregate type (i.e. a struct, class, interface, or union).
2748 
2749     These are fields which take up memory space within an instance of the type
2750     (i.e. not enums / manifest constants, since they don't take up memory
2751     space, and not static member variables, since they don't take up memory
2752     space within an instance).
2753 
2754     Hidden fields (like the virtual function table pointer or the context
2755     pointer for nested types) are not included.
2756 
2757     For classes, only the direct member variables are included and not those
2758     of any base classes.
2759 
2760     For interfaces, the result of FieldSymbols is always empty, because
2761     interfaces cannot have member variables. However, because interfaces are
2762     aggregate types, they work with FieldSymbols for consistency so that code
2763     that's written to work on aggregate types doesn't have to worry about
2764     whether it's dealing with an interface.
2765 
2766     In most cases, $(D FieldSymbols!T) has the same result as $(D T.tupleof).
2767     The difference is that for nested structs with a context pointer,
2768     $(D T.tupleof) includes the context pointer, whereas $(D FieldSymbols!T)
2769     does not. For non-nested structs, and for classes, interfaces, and unions,
2770     $(D FieldSymbols!T) and $(D T.tupleof) are the same.
2771 
2772     So, for most cases, $(D T.tupleof) is sufficient and avoids instantiating
2773     an additional template, but FieldSymbols is provided so that the code that
2774     needs to avoid including context pointers in the list of fields can do so
2775     without the programmer having to figure how to do that correctly. It also
2776     provides a template that's equivalent to what $(LREF FieldNames) and
2777     $(LREF FieldTypes) do in terms of which fields it gives (the difference of
2778     course then being whether you get the symbols, names, or types for the
2779     fields), whereas the behavior for $(D tupleof) is subtly different.
2780 
2781     See_Also:
2782         $(LREF FieldNames)
2783         $(LREF FieldTypes)
2784         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
2785         $(DDSUBLINK spec/traits, isNested, $(D __traits(isNested, ...))).
2786         $(DDSUBLINK spec/traits, isSame, $(D __traits(isSame, ...))).
2787   +/
2788 template FieldSymbols(T)
2789 if (isAggregateType!T)
2790 {
2791     static if (is(T == struct) && __traits(isNested, T))
2792     {
2793         import phobos.sys.meta : AliasSeq;
2794         alias FieldSymbols = AliasSeq!(T.tupleof[0 .. $ - 1]);
2795     }
2796     else
2797         alias FieldSymbols = T.tupleof;
2798 }
2799 
2800 ///
2801 @safe unittest
2802 {
2803     import phobos.sys.meta : AliasSeq;
2804 
2805     struct S
2806     {
2807         int x;
2808         float y;
2809     }
2810     static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.x, S.y)));
2811 
2812     // FieldSymbols!S and S.tupleof are the same, because S is not nested.
2813     static assert(__traits(isSame, FieldSymbols!S, S.tupleof));
2814 
2815     // Note that type qualifiers _should_ be passed on to the result, but due
2816     // to https://issues.dlang.org/show_bug.cgi?id=24516, they aren't.
2817     // FieldTypes does not have this problem, because it aliases the types
2818     // rather than the symbols, so if you need the types from the symbols, you
2819     // should use either FieldTypes or tupleof until the compiler bug has been
2820     // fixed (and if you use tupleof, you need to avoid aliasing the result
2821     // before getting the types from it).
2822     static assert(is(typeof(FieldSymbols!S[0]) == int));
2823 
2824     // These currently fail when they shouldn't:
2825     //static assert(is(typeof(FieldSymbols!(const S)[0]) == const int));
2826     //static assert(is(typeof(FieldSymbols!(shared S)[0]) == shared int));
2827 
2828     class C
2829     {
2830         // static variables are not included.
2831         static int var;
2832 
2833         // Manifest constants are not included.
2834         enum lang = "dlang";
2835 
2836         // Functions are not included, even if they're @property functions.
2837         @property int foo() { return 42; }
2838 
2839         string s;
2840         int i;
2841         int[] arr;
2842     }
2843     static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.s, C.i, C.arr)));
2844 
2845     // FieldSymbols!C and C.tupleof have the same symbols, because they are
2846     // always the same for classes.
2847     static assert(__traits(isSame, FieldSymbols!C, C.tupleof));
2848 
2849     // Only direct member variables are included. Member variables from any base
2850     // classes are not.
2851     class D : C
2852     {
2853         real r;
2854     }
2855     static assert(__traits(isSame, FieldSymbols!D, AliasSeq!(D.r)));
2856     static assert(__traits(isSame, FieldSymbols!D, D.tupleof));
2857 
2858     // FieldSymbols will always be empty for an interface, since it's not legal
2859     // for interfaces to have member variables.
2860     interface I
2861     {
2862     }
2863     static assert(FieldSymbols!I.length == 0);
2864     static assert(I.tupleof.length == 0);
2865 
2866     union U
2867     {
2868         int i;
2869         double d;
2870         long l;
2871         S s;
2872     }
2873     static assert(__traits(isSame, FieldSymbols!U, AliasSeq!(U.i, U.d, U.l, U.s)));
2874 
2875     // FieldSymbols!C and C.tupleof have the same symbols, because they are
2876     // always the same for unions.
2877     static assert(__traits(isSame, FieldSymbols!U, U.tupleof));
2878 
2879     // FieldSymbols only operates on aggregate types.
2880     static assert(!__traits(compiles, FieldSymbols!int));
2881     static assert(!__traits(compiles, FieldSymbols!(S*)));
2882     static assert(!__traits(compiles, FieldSymbols!(C[])));
2883 }
2884 
2885 /// Some examples with nested types.
2886 @safe unittest
2887 {
2888     import phobos.sys.meta : AliasSeq;
2889 
2890     int outside;
2891 
2892     struct S
2893     {
2894         long l;
2895         string s;
2896 
2897         void foo() { outside = 2; }
2898     }
2899     static assert(__traits(isNested, S));
2900     static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.l, S.s)));
2901 
2902     // FieldSymbols!S and S.tupleof are not the same, because S is nested, and
2903     // the context pointer to the outer scope is included in S.tupleof, whereas
2904     // it is excluded from FieldSymbols!S.
2905     static assert(__traits(isSame, S.tupleof[0 .. $ - 1], AliasSeq!(S.l, S.s)));
2906     static assert(S.tupleof[$ - 1].stringof == "this");
2907 
2908     class C
2909     {
2910         bool b;
2911         int* ptr;
2912 
2913         void foo() { outside = 7; }
2914     }
2915     static assert(__traits(isNested, C));
2916     static assert(__traits(isSame, FieldSymbols!C, AliasSeq!(C.b, C.ptr)));
2917 
2918     // FieldSymbols!C and C.tupleof have the same symbols, because they are
2919     // always the same for classes. No context pointer is provided as part of
2920     // tupleof for nested classes.
2921     static assert(__traits(isSame, FieldSymbols!C, C.tupleof));
2922 
2923     // __traits(isNested, ...) is never true for interfaces or unions, since
2924     // they cannot have a context pointer to an outer scope. So, tupleof and
2925     // FieldSymbols will always be the same for interfaces and unions.
2926 }
2927 
2928 @safe unittest
2929 {
2930     import phobos.sys.meta : AliasSeq;
2931 
2932     {
2933         static struct S0 {}
2934         static assert(FieldSymbols!S0.length == 0);
2935 
2936         static struct S1 { int a; }
2937         static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a)));
2938 
2939         static struct S2 { int a; string b; }
2940         static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b)));
2941 
2942         static struct S3 { int a; string b; real c; }
2943         static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c)));
2944     }
2945     {
2946         int i;
2947         struct S0 { void foo() { i = 0; }}
2948         static assert(FieldSymbols!S0.length == 0);
2949         static assert(__traits(isNested, S0));
2950 
2951         struct S1 { int a; void foo() { i = 0; } }
2952         static assert(__traits(isSame, FieldSymbols!S1, AliasSeq!(S1.a)));
2953         static assert(__traits(isNested, S1));
2954 
2955         struct S2 { int a; string b; void foo() { i = 0; } }
2956         static assert(__traits(isSame, FieldSymbols!S2, AliasSeq!(S2.a, S2.b)));
2957         static assert(__traits(isNested, S2));
2958 
2959         struct S3 { int a; string b; real c; void foo() { i = 0; } }
2960         static assert(__traits(isSame, FieldSymbols!S3, AliasSeq!(S3.a, S3.b, S3.c)));
2961         static assert(__traits(isNested, S3));
2962     }
2963     {
2964         static class C0 {}
2965         static assert(FieldSymbols!C0.length == 0);
2966 
2967         static class C1 { int a; }
2968         static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a)));
2969 
2970         static class C2 { int a; string b; }
2971         static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b)));
2972 
2973         static class C3 { int a; string b; real c; }
2974         static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c)));
2975 
2976         static class D0 : C3 {}
2977         static assert(FieldSymbols!D0.length == 0);
2978 
2979         static class D1 : C3 { bool x; }
2980         static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x)));
2981 
2982         static class D2 : C3 { bool x; int* y; }
2983         static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y)));
2984 
2985         static class D3 : C3 { bool x; int* y; short[] z; }
2986         static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z)));
2987     }
2988     {
2989         int i;
2990         class C0 { void foo() { i = 0; }}
2991         static assert(FieldSymbols!C0.length == 0);
2992         static assert(__traits(isNested, C0));
2993 
2994         class C1 { int a; void foo() { i = 0; } }
2995         static assert(__traits(isSame, FieldSymbols!C1, AliasSeq!(C1.a)));
2996         static assert(__traits(isNested, C1));
2997 
2998         class C2 { int a; string b; void foo() { i = 0; } }
2999         static assert(__traits(isSame, FieldSymbols!C2, AliasSeq!(C2.a, C2.b)));
3000         static assert(__traits(isNested, C2));
3001 
3002         class C3 { int a; string b; real c; void foo() { i = 0; } }
3003         static assert(__traits(isSame, FieldSymbols!C3, AliasSeq!(C3.a, C3.b, C3.c)));
3004         static assert(__traits(isNested, C3));
3005 
3006         class D0 : C3 {}
3007         static assert(FieldSymbols!D0.length == 0);
3008         static assert(__traits(isNested, D0));
3009 
3010         class D1 : C3 { bool x; }
3011         static assert(__traits(isSame, FieldSymbols!D1, AliasSeq!(D1.x)));
3012         static assert(__traits(isNested, D1));
3013 
3014         class D2 : C3 { bool x; int* y; }
3015         static assert(__traits(isSame, FieldSymbols!D2, AliasSeq!(D2.x, D2.y)));
3016         static assert(__traits(isNested, D2));
3017 
3018         class D3 : C3 { bool x; int* y; short[] z; }
3019         static assert(__traits(isSame, FieldSymbols!D3, AliasSeq!(D3.x, D3.y, D3.z)));
3020         static assert(__traits(isNested, D3));
3021     }
3022     {
3023         static union U0 {}
3024         static assert(FieldSymbols!U0.length == 0);
3025 
3026         static union U1 { int a; }
3027         static assert(__traits(isSame, FieldSymbols!U1, AliasSeq!(U1.a)));
3028 
3029         static union U2 { int a; string b; }
3030         static assert(__traits(isSame, FieldSymbols!U2, AliasSeq!(U2.a, U2.b)));
3031 
3032         static union U3 { int a; string b; real c; }
3033         static assert(__traits(isSame, FieldSymbols!U3, AliasSeq!(U3.a, U3.b, U3.c)));
3034     }
3035     {
3036         static struct S
3037         {
3038             enum e = 42;
3039             static str = "foobar";
3040 
3041             string name() { return "foo"; }
3042 
3043             int[] arr;
3044 
3045             struct Inner1 { int i; }
3046 
3047             static struct Inner2 { long gnol; }
3048 
3049             union { int a; string b; }
3050 
3051             alias Foo = Inner1;
3052         }
3053 
3054         static assert(__traits(isSame, FieldSymbols!S, AliasSeq!(S.arr, S.a, S.b)));
3055         static assert(__traits(isSame, FieldSymbols!(const S), AliasSeq!(S.arr, S.a, S.b)));
3056         static assert(__traits(isSame, FieldSymbols!(S.Inner1), AliasSeq!(S.Inner1.i)));
3057         static assert(__traits(isSame, FieldSymbols!(S.Inner2), AliasSeq!(S.Inner2.gnol)));
3058     }
3059 }
3060 
3061 /++
3062     Evaluates to an $(D AliasSeq) of the types of the member variables of an
3063     aggregate type (i.e. a struct, class, interface, or union).
3064 
3065     These are fields which take up memory space within an instance of the type
3066     (i.e. not enums / manifest constants, since they don't take up memory
3067     space, and not static member variables, since they don't take up memory
3068     space within an instance).
3069 
3070     Hidden fields (like the virtual function table pointer or the context
3071     pointer for nested types) are not included.
3072 
3073     For classes, only the direct member variables are included and not those
3074     of any base classes.
3075 
3076     For interfaces, the result of FieldTypes is always empty, because
3077     interfaces cannot have member variables. However, because interfaces are
3078     aggregate types, they work with FieldTypes for consistency so that code
3079     that's written to work on aggregate types doesn't have to worry about
3080     whether it's dealing with an interface.
3081 
3082     See_Also:
3083         $(LREF FieldNames)
3084         $(LREF FieldSymbols)
3085         $(DDSUBLINK spec/struct.html, struct_instance_properties, $(D tupleof))
3086   +/
3087 template FieldTypes(T)
3088 if (isAggregateType!T)
3089 {
3090     static if (is(T == struct) && __traits(isNested, T))
3091         alias FieldTypes = typeof(T.tupleof[0 .. $ - 1]);
3092     else
3093         alias FieldTypes = typeof(T.tupleof);
3094 }
3095 
3096 ///
3097 @safe unittest
3098 {
3099     import phobos.sys.meta : AliasSeq;
3100 
3101     struct S
3102     {
3103         int x;
3104         float y;
3105     }
3106     static assert(is(FieldTypes!S == AliasSeq!(int, float)));
3107 
3108     // Type qualifers will be passed on to the result.
3109     static assert(is(FieldTypes!(const S) == AliasSeq!(const int, const float)));
3110     static assert(is(FieldTypes!(shared S) == AliasSeq!(shared int, shared float)));
3111 
3112     class C
3113     {
3114         // static variables are not included.
3115         static int var;
3116 
3117         // Manifest constants are not included.
3118         enum lang = "dlang";
3119 
3120         // Functions are not included, even if they're @property functions.
3121         @property int foo() { return 42; }
3122 
3123         string s;
3124         int i;
3125         int[] arr;
3126     }
3127     static assert(is(FieldTypes!C == AliasSeq!(string, int, int[])));
3128 
3129     // Only direct member variables are included. Member variables from any base
3130     // classes are not.
3131     class D : C
3132     {
3133         real r;
3134     }
3135     static assert(is(FieldTypes!D == AliasSeq!real));
3136 
3137     // FieldTypes will always be empty for an interface, since it's not legal
3138     // for interfaces to have member variables.
3139     interface I
3140     {
3141     }
3142     static assert(FieldTypes!I.length == 0);
3143 
3144     union U
3145     {
3146         int i;
3147         double d;
3148         long l;
3149         S s;
3150     }
3151     static assert(is(FieldTypes!U == AliasSeq!(int, double, long, S)));
3152 
3153     // FieldTypes only operates on aggregate types.
3154     static assert(!__traits(compiles, FieldTypes!int));
3155     static assert(!__traits(compiles, FieldTypes!(S*)));
3156     static assert(!__traits(compiles, FieldTypes!(C[])));
3157 }
3158 
3159 @safe unittest
3160 {
3161     import phobos.sys.meta : AliasSeq;
3162 
3163     {
3164         static struct S0 {}
3165         static assert(FieldTypes!S0.length == 0);
3166 
3167         static struct S1 { int a; }
3168         static assert(is(FieldTypes!S1 == AliasSeq!int));
3169 
3170         static struct S2 { int a; string b; }
3171         static assert(is(FieldTypes!S2 == AliasSeq!(int, string)));
3172 
3173         static struct S3 { int a; string b; real c; }
3174         static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real)));
3175     }
3176     {
3177         int i;
3178         struct S0 { void foo() { i = 0; }}
3179         static assert(FieldTypes!S0.length == 0);
3180         static assert(__traits(isNested, S0));
3181 
3182         struct S1 { int a; void foo() { i = 0; } }
3183         static assert(is(FieldTypes!S1 == AliasSeq!int));
3184         static assert(__traits(isNested, S1));
3185 
3186         struct S2 { int a; string b; void foo() { i = 0; } }
3187         static assert(is(FieldTypes!S2 == AliasSeq!(int, string)));
3188         static assert(__traits(isNested, S2));
3189 
3190         struct S3 { int a; string b; real c; void foo() { i = 0; } }
3191         static assert(is(FieldTypes!S3 == AliasSeq!(int, string, real)));
3192         static assert(__traits(isNested, S3));
3193     }
3194     {
3195         static class C0 {}
3196         static assert(FieldTypes!C0.length == 0);
3197 
3198         static class C1 { int a; }
3199         static assert(is(FieldTypes!C1 == AliasSeq!int));
3200 
3201         static class C2 { int a; string b; }
3202         static assert(is(FieldTypes!C2 == AliasSeq!(int, string)));
3203 
3204         static class C3 { int a; string b; real c; }
3205         static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real)));
3206 
3207         static class D0 : C3 {}
3208         static assert(FieldTypes!D0.length == 0);
3209 
3210         static class D1 : C3 { bool x; }
3211         static assert(is(FieldTypes!D1 == AliasSeq!bool));
3212 
3213         static class D2 : C3 { bool x; int* y; }
3214         static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*)));
3215 
3216         static class D3 : C3 { bool x; int* y; short[] z; }
3217         static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[])));
3218     }
3219     {
3220         int i;
3221         class C0 { void foo() { i = 0; }}
3222         static assert(FieldTypes!C0.length == 0);
3223         static assert(__traits(isNested, C0));
3224 
3225         class C1 { int a; void foo() { i = 0; } }
3226         static assert(is(FieldTypes!C1 == AliasSeq!int));
3227         static assert(__traits(isNested, C1));
3228 
3229         class C2 { int a; string b; void foo() { i = 0; } }
3230         static assert(is(FieldTypes!C2 == AliasSeq!(int, string)));
3231         static assert(__traits(isNested, C2));
3232 
3233         class C3 { int a; string b; real c; void foo() { i = 0; } }
3234         static assert(is(FieldTypes!C3 == AliasSeq!(int, string, real)));
3235         static assert(__traits(isNested, C3));
3236 
3237         class D0 : C3 {}
3238         static assert(FieldTypes!D0.length == 0);
3239         static assert(__traits(isNested, D0));
3240 
3241         class D1 : C3 { bool x; }
3242         static assert(is(FieldTypes!D1 == AliasSeq!bool));
3243         static assert(__traits(isNested, D1));
3244 
3245         class D2 : C3 { bool x; int* y; }
3246         static assert(is(FieldTypes!D2 == AliasSeq!(bool, int*)));
3247         static assert(__traits(isNested, D2));
3248 
3249         class D3 : C3 { bool x; int* y; short[] z; }
3250         static assert(is(FieldTypes!D3 == AliasSeq!(bool, int*, short[])));
3251         static assert(__traits(isNested, D3));
3252     }
3253     {
3254         static union U0 {}
3255         static assert(FieldTypes!U0.length == 0);
3256 
3257         static union U1 { int a; }
3258         static assert(is(FieldTypes!U1 == AliasSeq!int));
3259 
3260         static union U2 { int a; string b; }
3261         static assert(is(FieldTypes!U2 == AliasSeq!(int, string)));
3262 
3263         static union U3 { int a; string b; real c; }
3264         static assert(is(FieldTypes!U3 == AliasSeq!(int, string, real)));
3265     }
3266     {
3267         static struct S
3268         {
3269             enum e = 42;
3270             static str = "foobar";
3271 
3272             string name() { return "foo"; }
3273 
3274             int[] arr;
3275 
3276             struct Inner1 { int i; }
3277 
3278             static struct Inner2 { long gnol; }
3279 
3280             union { int a; string b; }
3281 
3282             alias Foo = Inner1;
3283         }
3284 
3285         static assert(is(FieldTypes!S == AliasSeq!(int[], int, string)));
3286         static assert(is(FieldTypes!(const S) == AliasSeq!(const(int[]), const int, const string)));
3287         static assert(is(FieldTypes!(S.Inner1) == AliasSeq!int));
3288         static assert(is(FieldTypes!(S.Inner2) == AliasSeq!long));
3289     }
3290 }
3291 
3292 /++
3293     Whether assigning to a variable of the given type involves either a
3294     user-defined $(D opAssign) or a compiler-generated $(D opAssign) rather than
3295     using the default assignment behavior (which would use $(D memcpy)). The
3296     $(D opAssign) must accept the same type (with compatible qualifiers) as the
3297     type which the $(D opAssign) is declared on for it to count for
3298     hasComplexAssignment.
3299 
3300     The compiler will generate an $(D opAssign) for a struct when a member
3301     variable of that struct defines an $(D opAssign). It will also generate one
3302     when the struct has a postblit constructor or destructor (and those can be
3303     either user-defined or compiler-generated).
3304 
3305     However, due to $(BUGZILLA 24834), the compiler does not currently generate
3306     an $(D opAssign) for structs that define a copy constructor, and so
3307     hasComplexAssignment is $(D false) for such types unless they have an
3308     explicit $(D opAssign), or the compiler generates one due to a member
3309     variable having an $(D opAssign).
3310 
3311     Note that hasComplexAssignment is also $(D true) for static arrays whose
3312     element type has an $(D opAssign), since while the static array itself does
3313     not have an $(D opAssign), the compiler must use the $(D opAssign) of the
3314     elements when assigning to the static array.
3315 
3316     Due to $(BUGZILLA 24833), enums never have complex assignment even if their
3317     base type does. Their $(D opAssign) is never called, resulting in incorrect
3318     behavior for such enums. So, because the compiler does not treat them as
3319     having complex assignment, hasComplexAssignment is $(D false) for them.
3320 
3321     No other types (including class references, pointers, and unions)
3322     ever have an $(D opAssign) and thus hasComplexAssignment is never $(D true)
3323     for them. It is particularly important to note that unions never have an
3324     $(D opAssign), so if a struct contains a union which contains one or more
3325     members which have an $(D opAssign), that struct will have to have a
3326     user-defined $(D opAssign) which explicitly assigns to the correct member
3327     of the union if you don't want the current value of the union to simply be
3328     memcopied when assigning to the struct.
3329 
3330     One big reason that code would need to worry about hasComplexAssignment is
3331     if void initialization is used anywhere. While it might be okay to assign
3332     to uninitialized memory for a type where assignment does a memcopy,
3333     assigning to uninitialized memory will cause serious issues with any
3334     $(D opAssign) which looks at the object before assigning to it (e.g.
3335     because the type uses reference counting). In such cases,
3336     $(REF copyEmplace, core, sys, lifetime) needs to be used instead of
3337     assignment.
3338 
3339     See_Also:
3340         $(LREF hasComplexCopying)
3341         $(LREF hasComplexDestruction)
3342         $(DDSUBLINK spec/operatoroverloading, assignment,
3343                     The language spec for overloading assignment)
3344         $(DDSUBLINK spec/struct, assign-overload,
3345                     The language spec for $(D opAssign) on structs)
3346   +/
3347 template hasComplexAssignment(T)
3348 {
3349     import core.internal.traits : hasElaborateAssign;
3350     alias hasComplexAssignment = hasElaborateAssign!T;
3351 }
3352 
3353 ///
3354 @safe unittest
3355 {
3356     static assert(!hasComplexAssignment!int);
3357     static assert(!hasComplexAssignment!real);
3358     static assert(!hasComplexAssignment!string);
3359     static assert(!hasComplexAssignment!(int[]));
3360     static assert(!hasComplexAssignment!(int[42]));
3361     static assert(!hasComplexAssignment!(int[string]));
3362     static assert(!hasComplexAssignment!Object);
3363 
3364     static struct NoOpAssign
3365     {
3366         int i;
3367     }
3368     static assert(!hasComplexAssignment!NoOpAssign);
3369 
3370     // For complex assignment, the parameter type must match the type of the
3371     // struct (with compatible qualifiers), but refness does not matter (though
3372     // it will obviously affect whether rvalues will be accepted as well as
3373     // whether non-copyable types will be accepted).
3374     static struct HasOpAssign
3375     {
3376         void opAssign(HasOpAssign) {}
3377     }
3378     static assert( hasComplexAssignment!HasOpAssign);
3379     static assert(!hasComplexAssignment!(const(HasOpAssign)));
3380 
3381     static struct HasOpAssignRef
3382     {
3383         void opAssign(ref HasOpAssignRef) {}
3384     }
3385     static assert( hasComplexAssignment!HasOpAssignRef);
3386     static assert(!hasComplexAssignment!(const(HasOpAssignRef)));
3387 
3388     static struct HasOpAssignAutoRef
3389     {
3390         void opAssign()(auto ref HasOpAssignAutoRef) {}
3391     }
3392     static assert( hasComplexAssignment!HasOpAssignAutoRef);
3393     static assert(!hasComplexAssignment!(const(HasOpAssignAutoRef)));
3394 
3395     // Assigning a mutable value works when opAssign takes const, because
3396     // mutable implicitly converts to const, but assigning to a const variable
3397     // does not work, so normally, a const object is not considered to have
3398     // complex assignment.
3399     static struct HasOpAssignC
3400     {
3401         void opAssign(const HasOpAssignC) {}
3402     }
3403     static assert( hasComplexAssignment!HasOpAssignC);
3404     static assert(!hasComplexAssignment!(const(HasOpAssignC)));
3405 
3406     // If opAssign is const, then assigning to a const variable will work, and a
3407     // const object will have complex assignment. However, such a type would
3408     // not normally make sense, since it can't actually be mutated by opAssign.
3409     static struct HasConstOpAssignC
3410     {
3411         void opAssign(const HasConstOpAssignC) const {}
3412     }
3413     static assert( hasComplexAssignment!HasConstOpAssignC);
3414     static assert( hasComplexAssignment!(const(HasConstOpAssignC)));
3415 
3416     // For a type to have complex assignment, the types must match aside from
3417     // the qualifiers. So, an opAssign which takes another type does not count
3418     // as complex assignment.
3419     static struct OtherOpAssign
3420     {
3421         void opAssign(int) {}
3422     }
3423     static assert(!hasComplexAssignment!OtherOpAssign);
3424 
3425     // The return type doesn't matter for complex assignment, though normally,
3426     // opAssign should either return a reference to the this reference (so that
3427     // assignments can be chained) or void.
3428     static struct HasOpAssignWeirdRet
3429     {
3430         int opAssign(HasOpAssignWeirdRet) { return 42; }
3431     }
3432     static assert( hasComplexAssignment!HasOpAssignWeirdRet);
3433 
3434     // The compiler will generate an assignment operator if a member variable
3435     // has one.
3436     static struct HasMemberWithOpAssign
3437     {
3438         HasOpAssign s;
3439     }
3440     static assert( hasComplexAssignment!HasMemberWithOpAssign);
3441 
3442     // The compiler will generate an assignment operator if the type has a
3443     // postblit constructor or a destructor.
3444     static struct HasDtor
3445     {
3446         ~this() {}
3447     }
3448     static assert( hasComplexAssignment!HasDtor);
3449 
3450     // If a struct has @disabled opAssign (and thus assigning to a variable of
3451     // that type will result in a compilation error), then
3452     // hasComplexAssignment is false.
3453     // Code that wants to check whether assignment works will need to test that
3454     // assigning to a variable of that type compiles (which could need to test
3455     // both an lvalue and an rvalue depending on the exact sort of assignment
3456     // the code is actually going to do).
3457     static struct DisabledOpAssign
3458     {
3459         @disable void opAssign(DisabledOpAssign);
3460     }
3461     static assert(!hasComplexAssignment!DisabledOpAssign);
3462     static assert(!__traits(compiles, { DisabledOpAssign s;
3463                                         s = rvalueOf!DisabledOpAssign;
3464                                         s = lvalueOf!DisabledOpAssign; }));
3465     static assert(!is(typeof({ DisabledOpAssign s;
3466                                s = rvalueOf!DisabledOpAssign;
3467                                s = lvalueOf!DisabledOpAssign; })));
3468 
3469     // Static arrays have complex assignment if their elements do.
3470     static assert( hasComplexAssignment!(HasOpAssign[1]));
3471 
3472     // Static arrays with no elements do not have complex assignment, because
3473     // there's nothing to assign to.
3474     static assert(!hasComplexAssignment!(HasOpAssign[0]));
3475 
3476     // Dynamic arrays do not have complex assignment, because assigning to them
3477     // just slices them rather than assigning to their elements. Assigning to
3478     // an array with a slice operation - e.g. arr[0 .. 5] = other[0 .. 5]; -
3479     // does use opAssign if the elements have it, but since assigning to the
3480     // array itself does not, hasComplexAssignment is false for dynamic arrays.
3481     static assert(!hasComplexAssignment!(HasOpAssign[]));
3482 
3483     // Classes and unions do not have complex assignment even if they have
3484     // members which do.
3485     class C
3486     {
3487         HasOpAssign s;
3488     }
3489     static assert(!hasComplexAssignment!C);
3490 
3491     union U
3492     {
3493         HasOpAssign s;
3494     }
3495     static assert(!hasComplexAssignment!U);
3496 
3497     // https://issues.dlang.org/show_bug.cgi?id=24833
3498     // This static assertion fails, because the compiler
3499     // currently ignores assignment operators for enum types.
3500     enum E : HasOpAssign { a = HasOpAssign.init }
3501     //static assert( hasComplexAssignment!E);
3502 }
3503 
3504 @safe unittest
3505 {
3506     import phobos.sys.meta : AliasSeq;
3507 
3508     {
3509         struct S1 { int i; }
3510         struct S2 { real r; }
3511         struct S3 { string s; }
3512         struct S4 { int[] arr; }
3513         struct S5 { int[0] arr; }
3514         struct S6 { int[42] arr; }
3515         struct S7 { int[string] aa; }
3516 
3517         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
3518         {
3519             static assert(!hasComplexAssignment!T);
3520             static assert(!hasComplexAssignment!(T[0]));
3521             static assert(!hasComplexAssignment!(T[42]));
3522             static assert(!hasComplexAssignment!(T[]));
3523         }
3524     }
3525 
3526     // Basic variations of opAssign.
3527     {
3528         static struct S { void opAssign(S) {} }
3529         static assert( hasComplexAssignment!S);
3530 
3531         static struct S2 { S s; }
3532         static assert( hasComplexAssignment!S2);
3533     }
3534     {
3535         static struct S { void opAssign(ref S) {} }
3536         static assert( hasComplexAssignment!S);
3537 
3538         static struct S2 { S s; }
3539         static assert( hasComplexAssignment!S2);
3540     }
3541     {
3542         static struct S { void opAssign()(auto ref S) {} }
3543         static assert( hasComplexAssignment!S);
3544 
3545         static struct S2 { S s; }
3546         static assert( hasComplexAssignment!S2);
3547     }
3548     {
3549         static struct S { ref opAssign(S) { return this; } }
3550         static assert( hasComplexAssignment!S);
3551 
3552         static struct S2 { S s; }
3553         static assert( hasComplexAssignment!S2);
3554     }
3555     {
3556         static struct S { ref opAssign(ref S) { return this; } }
3557         static assert( hasComplexAssignment!S);
3558 
3559         static struct S2 { S s; }
3560         static assert( hasComplexAssignment!S2);
3561     }
3562     {
3563         static struct S { ref opAssign()(auto ref S) { return this; } }
3564         static assert( hasComplexAssignment!S);
3565 
3566         static struct S2 { S s; }
3567         static assert( hasComplexAssignment!S2);
3568     }
3569     {
3570         static struct S { ref opAssign(T)(auto ref T) { return this; } }
3571         static assert( hasComplexAssignment!S);
3572 
3573         static struct S2 { S s; }
3574         static assert( hasComplexAssignment!S2);
3575     }
3576 
3577     // Non-complex opAssign.
3578     {
3579         static struct S { ref opAssign(int) { return this; } }
3580         static assert(!hasComplexAssignment!S);
3581 
3582         static struct S2 { S s; }
3583         static assert(!hasComplexAssignment!S2);
3584     }
3585     {
3586         struct Other {}
3587         static struct S { ref opAssign(Other) { return this; } }
3588         static assert(!hasComplexAssignment!S);
3589 
3590         static struct S2 { S s; }
3591         static assert(!hasComplexAssignment!S2);
3592     }
3593 
3594     // Multiple opAssigns.
3595     {
3596         static struct S
3597         {
3598             void opAssign(S) {}
3599             void opAssign(int) {}
3600         }
3601         static assert( hasComplexAssignment!S);
3602 
3603         static struct S2 { S s; }
3604         static assert( hasComplexAssignment!S2);
3605     }
3606     {
3607         // This just flips the order of the previous test to catch potential
3608         // bugs related to the order of declaration, since that's occasionally
3609         // popped up in the compiler in other contexts.
3610         static struct S
3611         {
3612             void opAssign(int) {}
3613             void opAssign(S) {}
3614         }
3615         static assert( hasComplexAssignment!S);
3616 
3617         static struct S2 { S s; }
3618         static assert( hasComplexAssignment!S2);
3619     }
3620     {
3621         static struct S
3622         {
3623             void opAssign(S) {}
3624             void opAssign(ref S) {}
3625             void opAssign(const ref S) {}
3626         }
3627         static assert( hasComplexAssignment!S);
3628 
3629         static struct S2 { S s; }
3630         static assert( hasComplexAssignment!S2);
3631     }
3632 
3633     // Make sure that @disabled alternate opAssigns don't cause issues.
3634     {
3635         static struct S
3636         {
3637             void opAssign(S) {}
3638             @disable void opAssign(ref S) {}
3639         }
3640         static assert( hasComplexAssignment!S);
3641 
3642         // See https://issues.dlang.org/show_bug.cgi?id=24854
3643         // The compiler won't generate any opAssign (even if it theoretically
3644         // can) if the member variable has an @disabled opAssign which counts as
3645         // complex assignment.
3646         static struct S2 { S s; }
3647         static assert(!hasComplexAssignment!S2);
3648     }
3649     {
3650         static struct S
3651         {
3652             void opAssign(T)(T) {}
3653             @disable void opAssign(T)(ref T) {}
3654         }
3655         static assert( hasComplexAssignment!S);
3656 
3657         static struct S2 { S s; }
3658         static assert(!hasComplexAssignment!S2);
3659     }
3660     {
3661         static struct S
3662         {
3663             @disable void opAssign(S) {}
3664             void opAssign(ref S) {}
3665         }
3666         static assert( hasComplexAssignment!S);
3667 
3668         static struct S2 { S s; }
3669         static assert(!hasComplexAssignment!S2);
3670     }
3671     {
3672         static struct S
3673         {
3674             @disable void opAssign(T)(T) {}
3675             void opAssign(T)(ref T) {}
3676         }
3677         static assert( hasComplexAssignment!S);
3678 
3679         static struct S2 { S s; }
3680         static assert(!hasComplexAssignment!S2);
3681     }
3682     {
3683         static struct S
3684         {
3685             void opAssign(S) {}
3686             @disable void opAssign(int) {}
3687         }
3688         static assert( hasComplexAssignment!S);
3689 
3690         static struct S2 { S s; }
3691         static assert( hasComplexAssignment!S2);
3692     }
3693     {
3694         // The same as the previous test but in reverse order just to catch
3695         // compiler bugs related to the order of declaration.
3696         static struct S
3697         {
3698             @disable void opAssign(int) {}
3699             void opAssign(S) {}
3700         }
3701         static assert( hasComplexAssignment!S);
3702 
3703         static struct S2 { S s; }
3704         static assert( hasComplexAssignment!S2);
3705     }
3706 
3707     // Generated opAssign due to other functions.
3708     {
3709         static struct S { this(this) {} }
3710         static assert( hasComplexAssignment!S);
3711 
3712         static struct S2 { S s; }
3713         static assert( hasComplexAssignment!S2);
3714     }
3715     // https://issues.dlang.org/show_bug.cgi?id=24834
3716     /+
3717     {
3718         static struct S { this(ref S) {} }
3719         static assert( hasComplexAssignment!S);
3720 
3721         static struct S2 { S s; }
3722         static assert( hasComplexAssignment!S2);
3723     }
3724     +/
3725     {
3726         static struct S { ~this() {}  }
3727         static assert( hasComplexAssignment!S);
3728 
3729         static struct S2 { S s; }
3730         static assert( hasComplexAssignment!S2);
3731     }
3732 
3733     {
3734         static struct S
3735         {
3736             this(this) {}
3737             @disable void opAssign()(auto ref S) {}
3738         }
3739         static assert(!hasComplexAssignment!S);
3740 
3741         static struct S2 { S s; }
3742         static assert(!hasComplexAssignment!S2);
3743     }
3744     {
3745         static struct S
3746         {
3747             this(this) {}
3748             void opAssign()(auto ref S) {}
3749             @disable void opAssign(int) {}
3750         }
3751         static assert( hasComplexAssignment!S);
3752 
3753         static struct S2 { S s; }
3754         static assert( hasComplexAssignment!S2);
3755     }
3756 
3757     // Static arrays
3758     {
3759         static struct S { void opAssign(S) {} }
3760         static assert( hasComplexAssignment!S);
3761 
3762         static assert(!hasComplexAssignment!(S[0]));
3763         static assert( hasComplexAssignment!(S[12]));
3764         static assert(!hasComplexAssignment!(S[]));
3765 
3766         static struct S2 { S[42] s; }
3767         static assert( hasComplexAssignment!S2);
3768     }
3769 }
3770 
3771 /++
3772     Whether copying an object of the given type involves either a user-defined
3773     copy / postblit constructor or a compiler-generated copy / postblit
3774     constructor rather than using the default copying behavior (which would use
3775     $(D memcpy)).
3776 
3777     The compiler will generate a copy / postblit constructor for a struct when
3778     a member variable of that struct defines a copy / postblit constructor.
3779 
3780     Note that hasComplexCopying is also $(D true) for static arrays whose
3781     element type has a copy constructor or postblit constructor, since while
3782     the static array itself does not have a copy constructor or postblit
3783     constructor, the compiler must use the copy / postblit constructor of the
3784     elements when copying the static array.
3785 
3786     Due to $(BUGZILLA 24833), enums never have complex copying even if their
3787     base type does. Their copy / postblit constructor is never called,
3788     resulting in incorrect behavior for such enums. So, because the compiler
3789     does not treat them as having complex copying, hasComplexCopying is
3790     $(D false) for them.
3791 
3792     No other types (including class references, pointers, and unions) ever have
3793     a copy constructor or postblit constructor and thus hasComplexCopying is
3794     never $(D true) for them. It is particularly important to note that unions
3795     never have a copy constructor or postblit constructor, so if a struct
3796     contains a union which contains one or more members which have a copy
3797     constructor or postblit constructor, that struct will have to have a
3798     user-defined copy constructor or posthblit constructor which explicitly
3799     copies the correct member of the union if you don't want the current value
3800     of the union to simply be memcopied when copying the struct.
3801 
3802     If a particular piece of code cares about the existence of a copy
3803     constructor or postblit constructor specifically rather than if a type has
3804     one or the other, the traits
3805     $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T)))
3806     and
3807     $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T))) can
3808     be used, though note that they will not be true for static arrays.
3809 
3810     See_Also:
3811         $(LREF hasComplexAssignment)
3812         $(LREF hasComplexDestruction)
3813         $(DDSUBLINK spec/traits, hasCopyConstructor, $(D __traits(hasCopyConstructor, T)))
3814         $(DDSUBLINK spec/traits, hasPostblit, $(D __traits(hasPostblit, T)))
3815         $(DDSUBLINK spec/traits, isCopyable, $(D __traits(isCopyable, T)))
3816         $(DDSUBLINK spec/structs, struct-copy-constructor, The language spec for copy constructors)
3817         $(DDSUBLINK spec/structs, struct-postblit, The language spec for postblit constructors)
3818   +/
3819 template hasComplexCopying(T)
3820 {
3821     import core.internal.traits : hasElaborateCopyConstructor;
3822     alias hasComplexCopying = hasElaborateCopyConstructor!T;
3823 }
3824 
3825 ///
3826 @safe unittest
3827 {
3828     static assert(!hasComplexCopying!int);
3829     static assert(!hasComplexCopying!real);
3830     static assert(!hasComplexCopying!string);
3831     static assert(!hasComplexCopying!(int[]));
3832     static assert(!hasComplexCopying!(int[42]));
3833     static assert(!hasComplexCopying!(int[string]));
3834     static assert(!hasComplexCopying!Object);
3835 
3836     static struct NoCopyCtor1
3837     {
3838         int i;
3839     }
3840     static assert(!hasComplexCopying!NoCopyCtor1);
3841     static assert(!__traits(hasCopyConstructor, NoCopyCtor1));
3842     static assert(!__traits(hasPostblit, NoCopyCtor1));
3843 
3844     static struct NoCopyCtor2
3845     {
3846         int i;
3847 
3848         this(int i)
3849         {
3850             this.i = i;
3851         }
3852     }
3853     static assert(!hasComplexCopying!NoCopyCtor2);
3854     static assert(!__traits(hasCopyConstructor, NoCopyCtor2));
3855     static assert(!__traits(hasPostblit, NoCopyCtor2));
3856 
3857     struct HasCopyCtor
3858     {
3859         this(ref HasCopyCtor)
3860         {
3861         }
3862     }
3863     static assert( hasComplexCopying!HasCopyCtor);
3864     static assert( __traits(hasCopyConstructor, HasCopyCtor));
3865     static assert(!__traits(hasPostblit, HasCopyCtor));
3866 
3867     // hasComplexCopying does not take constness into account.
3868     // Code that wants to check whether copying works will need to test
3869     // __traits(isCopyable, T) or test that copying compiles.
3870     static assert( hasComplexCopying!(const HasCopyCtor));
3871     static assert( __traits(hasCopyConstructor, const HasCopyCtor));
3872     static assert(!__traits(hasPostblit, const HasCopyCtor));
3873     static assert(!__traits(isCopyable, const HasCopyCtor));
3874     static assert(!__traits(compiles, { const HasCopyCtor h;
3875                                         auto h2 = h; }));
3876     static assert(!is(typeof({ const HasCopyCtor h1;
3877                                auto h2 = h1; })));
3878 
3879     // An rvalue constructor is not a copy constructor.
3880     struct HasRValueCtor
3881     {
3882         this(HasRValueCtor)
3883         {
3884         }
3885     }
3886     static assert(!hasComplexCopying!HasRValueCtor);
3887     static assert(!__traits(hasCopyConstructor, HasRValueCtor));
3888     static assert(!__traits(hasPostblit, HasRValueCtor));
3889 
3890     struct HasPostblit
3891     {
3892         this(this)
3893         {
3894         }
3895     }
3896     static assert( hasComplexCopying!HasPostblit);
3897     static assert(!__traits(hasCopyConstructor, HasPostblit));
3898     static assert( __traits(hasPostblit, HasPostblit));
3899 
3900     // The compiler will generate a copy constructor if a member variable
3901     // has one.
3902     static struct HasMemberWithCopyCtor
3903     {
3904         HasCopyCtor s;
3905     }
3906     static assert( hasComplexCopying!HasMemberWithCopyCtor);
3907 
3908     // The compiler will generate a postblit constructor if a member variable
3909     // has one.
3910     static struct HasMemberWithPostblit
3911     {
3912         HasPostblit s;
3913     }
3914     static assert( hasComplexCopying!HasMemberWithPostblit);
3915 
3916     // If a struct has @disabled copying, hasComplexCopying is still true.
3917     // Code that wants to check whether copying works will need to test
3918     // __traits(isCopyable, T) or test that copying compiles.
3919     static struct DisabledCopying
3920     {
3921         @disable this(this);
3922         @disable this(ref DisabledCopying);
3923     }
3924     static assert( hasComplexCopying!DisabledCopying);
3925     static assert(!__traits(isCopyable, DisabledCopying));
3926     static assert(!__traits(compiles, { DisabledCopying dc1;
3927                                         auto dc2 = dc1; }));
3928     static assert(!is(typeof({ DisabledCopying dc1;
3929                                auto dc2 = dc1; })));
3930 
3931     // Static arrays have complex copying if their elements do.
3932     static assert( hasComplexCopying!(HasCopyCtor[1]));
3933     static assert( hasComplexCopying!(HasPostblit[1]));
3934 
3935     // Static arrays with no elements do not have complex copying, because
3936     // there's nothing to copy.
3937     static assert(!hasComplexCopying!(HasCopyCtor[0]));
3938     static assert(!hasComplexCopying!(HasPostblit[0]));
3939 
3940     // Dynamic arrays do not have complex copying, because copying them
3941     // just slices them rather than copying their elements.
3942     static assert(!hasComplexCopying!(HasCopyCtor[]));
3943     static assert(!hasComplexCopying!(HasPostblit[]));
3944 
3945     // Classes and unions do not have complex copying even if they have
3946     // members which do.
3947     class C
3948     {
3949         HasCopyCtor s;
3950     }
3951     static assert(!hasComplexCopying!C);
3952 
3953     union U
3954     {
3955         HasCopyCtor s;
3956     }
3957     static assert(!hasComplexCopying!U);
3958 
3959     // https://issues.dlang.org/show_bug.cgi?id=24833
3960     // This static assertion fails, because the compiler
3961     // currently ignores assignment operators for enum types.
3962     enum E : HasCopyCtor { a = HasCopyCtor.init }
3963     //static assert( hasComplexCopying!E);
3964 }
3965 
3966 @safe unittest
3967 {
3968     import phobos.sys.meta : AliasSeq;
3969 
3970     {
3971         struct S1 { int i; }
3972         struct S2 { real r; }
3973         struct S3 { string s; }
3974         struct S4 { int[] arr; }
3975         struct S5 { int[0] arr; }
3976         struct S6 { int[42] arr; }
3977         struct S7 { int[string] aa; }
3978 
3979         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
3980         {
3981             static assert(!hasComplexCopying!T);
3982             static assert(!hasComplexCopying!(T[0]));
3983             static assert(!hasComplexCopying!(T[42]));
3984             static assert(!hasComplexCopying!(T[]));
3985         }
3986     }
3987 
3988     // Basic variations of copy constructors.
3989     {
3990         static struct S { this(ref S) {} }
3991         static assert( hasComplexCopying!S);
3992 
3993         static struct S2 { S s; }
3994         static assert( hasComplexCopying!S2);
3995     }
3996     {
3997         static struct S { this(const ref S) const {} }
3998         static assert( hasComplexCopying!S);
3999 
4000         static struct S2 { S s; }
4001         static assert( hasComplexCopying!S2);
4002     }
4003     {
4004         static struct S
4005         {
4006             this(ref S) {}
4007             this(const ref S) const {}
4008         }
4009         static assert( hasComplexCopying!S);
4010 
4011         static struct S2 { S s; }
4012         static assert( hasComplexCopying!S2);
4013     }
4014     {
4015         static struct S { this(inout ref S) inout {} }
4016         static assert( hasComplexCopying!S);
4017 
4018         static struct S2 { S s; }
4019         static assert( hasComplexCopying!S2);
4020     }
4021     {
4022         static struct S { this(scope ref S) {} }
4023         static assert( hasComplexCopying!S);
4024 
4025         static struct S2 { S s; }
4026         static assert( hasComplexCopying!S2);
4027     }
4028     {
4029         static struct S { this(scope ref S) scope {} }
4030         static assert( hasComplexCopying!S);
4031 
4032         static struct S2 { S s; }
4033         static assert( hasComplexCopying!S2);
4034     }
4035     {
4036         static struct S { this(ref S) @safe {} }
4037         static assert( hasComplexCopying!S);
4038 
4039         static struct S2 { S s; }
4040         static assert( hasComplexCopying!S2);
4041     }
4042     {
4043         static struct S { this(ref S) nothrow {} }
4044         static assert( hasComplexCopying!S);
4045 
4046         static struct S2 { S s; }
4047         static assert( hasComplexCopying!S2);
4048     }
4049     {
4050         static struct S { this(scope inout ref S) inout scope @safe pure nothrow @nogc {} }
4051         static assert( hasComplexCopying!S);
4052 
4053         static struct S2 { S s; }
4054         static assert( hasComplexCopying!S2);
4055     }
4056 
4057     // Basic variations of postblit constructors.
4058     {
4059         static struct S { this(this) {} }
4060         static assert( hasComplexCopying!S);
4061 
4062         static struct S2 { S s; }
4063         static assert( hasComplexCopying!S2);
4064     }
4065     {
4066         static struct S { this(this) scope @safe pure nothrow @nogc {} }
4067         static assert( hasComplexCopying!S);
4068 
4069         static struct S2 { S s; }
4070         static assert( hasComplexCopying!S2);
4071     }
4072 
4073     // Rvalue constructors.
4074     {
4075         static struct S { this(S) {} }
4076         static assert(!hasComplexCopying!S);
4077 
4078         static struct S2 { S s; }
4079         static assert(!hasComplexCopying!S2);
4080     }
4081     {
4082         static struct S { this(const S) const {} }
4083         static assert(!hasComplexCopying!S);
4084 
4085         static struct S2 { S s; }
4086         static assert(!hasComplexCopying!S2);
4087     }
4088     {
4089         static struct S
4090         {
4091             this(S) {}
4092             this(const S) const {}
4093         }
4094         static assert(!hasComplexCopying!S);
4095 
4096         static struct S2 { S s; }
4097         static assert(!hasComplexCopying!S2);
4098     }
4099     {
4100         static struct S { this(inout S) inout {} }
4101         static assert(!hasComplexCopying!S);
4102 
4103         static struct S2 { S s; }
4104         static assert(!hasComplexCopying!S2);
4105     }
4106     {
4107         static struct S { this(S) @safe {} }
4108         static assert(!hasComplexCopying!S);
4109 
4110         static struct S2 { S s; }
4111         static assert(!hasComplexCopying!S2);
4112     }
4113     {
4114         static struct S { this(S) nothrow {} }
4115         static assert(!hasComplexCopying!S);
4116 
4117         static struct S2 { S s; }
4118         static assert(!hasComplexCopying!S2);
4119     }
4120     {
4121         static struct S { this(inout S) inout @safe pure nothrow @nogc {} }
4122         static assert(!hasComplexCopying!S);
4123 
4124         static struct S2 { S s; }
4125         static assert(!hasComplexCopying!S2);
4126     }
4127 
4128     // @disabled copy constructors.
4129     {
4130         static struct S { @disable this(ref S) {} }
4131         static assert( hasComplexCopying!S);
4132 
4133         static struct S2 { S s; }
4134         static assert( hasComplexCopying!S2);
4135     }
4136     {
4137         static struct S { @disable this(const ref S) const {} }
4138         static assert( hasComplexCopying!S);
4139 
4140         static struct S2 { S s; }
4141         static assert( hasComplexCopying!S2);
4142     }
4143     {
4144         static struct S
4145         {
4146             @disable this(ref S) {}
4147             this(const ref S) const {}
4148         }
4149         static assert( hasComplexCopying!S);
4150 
4151         static struct S2 { S s; }
4152         static assert( hasComplexCopying!S2);
4153     }
4154     {
4155         static struct S
4156         {
4157             this(ref S) {}
4158             @disable this(const ref S) const {}
4159         }
4160         static assert( hasComplexCopying!S);
4161 
4162         static struct S2 { S s; }
4163         static assert( hasComplexCopying!S2);
4164     }
4165     {
4166         static struct S
4167         {
4168             @disable this(ref S) {}
4169             @disable this(const ref S) const {}
4170         }
4171         static assert( hasComplexCopying!S);
4172 
4173         static struct S2 { S s; }
4174         static assert( hasComplexCopying!S2);
4175     }
4176 
4177     // Static arrays
4178     {
4179         static struct S { this(ref S) {} }
4180         static assert( hasComplexCopying!S);
4181 
4182         static assert(!hasComplexCopying!(S[0]));
4183         static assert( hasComplexCopying!(S[12]));
4184         static assert(!hasComplexCopying!(S[]));
4185 
4186         static struct S2 { S[42] s; }
4187         static assert( hasComplexCopying!S2);
4188     }
4189     {
4190         static struct S { this(this) {} }
4191         static assert( hasComplexCopying!S);
4192 
4193         static assert(!hasComplexCopying!(S[0]));
4194         static assert( hasComplexCopying!(S[12]));
4195         static assert(!hasComplexCopying!(S[]));
4196 
4197         static struct S2 { S[42] s; }
4198         static assert( hasComplexCopying!S2);
4199     }
4200 }
4201 
4202 /++
4203     Whether the given type has either a user-defined destructor or a
4204     compiler-generated destructor.
4205 
4206     The compiler will generate a destructor for a struct when a member variable
4207     of that struct defines a destructor.
4208 
4209     Note that hasComplexDestruction is also $(D true) for static arrays whose
4210     element type has a destructor, since while the static array itself does not
4211     have a destructor, the compiler must use the destructor of the elements
4212     when destroying the static array.
4213 
4214     Due to $(BUGZILLA 24833), enums never have complex destruction even if their
4215     base type does. Their destructor is never called, resulting in incorrect
4216     behavior for such enums. So, because the compiler does not treat them as
4217     having complex destruction, hasComplexDestruction is $(D false) for them.
4218 
4219     Note that while the $(DDSUBLINK spec/class, destructors, language spec)
4220     currently refers to $(D ~this()) on classes as destructors (whereas the
4221     runtime refers to them as finalizers, and they're arguably finalizers
4222     rather than destructors given how they work), classes are not considered to
4223     have complex destruction. Under normal circumstances, it's just the GC or
4224     $(REF1 destroy, object) which calls the destructor / finalizer on a class
4225     (and it's not guaranteed that a class destructor / finalizer will even ever
4226     be called), which is in stark contrast to structs, which normally live on
4227     the stack and need to be destroyed when they leave scope. So,
4228     hasComplexDestruction is concerned with whether that type will have a
4229     destructor that's run when it leaves scope and not with what happens when
4230     the GC destroys an object prior to freeing its memory.
4231 
4232     No other types (including pointers and unions) ever have a destructor and
4233     thus hasComplexDestruction is never $(D true) for them. It is particularly
4234     important to note that unions never have a destructor, so if a struct
4235     contains a union which contains one or more members which have a
4236     destructor, that struct will have to have a user-defined destructor which
4237     explicitly calls $(REF1 destroy, object) on the correct member of the
4238     union if you want the object in question to be destroyed properly.
4239 
4240     See_Also:
4241         $(LREF hasComplexAssignment)
4242         $(LREF hasComplexCopying)
4243         $(REF destroy, object)
4244         $(DDSUBLINK spec/structs, struct-destructor, The language spec for destructors)
4245         $(DDSUBLINK spec/class, destructors, The language spec for class finalizers)
4246   +/
4247 template hasComplexDestruction(T)
4248 {
4249     import core.internal.traits : hasElaborateDestructor;
4250     alias hasComplexDestruction = hasElaborateDestructor!T;
4251 }
4252 
4253 ///
4254 @safe unittest
4255 {
4256     static assert(!hasComplexDestruction!int);
4257     static assert(!hasComplexDestruction!real);
4258     static assert(!hasComplexDestruction!string);
4259     static assert(!hasComplexDestruction!(int[]));
4260     static assert(!hasComplexDestruction!(int[42]));
4261     static assert(!hasComplexDestruction!(int[string]));
4262     static assert(!hasComplexDestruction!Object);
4263 
4264     static struct NoDtor
4265     {
4266         int i;
4267     }
4268     static assert(!hasComplexDestruction!NoDtor);
4269 
4270     struct HasDtor
4271     {
4272         ~this() {}
4273     }
4274     static assert( hasComplexDestruction!HasDtor);
4275 
4276     // The compiler will generate a destructor if a member variable has one.
4277     static struct HasMemberWithDtor
4278     {
4279         HasDtor s;
4280     }
4281     static assert( hasComplexDestruction!HasMemberWithDtor);
4282 
4283     // If a struct has @disabled destruction, hasComplexDestruction is still
4284     // true. Code that wants to check whether destruction works can either
4285     // test for whether the __xdtor member is disabled, or it can test whether
4286     // code that will destroy the object compiles. That being said, a disabled
4287     // destructor probably isn't very common in practice, because about all that
4288     // such a type is good for is being allocated on the heap.
4289     static struct DisabledDtor
4290     {
4291         @disable ~this() {}
4292     }
4293     static assert( hasComplexDestruction!DisabledDtor);
4294     static assert( __traits(isDisabled,
4295                             __traits(getMember, DisabledDtor, "__xdtor")));
4296 
4297     // A type with a disabled destructor cannot be created on the stack or used
4298     // in any way that would ever trigger a destructor, making it pretty much
4299     // useless outside of providing a way to force a struct to be allocated on
4300     // the heap - though that could be useful in some situations, since it
4301     // it makes it possible to have a type that has to be a reference type but
4302     // which doesn't have the overhead of a class.
4303     static assert(!__traits(compiles, { DisabledDtor d; }));
4304     static assert( __traits(compiles, { auto d = new DisabledDtor; }));
4305 
4306     // Static arrays have complex destruction if their elements do.
4307     static assert( hasComplexDestruction!(HasDtor[1]));
4308 
4309     // Static arrays with no elements do not have complex destruction, because
4310     // there's nothing to destroy.
4311     static assert(!hasComplexDestruction!(HasDtor[0]));
4312 
4313     // Dynamic arrays do not have complex destruction, because their elements
4314     // are contained in the memory that the dynamic array is a slice of and not
4315     // in the dynamic array itself, so there's nothing to destroy when a
4316     // dynamic array leaves scope.
4317     static assert(!hasComplexDestruction!(HasDtor[]));
4318 
4319     // Classes and unions do not have complex copying even if they have
4320     // members which do.
4321     class C
4322     {
4323         HasDtor s;
4324     }
4325     static assert(!hasComplexDestruction!C);
4326 
4327     union U
4328     {
4329         HasDtor s;
4330     }
4331     static assert(!hasComplexDestruction!U);
4332 
4333     // https://issues.dlang.org/show_bug.cgi?id=24833
4334     // This static assertion fails, because the compiler
4335     // currently ignores assignment operators for enum types.
4336     enum E : HasDtor { a = HasDtor.init }
4337     //static assert( hasComplexDestruction!E);
4338 }
4339 
4340 @safe unittest
4341 {
4342     import phobos.sys.meta : AliasSeq;
4343 
4344     {
4345         struct S1 { int i; }
4346         struct S2 { real r; }
4347         struct S3 { string s; }
4348         struct S4 { int[] arr; }
4349         struct S5 { int[0] arr; }
4350         struct S6 { int[42] arr; }
4351         struct S7 { int[string] aa; }
4352 
4353         static foreach (T; AliasSeq!(S1, S2, S3, S4, S5, S6, S7))
4354         {
4355             static assert(!hasComplexDestruction!T);
4356             static assert(!hasComplexDestruction!(T[0]));
4357             static assert(!hasComplexDestruction!(T[42]));
4358             static assert(!hasComplexDestruction!(T[]));
4359         }
4360     }
4361 
4362     // Basic variations of destructors.
4363     {
4364         static struct S { ~this() {} }
4365         static assert( hasComplexDestruction!S);
4366 
4367         static struct S2 { S s; }
4368         static assert( hasComplexDestruction!S2);
4369     }
4370     {
4371         static struct S { ~this() const {} }
4372         static assert( hasComplexDestruction!S);
4373 
4374         static struct S2 { S s; }
4375         static assert( hasComplexDestruction!S2);
4376     }
4377     {
4378         static struct S { ~this() @safe {} }
4379         static assert( hasComplexDestruction!S);
4380 
4381         static struct S2 { S s; }
4382         static assert( hasComplexDestruction!S2);
4383     }
4384     {
4385         static struct S { ~this() @safe pure nothrow @nogc {} }
4386         static assert( hasComplexDestruction!S);
4387 
4388         static struct S2 { S s; }
4389         static assert( hasComplexDestruction!S2);
4390     }
4391 
4392     // @disabled destructors.
4393     {
4394         static struct S { @disable ~this() {} }
4395         static assert( __traits(isDisabled,
4396                                 __traits(getMember, S, "__xdtor")));
4397 
4398         static struct S2 { S s; }
4399         static assert( hasComplexDestruction!S2);
4400         static assert( __traits(isDisabled,
4401                                 __traits(getMember, S2, "__xdtor")));
4402     }
4403 
4404     // Static arrays
4405     {
4406         static struct S { ~this() {} }
4407         static assert( hasComplexDestruction!S);
4408 
4409         static assert(!hasComplexDestruction!(S[0]));
4410         static assert( hasComplexDestruction!(S[12]));
4411         static assert(!hasComplexDestruction!(S[]));
4412 
4413         static struct S2 { S[42] s; }
4414         static assert( hasComplexDestruction!S2);
4415     }
4416 }
4417 
4418 /++
4419     Evaluates to $(D true) if the given type is one or more of the following,
4420     or if it's a struct, union, or static array which contains one or more of
4421     the following:
4422 
4423     $(OL $(LI A raw pointer)
4424          $(LI A class reference)
4425          $(LI An interface reference)
4426          $(LI A dynamic array)
4427          $(LI An associative array)
4428          $(LI A delegate)
4429          $(LI A struct with a
4430               $(DDSUBLINK spec/traits, isNested, $(D context pointer)).))
4431 
4432     Note that function pointers are not considered to have indirections, because
4433     they do not point to any data (whereas a delegate has a context pointer
4434     and therefore has data that it points to).
4435 
4436     Also, while static arrays do not have indirections unless their element
4437     type has indirections, static arrays with an element type of $(D void) are
4438     considered to have indirections by hasIndirections, because it's unknown
4439     what type their elements actually are, so they $(I might) have
4440     indirections, and thus, the conservative approach is to assume that they do
4441     have indirections.
4442 
4443     Static arrays with length 0 do not have indirections no matter what their
4444     element type is, since they don't actually have any elements.
4445   +/
4446 version (StdDdoc) template hasIndirections(T)
4447 {
4448     import core.internal.traits : _hasIndirections = hasIndirections;
4449     alias hasIndirections = _hasIndirections!T;
4450 }
4451 else
4452 {
4453     import core.internal.traits : _hasIndirections = hasIndirections;
4454     alias hasIndirections = _hasIndirections;
4455 }
4456 
4457 ///
4458 @safe unittest
4459 {
4460     static class C {}
4461     static interface I {}
4462 
4463     static assert( hasIndirections!(int*));
4464     static assert( hasIndirections!C);
4465     static assert( hasIndirections!I);
4466     static assert( hasIndirections!(int[]));
4467     static assert( hasIndirections!(int[string]));
4468     static assert( hasIndirections!(void delegate()));
4469     static assert( hasIndirections!(string delegate(int)));
4470 
4471     static assert(!hasIndirections!(void function()));
4472     static assert(!hasIndirections!int);
4473 
4474     static assert(!hasIndirections!(ubyte[9]));
4475     static assert( hasIndirections!(ubyte[9]*));
4476     static assert( hasIndirections!(ubyte*[9]));
4477     static assert(!hasIndirections!(ubyte*[0]));
4478     static assert( hasIndirections!(ubyte[]));
4479 
4480     static assert( hasIndirections!(void[]));
4481     static assert( hasIndirections!(void[42]));
4482 
4483     static struct NoContext
4484     {
4485         int i;
4486     }
4487 
4488     int local;
4489 
4490     struct HasContext
4491     {
4492         int foo() { return local; }
4493     }
4494 
4495     struct HasMembersWithIndirections
4496     {
4497         int* ptr;
4498     }
4499 
4500     static assert(!hasIndirections!NoContext);
4501     static assert( hasIndirections!HasContext);
4502     static assert( hasIndirections!HasMembersWithIndirections);
4503 
4504     union U1
4505     {
4506         int i;
4507         float f;
4508     }
4509     static assert(!hasIndirections!U1);
4510 
4511     union U2
4512     {
4513         int i;
4514         int[] arr;
4515     }
4516     static assert( hasIndirections!U2);
4517 }
4518 
4519 // hasIndirections with types which aren't aggregate types.
4520 @safe unittest
4521 {
4522     import phobos.sys.meta : AliasSeq;
4523 
4524     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
4525 
4526     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
4527                           float, double, real, char, wchar, dchar, int function(string), void))
4528     {
4529         mixin testWithQualifiers!(T, false);
4530         mixin testWithQualifiers!(T*, true);
4531         mixin testWithQualifiers!(T[], true);
4532 
4533         mixin testWithQualifiers!(T[42], is(T == void));
4534         mixin testWithQualifiers!(T[0], false);
4535 
4536         mixin testWithQualifiers!(T*[42], true);
4537         mixin testWithQualifiers!(T*[0], false);
4538 
4539         mixin testWithQualifiers!(T[][42], true);
4540         mixin testWithQualifiers!(T[][0], false);
4541     }
4542 
4543     foreach (T; AliasSeq!(int[int], int delegate(string)))
4544     {
4545         mixin testWithQualifiers!(T, true);
4546         mixin testWithQualifiers!(T*, true);
4547         mixin testWithQualifiers!(T[], true);
4548 
4549         mixin testWithQualifiers!(T[42], true);
4550         mixin testWithQualifiers!(T[0], false);
4551 
4552         mixin testWithQualifiers!(T*[42], true);
4553         mixin testWithQualifiers!(T*[0], false);
4554 
4555         mixin testWithQualifiers!(T[][42], true);
4556         mixin testWithQualifiers!(T[][0], false);
4557     }
4558 }
4559 
4560 // hasIndirections with structs.
4561 @safe unittest
4562 {
4563     import phobos.sys.meta : AliasSeq;
4564 
4565     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
4566 
4567     {
4568         struct S {}
4569         mixin testWithQualifiers!(S, false);
4570     }
4571     {
4572         static struct S {}
4573         mixin testWithQualifiers!(S, false);
4574     }
4575     {
4576         struct S { void foo() {} }
4577         mixin testWithQualifiers!(S, true);
4578     }
4579     {
4580         static struct S { void foo() {} }
4581         mixin testWithQualifiers!(S, false);
4582     }
4583 
4584     // Structs with members which aren't aggregate types and don't have indirections.
4585     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
4586                           float, double, real, char, wchar, dchar, int function(string)))
4587     {
4588         // No indirections.
4589         {
4590             struct S { T member; }
4591             mixin testWithQualifiers!(S, false);
4592         }
4593         {
4594             struct S { const T member; }
4595             mixin testWithQualifiers!(S, false);
4596         }
4597         {
4598             struct S { immutable T member; }
4599             mixin testWithQualifiers!(S, false);
4600         }
4601         {
4602             struct S { shared T member; }
4603             mixin testWithQualifiers!(S, false);
4604         }
4605 
4606         {
4607             static struct S { T member; void foo() {} }
4608             mixin testWithQualifiers!(S, false);
4609         }
4610         {
4611             static struct S { const T member; void foo() {} }
4612             mixin testWithQualifiers!(S, false);
4613         }
4614         {
4615             static struct S { immutable T member; void foo() {} }
4616             mixin testWithQualifiers!(S, false);
4617         }
4618         {
4619             static struct S { shared T member; void foo() {} }
4620             mixin testWithQualifiers!(S, false);
4621         }
4622 
4623         // Has context pointer.
4624         {
4625             struct S { T member; void foo() {} }
4626             mixin testWithQualifiers!(S, true);
4627         }
4628         {
4629             struct S { const T member; void foo() {} }
4630             mixin testWithQualifiers!(S, true);
4631         }
4632         {
4633             struct S { immutable T member; void foo() {} }
4634             mixin testWithQualifiers!(S, true);
4635         }
4636         {
4637             struct S { shared T member; void foo() {} }
4638             mixin testWithQualifiers!(S, true);
4639         }
4640 
4641         {
4642             T local;
4643             struct S { void foo() { auto v = local; } }
4644             mixin testWithQualifiers!(S, true);
4645         }
4646         {
4647             const T local;
4648             struct S { void foo() { auto v = local; } }
4649             mixin testWithQualifiers!(S, true);
4650         }
4651         {
4652             immutable T local;
4653             struct S { void foo() { auto v = local; } }
4654             mixin testWithQualifiers!(S, true);
4655         }
4656         {
4657             shared T local;
4658             struct S { void foo() @trusted { auto v = cast() local; } }
4659             mixin testWithQualifiers!(S, true);
4660         }
4661 
4662         // Pointers.
4663         {
4664             struct S { T* member; }
4665             mixin testWithQualifiers!(S, true);
4666         }
4667         {
4668             struct S { const(T)* member; }
4669             mixin testWithQualifiers!(S, true);
4670         }
4671         {
4672             struct S { const T* member; }
4673             mixin testWithQualifiers!(S, true);
4674         }
4675         {
4676             struct S { immutable T* member; }
4677             mixin testWithQualifiers!(S, true);
4678         }
4679         {
4680             struct S { shared T* member; }
4681             mixin testWithQualifiers!(S, true);
4682         }
4683 
4684         // Dynamic arrays.
4685         {
4686             struct S { T[] member; }
4687             mixin testWithQualifiers!(S, true);
4688         }
4689         {
4690             struct S { const(T)[] member; }
4691             mixin testWithQualifiers!(S, true);
4692         }
4693         {
4694             struct S { const T[] member; }
4695             mixin testWithQualifiers!(S, true);
4696         }
4697         {
4698             struct S { immutable T[] member; }
4699             mixin testWithQualifiers!(S, true);
4700         }
4701         {
4702             struct S { shared T[] member; }
4703             mixin testWithQualifiers!(S, true);
4704         }
4705 
4706         // Static arrays.
4707         {
4708             struct S { T[1] member; }
4709             mixin testWithQualifiers!(S, false);
4710         }
4711         {
4712             struct S { const(T)[1] member; }
4713             mixin testWithQualifiers!(S, false);
4714         }
4715         {
4716             struct S { const T[1] member; }
4717             mixin testWithQualifiers!(S, false);
4718         }
4719         {
4720             struct S { immutable T[1] member; }
4721             mixin testWithQualifiers!(S, false);
4722         }
4723         {
4724             struct S { shared T[1] member; }
4725             mixin testWithQualifiers!(S, false);
4726         }
4727 
4728         // Static arrays of pointers.
4729         {
4730             struct S { T*[1] member; }
4731             mixin testWithQualifiers!(S, true);
4732         }
4733         {
4734             struct S { const(T)*[1] member; }
4735             mixin testWithQualifiers!(S, true);
4736         }
4737         {
4738             struct S { const(T*)[1] member; }
4739             mixin testWithQualifiers!(S, true);
4740         }
4741         {
4742             struct S { const T*[1] member; }
4743             mixin testWithQualifiers!(S, true);
4744         }
4745         {
4746             struct S { immutable T*[1] member; }
4747             mixin testWithQualifiers!(S, true);
4748         }
4749         {
4750             struct S { shared T*[1] member; }
4751             mixin testWithQualifiers!(S, true);
4752         }
4753 
4754         {
4755             struct S { T*[0] member; }
4756             mixin testWithQualifiers!(S, false);
4757         }
4758         {
4759             struct S { const(T)*[0] member; }
4760             mixin testWithQualifiers!(S, false);
4761         }
4762         {
4763             struct S { const(T*)[0] member; }
4764             mixin testWithQualifiers!(S, false);
4765         }
4766         {
4767             struct S { const T*[0] member; }
4768             mixin testWithQualifiers!(S, false);
4769         }
4770         {
4771             struct S { immutable T*[0] member; }
4772             mixin testWithQualifiers!(S, false);
4773         }
4774         {
4775             struct S { shared T*[0] member; }
4776             mixin testWithQualifiers!(S, false);
4777         }
4778 
4779         // Static arrays of dynamic arrays.
4780         {
4781             struct S { T[][1] member; }
4782             mixin testWithQualifiers!(S, true);
4783         }
4784         {
4785             struct S { const(T)[][1] member; }
4786             mixin testWithQualifiers!(S, true);
4787         }
4788         {
4789             struct S { const(T[])[1] member; }
4790             mixin testWithQualifiers!(S, true);
4791         }
4792         {
4793             struct S { const T[][1] member; }
4794             mixin testWithQualifiers!(S, true);
4795         }
4796         {
4797             struct S { immutable T[][1] member; }
4798             mixin testWithQualifiers!(S, true);
4799         }
4800         {
4801             struct S { shared T[][1] member; }
4802             mixin testWithQualifiers!(S, true);
4803         }
4804 
4805         {
4806             struct S { T[][0] member; }
4807             mixin testWithQualifiers!(S, false);
4808         }
4809         {
4810             struct S { const(T)[][0] member; }
4811             mixin testWithQualifiers!(S, false);
4812         }
4813         {
4814             struct S { const(T[])[0] member; }
4815             mixin testWithQualifiers!(S, false);
4816         }
4817         {
4818             struct S { const T[][0] member; }
4819             mixin testWithQualifiers!(S, false);
4820         }
4821         {
4822             struct S { immutable T[][0] member; }
4823             mixin testWithQualifiers!(S, false);
4824         }
4825         {
4826             struct S { shared T[][0] member; }
4827             mixin testWithQualifiers!(S, false);
4828         }
4829     }
4830 
4831     // Structs with arrays of void.
4832     {
4833         {
4834             static struct S { void[] member; }
4835             mixin testWithQualifiers!(S, true);
4836         }
4837         {
4838             static struct S { void[1] member; }
4839             mixin testWithQualifiers!(S, true);
4840         }
4841         {
4842             static struct S { void[0] member; }
4843             mixin testWithQualifiers!(S, false);
4844         }
4845     }
4846 
4847     // Structs with multiple members, testing pointer types.
4848     {
4849         static struct S { int i; bool b; }
4850         mixin testWithQualifiers!(S, false);
4851     }
4852     {
4853         static struct S { int* i; bool b; }
4854         mixin testWithQualifiers!(S, true);
4855     }
4856     {
4857         static struct S { int i; bool* b; }
4858         mixin testWithQualifiers!(S, true);
4859     }
4860     {
4861         static struct S { int* i; bool* b; }
4862         mixin testWithQualifiers!(S, true);
4863     }
4864 
4865     // Structs with multiple members, testing dynamic arrays.
4866     {
4867         static struct S { int[] arr; }
4868         mixin testWithQualifiers!(S, true);
4869     }
4870     {
4871         static struct S { int i; int[] arr; }
4872         mixin testWithQualifiers!(S, true);
4873     }
4874     {
4875         static struct S { int[] arr; int i; }
4876         mixin testWithQualifiers!(S, true);
4877     }
4878 
4879     // Structs with multiple members, testing static arrays.
4880     {
4881         static struct S { int[1] arr; }
4882         mixin testWithQualifiers!(S, false);
4883     }
4884     {
4885         static struct S { int i; int[1] arr; }
4886         mixin testWithQualifiers!(S, false);
4887     }
4888     {
4889         static struct S { int[1] arr; int i; }
4890         mixin testWithQualifiers!(S, false);
4891     }
4892 
4893     {
4894         static struct S { int*[0] arr; }
4895         mixin testWithQualifiers!(S, false);
4896     }
4897     {
4898         static struct S { int i; int*[0] arr; }
4899         mixin testWithQualifiers!(S, false);
4900     }
4901     {
4902         static struct S { int*[0] arr; int i; }
4903         mixin testWithQualifiers!(S, false);
4904     }
4905 
4906     {
4907         static struct S { string[42] arr; }
4908         mixin testWithQualifiers!(S, true);
4909     }
4910     {
4911         static struct S { int i; string[42] arr; }
4912         mixin testWithQualifiers!(S, true);
4913     }
4914     {
4915         static struct S { string[42] arr; int i; }
4916         mixin testWithQualifiers!(S, true);
4917     }
4918 
4919     // Structs with associative arrays.
4920     {
4921         static struct S { int[string] aa; }
4922         mixin testWithQualifiers!(S, true);
4923     }
4924     {
4925         static struct S { int i; int[string] aa; }
4926         mixin testWithQualifiers!(S, true);
4927     }
4928     {
4929         static struct S { int[string] aa; int i; }
4930         mixin testWithQualifiers!(S, true);
4931     }
4932 
4933     {
4934         static struct S { int[42][int] aa; }
4935         mixin testWithQualifiers!(S, true);
4936     }
4937     {
4938         static struct S { int[0][int] aa; }
4939         mixin testWithQualifiers!(S, true);
4940     }
4941 
4942     // Structs with classes.
4943     {
4944         class C {}
4945         struct S { C c; }
4946         mixin testWithQualifiers!(S, true);
4947     }
4948     {
4949         interface I {}
4950         struct S { I i; }
4951         mixin testWithQualifiers!(S, true);
4952     }
4953 
4954     // Structs with delegates.
4955     {
4956         struct S { void delegate() d; }
4957         mixin testWithQualifiers!(S, true);
4958     }
4959     {
4960         struct S { int delegate(int) d; }
4961         mixin testWithQualifiers!(S, true);
4962     }
4963 
4964     // Structs multiple layers deep.
4965     {
4966         struct S1 { int i; }
4967         struct S2 { S1 s; }
4968         struct S3 { S2 s; }
4969         struct S4 { S3 s; }
4970         struct S5 { S4 s; }
4971         struct S6 { S5 s; }
4972         struct S7 { S6[0] s; }
4973         struct S8 { S7 s; }
4974         struct S9 { S8 s; }
4975         struct S10 { S9 s; }
4976         mixin testWithQualifiers!(S1, false);
4977         mixin testWithQualifiers!(S2, false);
4978         mixin testWithQualifiers!(S3, false);
4979         mixin testWithQualifiers!(S4, false);
4980         mixin testWithQualifiers!(S5, false);
4981         mixin testWithQualifiers!(S6, false);
4982         mixin testWithQualifiers!(S7, false);
4983         mixin testWithQualifiers!(S8, false);
4984         mixin testWithQualifiers!(S9, false);
4985         mixin testWithQualifiers!(S10, false);
4986     }
4987     {
4988         struct S1 { int* i; }
4989         struct S2 { S1 s; }
4990         struct S3 { S2 s; }
4991         struct S4 { S3 s; }
4992         struct S5 { S4 s; }
4993         struct S6 { S5 s; }
4994         struct S7 { S6[0] s; }
4995         struct S8 { S7 s; }
4996         struct S9 { S8 s; }
4997         struct S10 { S9 s; }
4998         mixin testWithQualifiers!(S1, true);
4999         mixin testWithQualifiers!(S2, true);
5000         mixin testWithQualifiers!(S3, true);
5001         mixin testWithQualifiers!(S4, true);
5002         mixin testWithQualifiers!(S5, true);
5003         mixin testWithQualifiers!(S6, true);
5004         mixin testWithQualifiers!(S7, false);
5005         mixin testWithQualifiers!(S8, false);
5006         mixin testWithQualifiers!(S9, false);
5007         mixin testWithQualifiers!(S10, false);
5008     }
5009 }
5010 
5011 // hasIndirections with unions.
5012 @safe unittest
5013 {
5014     import phobos.sys.meta : AliasSeq;
5015 
5016     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
5017 
5018     {
5019         union U {}
5020         mixin testWithQualifiers!(U, false);
5021     }
5022     {
5023         static union U {}
5024         mixin testWithQualifiers!(U, false);
5025     }
5026 
5027     // Unions with members which aren't aggregate types and don't have indirections.
5028     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
5029                           float, double, real, char, wchar, dchar, int function(string)))
5030     {
5031         // No indirections.
5032         {
5033             union U { T member; }
5034             mixin testWithQualifiers!(U, false);
5035         }
5036         {
5037             union U { const T member; }
5038             mixin testWithQualifiers!(U, false);
5039         }
5040         {
5041             union U { immutable T member; }
5042             mixin testWithQualifiers!(U, false);
5043         }
5044         {
5045             union U { shared T member; }
5046             mixin testWithQualifiers!(U, false);
5047         }
5048 
5049         // Pointers.
5050         {
5051             union U { T* member; }
5052             mixin testWithQualifiers!(U, true);
5053         }
5054         {
5055             union U { const(T)* member; }
5056             mixin testWithQualifiers!(U, true);
5057         }
5058         {
5059             union U { const T* member; }
5060             mixin testWithQualifiers!(U, true);
5061         }
5062         {
5063             union U { immutable T* member; }
5064             mixin testWithQualifiers!(U, true);
5065         }
5066         {
5067             union U { shared T* member; }
5068             mixin testWithQualifiers!(U, true);
5069         }
5070 
5071         // Dynamic arrays.
5072         {
5073             union U { T[] member; }
5074             mixin testWithQualifiers!(U, true);
5075         }
5076         {
5077             union U { const(T)[] member; }
5078             mixin testWithQualifiers!(U, true);
5079         }
5080         {
5081             union U { const T[] member; }
5082             mixin testWithQualifiers!(U, true);
5083         }
5084         {
5085             union U { immutable T[] member; }
5086             mixin testWithQualifiers!(U, true);
5087         }
5088         {
5089             union U { shared T[] member; }
5090             mixin testWithQualifiers!(U, true);
5091         }
5092 
5093         // Static arrays.
5094         {
5095             union U { T[1] member; }
5096             mixin testWithQualifiers!(U, false);
5097         }
5098         {
5099             union U { const(T)[1] member; }
5100             mixin testWithQualifiers!(U, false);
5101         }
5102         {
5103             union U { const T[1] member; }
5104             mixin testWithQualifiers!(U, false);
5105         }
5106         {
5107             union U { immutable T[1] member; }
5108             mixin testWithQualifiers!(U, false);
5109         }
5110         {
5111             union U { shared T[1] member; }
5112             mixin testWithQualifiers!(U, false);
5113         }
5114 
5115         // Static arrays of pointers.
5116         {
5117             union U { T*[1] member; }
5118             mixin testWithQualifiers!(U, true);
5119         }
5120         {
5121             union U { const(T)*[1] member; }
5122             mixin testWithQualifiers!(U, true);
5123         }
5124         {
5125             union U { const(T*)[1] member; }
5126             mixin testWithQualifiers!(U, true);
5127         }
5128         {
5129             union U { const T*[1] member; }
5130             mixin testWithQualifiers!(U, true);
5131         }
5132         {
5133             union U { immutable T*[1] member; }
5134             mixin testWithQualifiers!(U, true);
5135         }
5136         {
5137             union U { shared T*[1] member; }
5138             mixin testWithQualifiers!(U, true);
5139         }
5140 
5141         {
5142             union U { T*[0] member; }
5143             mixin testWithQualifiers!(U, false);
5144         }
5145         {
5146             union U { const(T)*[0] member; }
5147             mixin testWithQualifiers!(U, false);
5148         }
5149         {
5150             union U { const(T*)[0] member; }
5151             mixin testWithQualifiers!(U, false);
5152         }
5153         {
5154             union U { const T*[0] member; }
5155             mixin testWithQualifiers!(U, false);
5156         }
5157         {
5158             union U { immutable T*[0] member; }
5159             mixin testWithQualifiers!(U, false);
5160         }
5161         {
5162             union U { shared T*[0] member; }
5163             mixin testWithQualifiers!(U, false);
5164         }
5165 
5166         // Static arrays of dynamic arrays.
5167         {
5168             union U { T[][1] member; }
5169             mixin testWithQualifiers!(U, true);
5170         }
5171         {
5172             union U { const(T)[][1] member; }
5173             mixin testWithQualifiers!(U, true);
5174         }
5175         {
5176             union U { const(T[])[1] member; }
5177             mixin testWithQualifiers!(U, true);
5178         }
5179         {
5180             union U { const T[][1] member; }
5181             mixin testWithQualifiers!(U, true);
5182         }
5183         {
5184             union U { immutable T[][1] member; }
5185             mixin testWithQualifiers!(U, true);
5186         }
5187         {
5188             union U { shared T[][1] member; }
5189             mixin testWithQualifiers!(U, true);
5190         }
5191 
5192         {
5193             union U { T[][0] member; }
5194             mixin testWithQualifiers!(U, false);
5195         }
5196         {
5197             union U { const(T)[][0] member; }
5198             mixin testWithQualifiers!(U, false);
5199         }
5200         {
5201             union U { const(T[])[0] member; }
5202             mixin testWithQualifiers!(U, false);
5203         }
5204         {
5205             union U { const T[][0] member; }
5206             mixin testWithQualifiers!(U, false);
5207         }
5208         {
5209             union U { immutable T[][0] member; }
5210             mixin testWithQualifiers!(U, false);
5211         }
5212         {
5213             union U { shared T[][0] member; }
5214             mixin testWithQualifiers!(U, false);
5215         }
5216     }
5217 
5218     // Unions with arrays of void.
5219     {
5220         {
5221             static union U { void[] member; }
5222             mixin testWithQualifiers!(U, true);
5223         }
5224         {
5225             static union U { void[1] member; }
5226             mixin testWithQualifiers!(U, true);
5227         }
5228         {
5229             static union U { void[0] member; }
5230             mixin testWithQualifiers!(U, false);
5231         }
5232     }
5233 
5234     // Unions with multiple members, testing pointer types.
5235     {
5236         static union U { int i; bool b; }
5237         mixin testWithQualifiers!(U, false);
5238     }
5239     {
5240         static union U { int* i; bool b; }
5241         mixin testWithQualifiers!(U, true);
5242     }
5243     {
5244         static union U { int i; bool* b; }
5245         mixin testWithQualifiers!(U, true);
5246     }
5247     {
5248         static union U { int* i; bool* b; }
5249         mixin testWithQualifiers!(U, true);
5250     }
5251 
5252     // Unions with multiple members, testing dynamic arrays.
5253     {
5254         static union U { int[] arr; }
5255         mixin testWithQualifiers!(U, true);
5256     }
5257     {
5258         static union U { int i; int[] arr; }
5259         mixin testWithQualifiers!(U, true);
5260     }
5261     {
5262         static union U { int[] arr; int i; }
5263         mixin testWithQualifiers!(U, true);
5264     }
5265 
5266     // Unions with multiple members, testing static arrays.
5267     {
5268         static union U { int[1] arr; }
5269         mixin testWithQualifiers!(U, false);
5270     }
5271     {
5272         static union U { int i; int[1] arr; }
5273         mixin testWithQualifiers!(U, false);
5274     }
5275     {
5276         static union U { int[1] arr; int i; }
5277         mixin testWithQualifiers!(U, false);
5278     }
5279 
5280     {
5281         static union U { int*[0] arr; }
5282         mixin testWithQualifiers!(U, false);
5283     }
5284     {
5285         static union U { int i; int*[0] arr; }
5286         mixin testWithQualifiers!(U, false);
5287     }
5288     {
5289         static union U { int*[0] arr; int i; }
5290         mixin testWithQualifiers!(U, false);
5291     }
5292 
5293     {
5294         static union U { string[42] arr; }
5295         mixin testWithQualifiers!(U, true);
5296     }
5297     {
5298         static union U { int i; string[42] arr; }
5299         mixin testWithQualifiers!(U, true);
5300     }
5301     {
5302         static union U { string[42] arr; int i; }
5303         mixin testWithQualifiers!(U, true);
5304     }
5305 
5306     // Unions with associative arrays.
5307     {
5308         static union U { int[string] aa; }
5309         mixin testWithQualifiers!(U, true);
5310     }
5311     {
5312         static union U { int i; int[string] aa; }
5313         mixin testWithQualifiers!(U, true);
5314     }
5315     {
5316         static union U { int[string] aa; int i; }
5317         mixin testWithQualifiers!(U, true);
5318     }
5319 
5320     {
5321         static union U { int[42][int] aa; }
5322         mixin testWithQualifiers!(U, true);
5323     }
5324     {
5325         static union U { int[0][int] aa; }
5326         mixin testWithQualifiers!(U, true);
5327     }
5328 
5329     // Unions with classes.
5330     {
5331         class C {}
5332         union U { C c; }
5333         mixin testWithQualifiers!(U, true);
5334     }
5335     {
5336         interface I {}
5337         union U { I i; }
5338         mixin testWithQualifiers!(U, true);
5339     }
5340 
5341     // Unions with delegates.
5342     {
5343         union U { void delegate() d; }
5344         mixin testWithQualifiers!(U, true);
5345     }
5346     {
5347         union U { int delegate(int) d; }
5348         mixin testWithQualifiers!(U, true);
5349     }
5350 
5351     // Unions multiple layers deep.
5352     {
5353         union U1 { int i; }
5354         union U2 { U1 s; }
5355         union U3 { U2 s; }
5356         union U4 { U3 s; }
5357         union U5 { U4 s; }
5358         union U6 { U5 s; }
5359         union U7 { U6[0] s; }
5360         union U8 { U7 s; }
5361         union U9 { U8 s; }
5362         union U10 { U9 s; }
5363         mixin testWithQualifiers!(U1, false);
5364         mixin testWithQualifiers!(U2, false);
5365         mixin testWithQualifiers!(U3, false);
5366         mixin testWithQualifiers!(U4, false);
5367         mixin testWithQualifiers!(U5, false);
5368         mixin testWithQualifiers!(U6, false);
5369         mixin testWithQualifiers!(U7, false);
5370         mixin testWithQualifiers!(U8, false);
5371         mixin testWithQualifiers!(U9, false);
5372         mixin testWithQualifiers!(U10, false);
5373     }
5374     {
5375         union U1 { int* i; }
5376         union U2 { U1 s; }
5377         union U3 { U2 s; }
5378         union U4 { U3 s; }
5379         union U5 { U4 s; }
5380         union U6 { U5 s; }
5381         union U7 { U6[0] s; }
5382         union U8 { U7 s; }
5383         union U9 { U8 s; }
5384         union U10 { U9 s; }
5385         mixin testWithQualifiers!(U1, true);
5386         mixin testWithQualifiers!(U2, true);
5387         mixin testWithQualifiers!(U3, true);
5388         mixin testWithQualifiers!(U4, true);
5389         mixin testWithQualifiers!(U5, true);
5390         mixin testWithQualifiers!(U6, true);
5391         mixin testWithQualifiers!(U7, false);
5392         mixin testWithQualifiers!(U8, false);
5393         mixin testWithQualifiers!(U9, false);
5394         mixin testWithQualifiers!(U10, false);
5395     }
5396 }
5397 
5398 // hasIndirections with classes and interfaces
5399 @safe unittest
5400 {
5401     import phobos.sys.meta : AliasSeq;
5402 
5403     alias testWithQualifiers = assertWithQualifiers!hasIndirections;
5404 
5405     {
5406         class C {}
5407         mixin testWithQualifiers!(C, true);
5408     }
5409 
5410     foreach (T; AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
5411                           float, double, real, char, wchar, dchar, int function(string),
5412                           int[int], string delegate(int)))
5413     {
5414         {
5415             class C { T member; }
5416             mixin testWithQualifiers!(C, true);
5417         }
5418         {
5419             class C { const T member; }
5420             mixin testWithQualifiers!(C, true);
5421         }
5422         {
5423             class C { immutable T member; }
5424             mixin testWithQualifiers!(C, true);
5425         }
5426         {
5427             class C { shared T member; }
5428             mixin testWithQualifiers!(C, true);
5429         }
5430     }
5431 
5432     {
5433         interface I {}
5434         mixin testWithQualifiers!(I, true);
5435     }
5436 }
5437 
5438 /++
5439     Takes a type which is an associative array and evaluates to the type of the
5440     keys in that associative array.
5441 
5442     See_Also:
5443         $(LREF ValueType)
5444   +/
5445 alias KeyType(V : V[K], K) = K;
5446 
5447 ///
5448 @safe unittest
5449 {
5450     static assert(is(KeyType!(int[string]) == string));
5451     static assert(is(KeyType!(string[int]) == int));
5452 
5453     static assert(is(KeyType!(string[const int]) == const int));
5454     static assert(is(KeyType!(const int[string]) == string));
5455 
5456     struct S
5457     {
5458         int i;
5459     }
5460 
5461     string[S] aa1;
5462     static assert(is(KeyType!(typeof(aa1)) == S));
5463 
5464     S[string] aa2;
5465     static assert(is(KeyType!(typeof(aa2)) == string));
5466 
5467     KeyType!(typeof(aa1)) key1 = S(42);
5468     KeyType!(typeof(aa2)) key2 = "foo";
5469 
5470     // Key types with indirections have their inner layers treated as const
5471     // by the compiler, because the values of keys can't change, or the hash
5472     // value could change, putting the associative array in an invalid state.
5473     static assert(is(KeyType!(bool[string[]]) == const(string)[]));
5474     static assert(is(KeyType!(bool[int*]) == const(int)*));
5475 
5476     // If the given type is not an AA, then KeyType won't compile.
5477     static assert(!__traits(compiles, KeyType!int));
5478     static assert(!__traits(compiles, KeyType!(int[])));
5479 }
5480 
5481 /++
5482     Takes a type which is an associative array and evaluates to the type of the
5483     values in that associative array.
5484 
5485     See_Also:
5486         $(LREF KeyType)
5487   +/
5488 alias ValueType(V : V[K], K) = V;
5489 
5490 ///
5491 @safe unittest
5492 {
5493     static assert(is(ValueType!(int[string]) == int));
5494     static assert(is(ValueType!(string[int]) == string));
5495 
5496     static assert(is(ValueType!(string[const int]) == string));
5497     static assert(is(ValueType!(const int[string]) == const int));
5498 
5499     struct S
5500     {
5501         int i;
5502     }
5503 
5504     string[S] aa1;
5505     static assert(is(ValueType!(typeof(aa1)) == string));
5506 
5507     S[string] aa2;
5508     static assert(is(ValueType!(typeof(aa2)) == S));
5509 
5510     ValueType!(typeof(aa1)) value1 = "foo";
5511     ValueType!(typeof(aa2)) value2 = S(42);
5512 
5513     // If the given type is not an AA, then ValueType won't compile.
5514     static assert(!__traits(compiles, ValueType!int));
5515     static assert(!__traits(compiles, ValueType!(int[])));
5516 }
5517 
5518 /++
5519     Evaluates to the original / ultimate base type of an enum type - or for
5520     non-enum types, it evaluates to the type that it's given.
5521 
5522     If the base type of the given enum type is not an enum, then the result of
5523     OriginalType is its direct base type. However, if the base type of the
5524     given enum is also an enum, then OriginalType gives the ultimate base type
5525     - that is, it keeps getting the base type for each succesive enum in the
5526     chain until it gets to a base type that isn't an enum, and that's the
5527     result. So, the result will never be an enum type.
5528 
5529     If the given type has any qualifiers, the result will have those same
5530     qualifiers.
5531   +/
5532 version (StdDdoc) template OriginalType(T)
5533 {
5534     import core.internal.traits : CoreOriginalType = OriginalType;
5535     alias OriginalType = CoreOriginalType!T;
5536 }
5537 else
5538 {
5539     import core.internal.traits : CoreOriginalType = OriginalType;
5540     alias OriginalType = CoreOriginalType;
5541 }
5542 
5543 ///
5544 @safe unittest
5545 {
5546     enum E { a, b, c }
5547     static assert(is(OriginalType!E == int));
5548 
5549     enum F : E { x = E.a }
5550     static assert(is(OriginalType!F == int));
5551 
5552     enum G : F { y = F.x }
5553     static assert(is(OriginalType!G == int));
5554     static assert(is(OriginalType!(const G) == const int));
5555     static assert(is(OriginalType!(immutable G) == immutable int));
5556     static assert(is(OriginalType!(shared G) == shared int));
5557 
5558     enum C : char { a = 'a', b = 'b' }
5559     static assert(is(OriginalType!C == char));
5560 
5561     enum D : string { d = "dlang" }
5562     static assert(is(OriginalType!D == string));
5563 
5564     static assert(is(OriginalType!int == int));
5565     static assert(is(OriginalType!(const long) == const long));
5566     static assert(is(OriginalType!string == string));
5567 
5568     // OriginalType gets the base type of enums and for all other types gives
5569     // the same type back. It does nothing special for other types - like
5570     // classes - where one could talk about the type having a base type.
5571     class Base {}
5572     class Derived : Base {}
5573     static assert(is(OriginalType!Base == Base));
5574     static assert(is(OriginalType!Derived == Derived));
5575 }
5576 
5577 /++
5578     Removes the outer layer of $(D const), $(D inout), or $(D immutable)
5579     from type $(D T).
5580 
5581     If none of those qualifiers have been applied to the outer layer of
5582     type $(D T), then the result is $(D T).
5583 
5584     For the built-in scalar types (that is $(D bool), the character types, and
5585     the numeric types), they only have one layer, so $(D const U) simply becomes
5586     $(D U).
5587 
5588     Where the layers come in is pointers and arrays. $(D const(U*)) becomes
5589     $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer
5590     goes from being fully $(D const) to being a mutable pointer to $(D const),
5591     and a dynamic array goes from being fully $(D const) to being a mutable
5592     dynamic array of $(D const) elements. And if there are multiple layers of
5593     pointers or arrays, it's just that outer layer which is affected - e.g.
5594     $(D const(U**)) would become $(D const(U*)*).
5595 
5596     For user-defined types, the effect is that $(D const U) becomes $(D U), and
5597     how that affects member variables depends on the type of the member
5598     variable. If a member variable is explicitly marked with any mutability
5599     qualifiers, then it will continue to have those qualifiers even after
5600     Unconst has stripped all mutability qualifiers from the containing type.
5601     However, if a mutability qualifier was on the member variable only because
5602     the containing type had that qualifier, then when Unconst removes the
5603     qualifier from the containing type, it is removed from the member variable
5604     as well.
5605 
5606     Also, Unconst has no effect on what a templated type is instantiated
5607     with, so if a templated type is instantiated with a template argument which
5608     has a mutability qualifier, the template instantiation will not change.
5609   +/
5610 version (StdDdoc) template Unconst(T)
5611 {
5612     import core.internal.traits : CoreUnconst = Unconst;
5613     alias Unconst = CoreUnconst!T;
5614 }
5615 else
5616 {
5617     import core.internal.traits : CoreUnconst = Unconst;
5618     alias Unconst = CoreUnconst;
5619 }
5620 
5621 ///
5622 @safe unittest
5623 {
5624     static assert(is(Unconst!(                   int) == int));
5625     static assert(is(Unconst!(             const int) == int));
5626     static assert(is(Unconst!(       inout       int) == int));
5627     static assert(is(Unconst!(       inout const int) == int));
5628     static assert(is(Unconst!(shared             int) == shared int));
5629     static assert(is(Unconst!(shared       const int) == shared int));
5630     static assert(is(Unconst!(shared inout       int) == shared int));
5631     static assert(is(Unconst!(shared inout const int) == shared int));
5632     static assert(is(Unconst!(         immutable int) == int));
5633 
5634     // Only the outer layer of immutable is removed.
5635     // immutable(int[]) -> immutable(int)[]
5636     alias ImmIntArr = immutable(int[]);
5637     static assert(is(Unconst!ImmIntArr == immutable(int)[]));
5638 
5639     // Only the outer layer of const is removed.
5640     // immutable(int*) -> immutable(int)*
5641     alias ConstIntPtr = const(int*);
5642     static assert(is(Unconst!ConstIntPtr == const(int)*));
5643 
5644     // const(int)* -> const(int)*
5645     alias PtrToConstInt = const(int)*;
5646     static assert(is(Unconst!PtrToConstInt == const(int)*));
5647 
5648     static struct S
5649     {
5650         int* ptr;
5651         const int* cPtr;
5652         shared int* sPtr;
5653     }
5654 
5655     const S s;
5656     static assert(is(typeof(s) == const S));
5657     static assert(is(typeof(typeof(s).ptr) == const int*));
5658     static assert(is(typeof(typeof(s).cPtr) == const int*));
5659     static assert(is(typeof(typeof(s).sPtr) == const shared int*));
5660 
5661     // For user-defined types, all mutability qualifiers that are applied to
5662     // member variables only because the containing type has them are removed,
5663     // but the ones that are directly on those member variables remain.
5664 
5665     // const S -> S
5666     static assert(is(Unconst!(typeof(s)) == S));
5667     static assert(is(typeof(Unconst!(typeof(s)).ptr) == int*));
5668     static assert(is(typeof(Unconst!(typeof(s)).cPtr) == const int*));
5669     static assert(is(typeof(Unconst!(typeof(s)).sPtr) == shared int*));
5670 
5671     static struct Foo(T)
5672     {
5673         T* ptr;
5674     }
5675 
5676     // The qualifier on the type is removed, but the qualifier on the template
5677     // argument is not.
5678     static assert(is(Unconst!(const(Foo!(const int))) == Foo!(const int)));
5679     static assert(is(Unconst!(Foo!(const int)) == Foo!(const int)));
5680     static assert(is(Unconst!(const(Foo!int)) == Foo!int));
5681 }
5682 
5683 /++
5684     Removes the outer layer of $(D shared) from type $(D T).
5685 
5686     If $(D shared) has not been applied to the outer layer of type $(D T), then
5687     the result is $(D T).
5688 
5689     Note that while $(D immutable) is implicitly $(D shared), it is unaffected
5690     by Unshared. Only explicit $(D shared) is removed.
5691 
5692     For the built-in scalar types (that is $(D bool), the character types, and
5693     the numeric types), they only have one layer, so $(D shared U) simply
5694     becomes $(D U).
5695 
5696     Where the layers come in is pointers and arrays. $(D shared(U*)) becomes
5697     $(D shared(U)*), and $(D shared(U[])), becomes $(D shared(U)[]). So, a
5698     pointer goes from being fully $(D shared) to being a mutable pointer to
5699     $(D shared), and a dynamic array goes from being fully $(D shared) to being
5700     a mutable dynamic array of $(D shared) elements. And if there are multiple
5701     layers of pointers or arrays, it's just that outer layer which is affected
5702     - e.g. $(D shared(U**)) would become $(D shared(U*)*).
5703 
5704     For user-defined types, the effect is that $(D shared U) becomes $(D U),
5705     and how that affects member variables depends on the type of the member
5706     variable. If a member variable is explicitly marked with $(D shared), then
5707     it will continue to be $(D shared) even after Unshared has stripped
5708     $(D shared) from the containing type. However, if $(D shared) was on the
5709     member variable only because the containing type was $(D shared), then when
5710     Unshared removes the qualifier from the containing type, it is removed from
5711     the member variable as well.
5712 
5713     Also, Unshared has no effect on what a templated type is instantiated
5714     with, so if a templated type is instantiated with a template argument which
5715     has a type qualifier, the template instantiation will not change.
5716   +/
5717 template Unshared(T)
5718 {
5719     static if (is(T == shared U, U))
5720         alias Unshared = U;
5721     else
5722         alias Unshared = T;
5723 }
5724 
5725 ///
5726 @safe unittest
5727 {
5728     static assert(is(Unshared!(                   int) == int));
5729     static assert(is(Unshared!(             const int) == const int));
5730     static assert(is(Unshared!(       inout       int) == inout int));
5731     static assert(is(Unshared!(       inout const int) == inout const int));
5732     static assert(is(Unshared!(shared             int) == int));
5733     static assert(is(Unshared!(shared       const int) == const int));
5734     static assert(is(Unshared!(shared inout       int) == inout int));
5735     static assert(is(Unshared!(shared inout const int) == inout const int));
5736     static assert(is(Unshared!(         immutable int) == immutable int));
5737 
5738     // Only the outer layer of shared is removed.
5739     // shared(int[]) -> shared(int)[]
5740     alias SharedIntArr = shared(int[]);
5741     static assert(is(Unshared!SharedIntArr == shared(int)[]));
5742 
5743     // Only the outer layer of shared is removed.
5744     // shared(int*) -> shared(int)*
5745     alias SharedIntPtr = shared(int*);
5746     static assert(is(Unshared!SharedIntPtr == shared(int)*));
5747 
5748     // shared(int)* -> shared(int)*
5749     alias PtrToSharedInt = shared(int)*;
5750     static assert(is(Unshared!PtrToSharedInt == shared(int)*));
5751 
5752     // immutable is unaffected
5753     alias ImmutableArr = immutable(int[]);
5754     static assert(is(Unshared!ImmutableArr == immutable(int[])));
5755 
5756     static struct S
5757     {
5758         int* ptr;
5759         const int* cPtr;
5760         shared int* sPtr;
5761     }
5762 
5763     shared S s;
5764     static assert(is(typeof(s) == shared S));
5765     static assert(is(typeof(typeof(s).ptr) == shared int*));
5766     static assert(is(typeof(typeof(s).cPtr) == const shared int*));
5767     static assert(is(typeof(typeof(s).sPtr) == shared int*));
5768 
5769     // For user-defined types, if shared is applied to a member variable only
5770     // because the containing type is shared, then shared is removed from that
5771     // member variable, but if the member variable is directly marked as shared,
5772     // then it continues to be shared.
5773 
5774     // shared S -> S
5775     static assert(is(Unshared!(typeof(s)) == S));
5776     static assert(is(typeof(Unshared!(typeof(s)).ptr) == int*));
5777     static assert(is(typeof(Unshared!(typeof(s)).cPtr) == const int*));
5778     static assert(is(typeof(Unshared!(typeof(s)).sPtr) == shared int*));
5779 
5780     static struct Foo(T)
5781     {
5782         T* ptr;
5783     }
5784 
5785     // The qualifier on the type is removed, but the qualifier on the template
5786     // argument is not.
5787     static assert(is(Unshared!(shared(Foo!(shared int))) == Foo!(shared int)));
5788     static assert(is(Unshared!(Foo!(shared int)) == Foo!(shared int)));
5789     static assert(is(Unshared!(shared(Foo!int)) == Foo!int));
5790 }
5791 
5792 /++
5793     Removes the outer layer of all type qualifiers from type $(D T) - this
5794     includes $(D shared).
5795 
5796     If no type qualifiers have been applied to the outer layer of type $(D T),
5797     then the result is $(D T).
5798 
5799     For the built-in scalar types (that is $(D bool), the character types, and
5800     the numeric types), they only have one layer, so $(D const U) simply becomes
5801     $(D U).
5802 
5803     Where the layers come in is pointers and arrays. $(D const(U*)) becomes
5804     $(D const(U)*), and $(D const(U[])), becomes $(D const(U)[]). So, a pointer
5805     goes from being fully $(D const) to being a mutable pointer to $(D const),
5806     and a dynamic array goes from being fully $(D const) to being a mutable
5807     dynamic array of $(D const) elements. And if there are multiple layers of
5808     pointers or arrays, it's just that outer layer which is affected - e.g.
5809     $(D shared(U**)) would become $(D shared(U*)*).
5810 
5811     For user-defined types, the effect is that $(D const U) becomes $(D U), and
5812     how that affects member variables depends on the type of the member
5813     variable. If a member variable is explicitly marked with any qualifiers,
5814     then it will continue to have those qualifiers even after Unqualified has
5815     stripped all qualifiers from the containing type. However, if a qualifier
5816     was on the member variable only because the containing type had that
5817     qualifier, then when Unqualified removes the qualifier from the containing
5818     type, it is removed from the member variable as well.
5819 
5820     Also, Unqualified has no effect on what a templated type is instantiated
5821     with, so if a templated type is instantiated with a template argument which
5822     has a type qualifier, the template instantiation will not change.
5823 
5824     Note that in most cases, $(LREF Unconst) or $(LREF Unshared) should be used
5825     rather than Unqualified, because in most cases, code is not designed to
5826     work with $(D shared) and thus doing type checks which remove $(D shared)
5827     will allow $(D shared) types to pass template constraints when they won't
5828     actually work with the code. And when code is designed to work with
5829     $(D shared), it's often the case that the type checks need to take
5830     $(D const) into account in order to avoid accidentally mutating $(D const)
5831     data and violating the type system.
5832 
5833     In particular, historically, a lot of D code has used
5834     $(REF Unqual, std, traits) (which is equivalent to phobos.sys.traits'
5835     Unqualified) when the programmer's intent was to remove $(D const), and
5836     $(D shared) wasn't actually considered at all. And in such cases, the code
5837     really should use $(LREF Unconst) instead.
5838 
5839     But of course, if a template constraint or $(D static if) really needs to
5840     strip off both the mutability qualifiers and $(D shared) for what it's
5841     testing for, then that's what Unqualified is for. It's just that it's best
5842     practice to use $(LREF Unconst) when it's not clear that $(D shared) should
5843     be removed as well.
5844 
5845     Also, note that $(D is(immutable T == immutable U))) is equivalent to
5846     $(D is(Unqualified!T == Unqualified!U)) (using $(D immutable) converts
5847     $(D const), $(D inout), and $(D shared) to $(D immutable), whereas using
5848     Unqualified strips off all type qualifiers, but the resulting comparison is
5849     the same as long as $(D immutable) is used on both sides or Unqualified is
5850     used on both sides)). So, in cases where code needs to compare two types to
5851     see whether they're the same while ignoring all qualifiers, it's generally
5852     better to use $(D immutable) on both types rather than using Unqualfied on
5853     both types, since that avoids needing to instantiate a template, and those
5854     instantiations can really add up when a project has a lot of templates
5855     with template constraints, $(D static if)s, and other forms of conditional
5856     compilation that need to compare types.
5857   +/
5858 template Unqualified(T)
5859 {
5860     import core.internal.traits : CoreUnqualified = Unqual;
5861     alias Unqualified = CoreUnqualified!(T);
5862 }
5863 
5864 ///
5865 @safe unittest
5866 {
5867     static assert(is(Unqualified!(                   int) == int));
5868     static assert(is(Unqualified!(             const int) == int));
5869     static assert(is(Unqualified!(       inout       int) == int));
5870     static assert(is(Unqualified!(       inout const int) == int));
5871     static assert(is(Unqualified!(shared             int) == int));
5872     static assert(is(Unqualified!(shared       const int) == int));
5873     static assert(is(Unqualified!(shared inout       int) == int));
5874     static assert(is(Unqualified!(shared inout const int) == int));
5875     static assert(is(Unqualified!(         immutable int) == int));
5876 
5877     // Only the outer layer of immutable is removed.
5878     // immutable(int[]) -> immutable(int)[]
5879     alias ImmIntArr = immutable(int[]);
5880     static assert(is(Unqualified!ImmIntArr == immutable(int)[]));
5881 
5882     // Only the outer layer of const is removed.
5883     // const(int*) -> const(int)*
5884     alias ConstIntPtr = const(int*);
5885     static assert(is(Unqualified!ConstIntPtr == const(int)*));
5886 
5887     // const(int)* -> const(int)*
5888     alias PtrToConstInt = const(int)*;
5889     static assert(is(Unqualified!PtrToConstInt == const(int)*));
5890 
5891     // Only the outer layer of shared is removed.
5892     // shared(int*) -> shared(int)*
5893     alias SharedIntPtr = shared(int*);
5894     static assert(is(Unqualified!SharedIntPtr == shared(int)*));
5895 
5896     // shared(int)* -> shared(int)*
5897     alias PtrToSharedInt = shared(int)*;
5898     static assert(is(Unqualified!PtrToSharedInt == shared(int)*));
5899 
5900     // Both const and shared are removed from the outer layer.
5901     // shared const int[] -> shared(const(int))[]
5902     alias SharedConstIntArr = shared const(int[]);
5903     static assert(is(Unqualified!SharedConstIntArr == shared(const(int))[]));
5904 
5905     static struct S
5906     {
5907         int* ptr;
5908         const int* cPtr;
5909         shared int* sPtr;
5910     }
5911 
5912     shared const S s;
5913     static assert(is(typeof(s) == shared const S));
5914     static assert(is(typeof(typeof(s).ptr) == shared const int*));
5915     static assert(is(typeof(typeof(s).cPtr) == shared const int*));
5916     static assert(is(typeof(typeof(s).sPtr) == shared const int*));
5917 
5918     // For user-defined types, all qualifiers that are applied to member
5919     // variables only because the containing type has them are removed, but the
5920     // ones that are directly on those member variables remain.
5921 
5922     // shared const S -> S
5923     static assert(is(Unqualified!(typeof(s)) == S));
5924     static assert(is(typeof(Unqualified!(typeof(s)).ptr) == int*));
5925     static assert(is(typeof(Unqualified!(typeof(s)).cPtr) == const int*));
5926     static assert(is(typeof(Unqualified!(typeof(s)).sPtr) == shared int*));
5927 
5928     static struct Foo(T)
5929     {
5930         T* ptr;
5931     }
5932 
5933     // The qualifiers on the type are removed, but the qualifiers on the
5934     // template argument are not.
5935     static assert(is(Unqualified!(const(Foo!(const int))) == Foo!(const int)));
5936     static assert(is(Unqualified!(Foo!(const int)) == Foo!(const int)));
5937     static assert(is(Unqualified!(const(Foo!int)) == Foo!int));
5938 }
5939 
5940 /++
5941     Applies $(D const) to the given type.
5942 
5943     This is primarily useful in conjunction with templates that take a template
5944     predicate (such as many of the templates in phobos.sys.meta), since while in
5945     most cases, you can simply do $(D const T) or $(D const(T)) to make $(D T)
5946     $(D const), with something like $(REF Map, phobos, sys, meta), you need to
5947     pass a template to be applied.
5948 
5949     See_Also:
5950         $(LREF ImmutableOf)
5951         $(LREF InoutOf)
5952         $(LREF SharedOf)
5953   +/
5954 alias ConstOf(T) = const T;
5955 
5956 ///
5957 @safe unittest
5958 {
5959     static assert(is(ConstOf!int == const int));
5960     static assert(is(ConstOf!(const int) == const int));
5961     static assert(is(ConstOf!(inout int) == inout const int));
5962     static assert(is(ConstOf!(shared int) == const shared int));
5963 
5964     // Note that const has no effect on immutable.
5965     static assert(is(ConstOf!(immutable int) == immutable int));
5966 
5967     import phobos.sys.meta : AliasSeq, Map;
5968 
5969     alias Types = AliasSeq!(int, long,
5970                             bool*, ubyte[],
5971                             string, immutable(string));
5972     alias WithConst = Map!(ConstOf, Types);
5973     static assert(is(WithConst ==
5974                      AliasSeq!(const int, const long,
5975                                const(bool*), const(ubyte[]),
5976                                const(string), immutable(string))));
5977 }
5978 
5979 /++
5980     Applies $(D immutable) to the given type.
5981 
5982     This is primarily useful in conjunction with templates that take a template
5983     predicate (such as many of the templates in phobos.sys.meta), since while in
5984     most cases, you can simply do $(D immutable T) or $(D immutable(T)) to make
5985     $(D T) $(D immutable), with something like $(REF Map, phobos, sys, meta),
5986     you need to pass a template to be applied.
5987 
5988     See_Also:
5989         $(LREF ConstOf)
5990         $(LREF InoutOf)
5991         $(LREF SharedOf)
5992   +/
5993 alias ImmutableOf(T) = immutable T;
5994 
5995 ///
5996 @safe unittest
5997 {
5998     static assert(is(ImmutableOf!int == immutable int));
5999 
6000     // Note that immutable overrides const and inout.
6001     static assert(is(ImmutableOf!(const int) == immutable int));
6002     static assert(is(ImmutableOf!(inout int) == immutable int));
6003 
6004     // Note that immutable overrides shared, since immutable is implicitly
6005     // shared.
6006     static assert(is(ImmutableOf!(shared int) == immutable int));
6007 
6008     static assert(is(ImmutableOf!(immutable int) == immutable int));
6009 
6010     import phobos.sys.meta : AliasSeq, Map;
6011 
6012     alias Types = AliasSeq!(int, long,
6013                             bool*, ubyte[],
6014                             string, immutable(string));
6015     alias WithImmutable = Map!(ImmutableOf, Types);
6016     static assert(is(WithImmutable ==
6017                      AliasSeq!(immutable int, immutable long,
6018                                immutable(bool*), immutable(ubyte[]),
6019                                immutable(string), immutable(string))));
6020 }
6021 
6022 /++
6023     Applies $(D inout) to the given type.
6024 
6025     This is primarily useful in conjunction with templates that take a template
6026     predicate (such as many of the templates in phobos.sys.meta), since while in
6027     most cases, you can simply do $(D inout T) or $(D inout(T)) to make $(D T)
6028     $(D inout), with something like $(REF Map, phobos, sys, meta), you need to
6029     pass a template to be applied.
6030 
6031     See_Also:
6032         $(LREF ConstOf)
6033         $(LREF ImmutableOf)
6034         $(LREF SharedOf)
6035   +/
6036 alias InoutOf(T) = inout T;
6037 
6038 ///
6039 @safe unittest
6040 {
6041     static assert(is(InoutOf!int == inout int));
6042     static assert(is(InoutOf!(const int) == inout const int));
6043     static assert(is(InoutOf!(inout int) == inout int));
6044     static assert(is(InoutOf!(shared int) == inout shared int));
6045 
6046     // Note that inout has no effect on immutable.
6047     static assert(is(InoutOf!(immutable int) == immutable int));
6048 
6049     import phobos.sys.meta : AliasSeq, Map;
6050 
6051     alias Types = AliasSeq!(int, long,
6052                             bool*, ubyte[],
6053                             string, immutable(string));
6054     alias WithInout = Map!(InoutOf, Types);
6055     static assert(is(WithInout ==
6056                      AliasSeq!(inout int, inout long,
6057                                inout(bool*), inout(ubyte[]),
6058                                inout(string), immutable(string))));
6059 }
6060 
6061 /++
6062     Applies $(D shared) to the given type.
6063 
6064     This is primarily useful in conjunction with templates that take a template
6065     predicate (such as many of the templates in phobos.sys.meta), since while in
6066     most cases, you can simply do $(D shared T) or $(D shared(T)) to make $(D T)
6067     $(D shared), with something like $(REF Map, phobos, sys, meta), you need to
6068     pass a template to be applied.
6069 
6070     See_Also:
6071         $(LREF ConstOf)
6072         $(LREF ImmutableOf)
6073         $(LREF InoutOf)
6074   +/
6075 alias SharedOf(T) = shared T;
6076 
6077 ///
6078 @safe unittest
6079 {
6080     static assert(is(SharedOf!int == shared int));
6081     static assert(is(SharedOf!(const int) == const shared int));
6082     static assert(is(SharedOf!(inout int) == inout shared int));
6083     static assert(is(SharedOf!(shared int) == shared int));
6084 
6085     // Note that shared has no effect on immutable, since immutable is
6086     // implicitly shared.
6087     static assert(is(SharedOf!(immutable int) == immutable int));
6088 
6089     import phobos.sys.meta : AliasSeq, Map;
6090 
6091     alias Types = AliasSeq!(int, long,
6092                             bool*, ubyte[],
6093                             string, immutable(string));
6094     alias WithShared = Map!(SharedOf, Types);
6095     static assert(is(WithShared ==
6096                      AliasSeq!(shared int, shared long,
6097                                shared(bool*), shared(ubyte[]),
6098                                shared(string), immutable(string))));
6099 }
6100 
6101 // Needed for rvalueOf/lvalueOf because
6102 // "inout on return means inout must be on a parameter as well"
6103 private struct __InoutWorkaroundStruct {}
6104 
6105 /++
6106     Creates an lvalue or rvalue of type T to be used in conjunction with
6107     $(D is(typeof(...))) or
6108     $(DDSUBLINK spec/traits, compiles, $(D __traits(compiles, ...))).
6109 
6110     The idea is that some traits or other forms of conditional compilation need
6111     to verify that a particular piece of code compiles with an rvalue or an
6112     lvalue of a specific type, and these $(D @property) functions allow you to
6113     get an rvalue or lvalue of a specific type to use within an expression that
6114     is then tested to see whether it compiles.
6115 
6116     They're $(D @property) functions so that using $(D typeof) on them gives
6117     the return type rather than the type of the function.
6118 
6119     Note that these functions are $(I not) defined, so if they're actually used
6120     outside of type introspection, they'll result in linker errors. They're
6121     entirely for testing that a particular piece of code compiles with an rvalue
6122     or lvalue of the given type.
6123 
6124     The $(D __InoutWorkaroundStruct) parameter is entirely to make it so that
6125     these work when the given type has the $(D inout) qualifier, since the
6126     language requires that a function that returns an $(D inout) type also have
6127     an $(D inout) type as a parameter. It should just be ignored.
6128   +/
6129 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
6130 
6131 /++ Ditto +/
6132 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
6133 
6134 ///
6135 @safe unittest
6136 {
6137     static int foo(int);
6138     static assert(is(typeof(foo(lvalueOf!int)) == int));
6139     static assert(is(typeof(foo(rvalueOf!int)) == int));
6140 
6141     static bool bar(ref int);
6142     static assert(is(typeof(bar(lvalueOf!int)) == bool));
6143     static assert(!is(typeof(bar(rvalueOf!int))));
6144 
6145     static assert( is(typeof({ lvalueOf!int = 42; })));
6146     static assert(!is(typeof({ rvalueOf!int = 42; })));
6147 
6148     static struct S {}
6149     static assert( is(typeof({ lvalueOf!S = S.init; })));
6150     static assert(!is(typeof({ rvalueOf!S = S.init; })));
6151 
6152     static struct NoAssign
6153     {
6154         @disable void opAssign(ref NoAssign);
6155     }
6156     static assert(!is(typeof({ lvalueOf!NoAssign = NoAssign.init; })));
6157     static assert(!is(typeof({ rvalueOf!NoAssign = NoAssign.init; })));
6158 }
6159 
6160 @system unittest
6161 {
6162     import phobos.sys.meta : AliasSeq;
6163 
6164     void needLvalue(T)(ref T);
6165     static struct S {}
6166     int i;
6167     struct Nested { void f() { ++i; } }
6168 
6169     static foreach (T; AliasSeq!(int, const int, immutable int, inout int, string, S, Nested, Object))
6170     {
6171         static assert(!__traits(compiles, needLvalue(rvalueOf!T)));
6172         static assert( __traits(compiles, needLvalue(lvalueOf!T)));
6173         static assert(is(typeof(rvalueOf!T) == T));
6174         static assert(is(typeof(lvalueOf!T) == T));
6175     }
6176 
6177     static assert(!__traits(compiles, rvalueOf!int = 1));
6178     static assert( __traits(compiles, lvalueOf!byte = 127));
6179     static assert(!__traits(compiles, lvalueOf!byte = 128));
6180 }
6181 
6182 // We may want to add this as some sort of public test helper in the future in
6183 // whatever module would be appropriate for that.
6184 private template assertWithQualifiers(alias Pred, T, bool expected)
6185 {
6186     static assert(Pred!T == expected);
6187     static assert(Pred!(const T) == expected);
6188     static assert(Pred!(inout T) == expected);
6189     static assert(Pred!(immutable T) == expected);
6190     static assert(Pred!(shared T) == expected);
6191 
6192     static if (is(T == U*, U))
6193     {
6194         static assert(Pred!(const(U)*) == expected);
6195         static assert(Pred!(inout(U)*) == expected);
6196         static assert(Pred!(immutable(U)*) == expected);
6197         static assert(Pred!(shared(U)*) == expected);
6198     }
6199     else static if (is(T == U[], U))
6200     {
6201         static assert(Pred!(const(U)[]) == expected);
6202         static assert(Pred!(inout(U)[]) == expected);
6203         static assert(Pred!(immutable(U)[]) == expected);
6204         static assert(Pred!(shared(U)[]) == expected);
6205     }
6206     else static if (is(T == U[n], U, size_t n))
6207     {
6208         static assert(Pred!(const(U)[n]) == expected);
6209         static assert(Pred!(inout(U)[n]) == expected);
6210         static assert(Pred!(immutable(U)[n]) == expected);
6211         static assert(Pred!(shared(U)[n]) == expected);
6212     }
6213 }
6214 
6215 private template assertWithQualifiers(alias Pred)
6216 {
6217     alias assertWithQualifiers(T, bool expected) = .assertWithQualifiers!(Pred, T, expected);
6218 }
6219 
6220 @safe unittest
6221 {
6222     mixin assertWithQualifiers!(isPointer, int*, true);
6223     mixin assertWithQualifiers!(isPointer, int, false);
6224 
6225     alias test = assertWithQualifiers!isPointer;
6226     mixin test!(int*, true);
6227     mixin test!(int, false);
6228 }