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