1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /**
6  * Type traits.
7  *
8  * Templates in this module are used to obtain type information at compile
9  * time.
10  *
11  * Copyright: Eugene Wissner 2017-2020.
12  * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
13  *                  Mozilla Public License, v. 2.0).
14  * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
15  * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/meta/tanya/meta/trait.d,
16  *                 tanya/meta/trait.d)
17  */
18 module tanya.meta.trait;
19 
20 import tanya.meta.metafunction;
21 import tanya.meta.transform;
22 
23 /**
24  * Determines whether $(D_PARAM T) is a wide string, i.e. consists of
25  * $(D_KEYWORD dchar).
26  *
27  * The character type of the string can be qualified with $(D_KEYWORD const),
28  * $(D_KEYWORD immutable) or $(D_KEYWORD inout), but an occurrence of
29  * $(D_KEYWORD shared) in the character type results in returning
30  * $(D_KEYWORD false).
31  * The string itself (in contrast to its character type) can have any type
32  * qualifiers.
33  *
34  * Static $(D_KEYWORD char) and $(D_KEYWORD wchar) arrays are not considered
35  * strings.
36  *
37  * Params:
38  *  T = A Type.
39  *
40  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a wide string,
41  *          $(D_KEYWORD false) otherwise.
42  *
43  * See_Also: $(D_PSYMBOL isNarrowString).
44  */
45 enum bool isWideString(T) = is(T : const dchar[]) && !isStaticArray!T;
46 
47 ///
48 @nogc nothrow pure @safe unittest
49 {
50     static assert(isWideString!(dchar[]));
51     static assert(!isWideString!(char[]));
52     static assert(!isWideString!(wchar[]));
53 
54     static assert(isWideString!dstring);
55     static assert(!isWideString!string);
56     static assert(!isWideString!wstring);
57 
58     static assert(isWideString!(const dstring));
59     static assert(!isWideString!(const string));
60     static assert(!isWideString!(const wstring));
61 
62     static assert(isWideString!(shared dstring));
63     static assert(!isWideString!(shared string));
64     static assert(!isWideString!(shared wstring));
65 
66     static assert(isWideString!(const(dchar)[]));
67     static assert(isWideString!(inout(dchar)[]));
68     static assert(!isWideString!(shared(const(dchar))[]));
69     static assert(!isWideString!(shared(dchar)[]));
70     static assert(!isWideString!(dchar[10]));
71 }
72 
73 /*
74  * Tests whether $(D_PARAM T) is an interface.
75  *
76  * Params:
77  *  T = A type.
78  *
79  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface,
80  *          $(D_KEYWORD false) otherwise.
81  */
82 private enum bool isInterface(T) = is(T == interface);
83 
84 /**
85  * Determines whether $(D_PARAM T) is a polymorphic type, i.e. a
86  * $(D_KEYWORD class) or an $(D_KEYWORD interface).
87  *
88  * Params:
89  *  T = A type.
90  *
91  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a $(D_KEYWORD class) or an
92  *          $(D_KEYWORD interface), $(D_KEYWORD false) otherwise.
93  */
94 enum bool isPolymorphicType(T) = is(T == class) || is(T == interface);
95 
96 ///
97 @nogc nothrow pure @safe unittest
98 {
99     interface I
100     {
101     }
102     static assert(isPolymorphicType!Object);
103     static assert(isPolymorphicType!I);
104     static assert(!isPolymorphicType!short);
105 }
106 
107 /**
108  * Determines whether the type $(D_PARAM T) has a static method
109  * named $(D_PARAM member).
110  *
111  * Params:
112  *  T      = Aggregate type.
113  *  member = Symbol name.
114  *
115  * Returns: $(D_KEYWORD true) if $(D_PARAM member) is a static method of
116  *          $(D_PARAM T), $(D_KEYWORD false) otherwise.
117  */
118 template hasStaticMember(T, string member)
119 {
120     static if (hasMember!(T, member))
121     {
122         alias Member = Alias!(__traits(getMember, T, member));
123 
124         static if (__traits(isStaticFunction, Member)
125                 || (!isFunction!Member && is(typeof(&Member))))
126         {
127             enum bool hasStaticMember = true;
128         }
129         else
130         {
131             enum bool hasStaticMember = false;
132         }
133     }
134     else
135     {
136         enum bool hasStaticMember = false;
137     }
138 }
139 
140 ///
141 @nogc nothrow pure @safe unittest
142 {
143     static struct S
144     {
145          int member1;
146          void member2()
147          {
148          }
149          static int member3;
150          static void member4()
151          {
152          }
153          static void function() member5;
154     }
155     static assert(!hasStaticMember!(S, "member1"));
156     static assert(!hasStaticMember!(S, "member2"));
157     static assert(hasStaticMember!(S, "member3"));
158     static assert(hasStaticMember!(S, "member4"));
159     static assert(hasStaticMember!(S, "member5"));
160 }
161 
162 /**
163  * Determines whether $(D_PARAM T) is a floating point type.
164  *
165  * Floating point types are:
166  * $(UL
167  *  $(LI float)
168  *  $(LI double)
169  *  $(LI real)
170  * )
171  *
172  * Params:
173  *  T = A type.
174  *
175  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a floating point type,
176  *          $(D_KEYWORD false) otherwise.
177  */
178 enum bool isFloatingPoint(T) = is(Unqual!(OriginalType!T) == double)
179                             || is(Unqual!(OriginalType!T) == float)
180                             || is(Unqual!(OriginalType!T) == real);
181 
182 ///
183 @nogc nothrow pure @safe unittest
184 {
185     static assert(isFloatingPoint!float);
186     static assert(isFloatingPoint!double);
187     static assert(isFloatingPoint!real);
188     static assert(isFloatingPoint!(const float));
189     static assert(isFloatingPoint!(shared float));
190     static assert(isFloatingPoint!(shared const float));
191     static assert(!isFloatingPoint!int);
192 }
193 
194 /**
195  * Determines whether $(D_PARAM T) is a signed numeric type.
196  *
197  * Signed numeric types are:
198  * $(UL
199  *  $(LI byte)
200  *  $(LI short)
201  *  $(LI int)
202  *  $(LI long)
203  *  $(LI float)
204  *  $(LI double)
205  *  $(LI real)
206  * )
207  *
208  * Params:
209  *  T = A type.
210  *
211  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a signed numeric type,
212  *          $(D_KEYWORD false) otherwise.
213  *
214  * See_Also: $(D_PSYMBOL isUnsigned).
215  */
216 enum bool isSigned(T) = is(Unqual!(OriginalType!T) == byte)
217                      || is(Unqual!(OriginalType!T) == short)
218                      || is(Unqual!(OriginalType!T) == int)
219                      || is(Unqual!(OriginalType!T) == long)
220                      || isFloatingPoint!T;
221 
222 ///
223 @nogc nothrow pure @safe unittest
224 {
225     static assert(isSigned!byte);
226     static assert(isSigned!short);
227     static assert(isSigned!int);
228     static assert(isSigned!long);
229     static assert(isSigned!float);
230     static assert(isSigned!double);
231     static assert(isSigned!real);
232 
233     static assert(!isSigned!ubyte);
234     static assert(!isSigned!ushort);
235     static assert(!isSigned!uint);
236     static assert(!isSigned!ulong);
237 }
238 
239 /**
240  * Determines whether $(D_PARAM T) is an unsigned numeric type.
241  *
242  * Unsigned numeric types are:
243  * $(UL
244  *  $(LI ubyte)
245  *  $(LI ushort)
246  *  $(LI uint)
247  *  $(LI ulong)
248  * )
249  *
250  * Params:
251  *  T = A type.
252  *
253  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an unsigned numeric type,
254  *          $(D_KEYWORD false) otherwise.
255  *
256  * See_Also: $(D_PSYMBOL isSigned).
257  */
258 enum bool isUnsigned(T) = is(Unqual!(OriginalType!T) == ubyte)
259                        || is(Unqual!(OriginalType!T) == ushort)
260                        || is(Unqual!(OriginalType!T) == uint)
261                        || is(Unqual!(OriginalType!T) == ulong);
262 
263 ///
264 @nogc nothrow pure @safe unittest
265 {
266     static assert(isUnsigned!ubyte);
267     static assert(isUnsigned!ushort);
268     static assert(isUnsigned!uint);
269     static assert(isUnsigned!ulong);
270 
271     static assert(!isUnsigned!byte);
272     static assert(!isUnsigned!short);
273     static assert(!isUnsigned!int);
274     static assert(!isUnsigned!long);
275     static assert(!isUnsigned!float);
276     static assert(!isUnsigned!double);
277     static assert(!isUnsigned!real);
278 }
279 
280 /**
281  * Determines whether $(D_PARAM T) is an integral type.
282  *
283  * Integral types are:
284  * $(UL
285  *  $(LI ubyte)
286  *  $(LI ushort)
287  *  $(LI uint)
288  *  $(LI ulong)
289  *  $(LI byte)
290  *  $(LI short)
291  *  $(LI int)
292  *  $(LI long)
293  * )
294  *
295  * Params:
296  *  T = A type.
297  *
298  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an integral type,
299  *          $(D_KEYWORD false) otherwise.
300  */
301 enum bool isIntegral(T) = isUnsigned!T
302                        || is(Unqual!(OriginalType!T) == byte)
303                        || is(Unqual!(OriginalType!T) == short)
304                        || is(Unqual!(OriginalType!T) == int)
305                        || is(Unqual!(OriginalType!T) == long);
306 
307 ///
308 @nogc nothrow pure @safe unittest
309 {
310     static assert(isIntegral!ubyte);
311     static assert(isIntegral!byte);
312     static assert(!isIntegral!float);
313 }
314 
315 /**
316  * Determines whether $(D_PARAM T) is a boolean type, i.e. $(D_KEYWORD bool).
317  *
318  * Params:
319  *  T = A type.
320  *
321  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a boolean type,
322  *          $(D_KEYWORD false) otherwise.
323  */
324 enum bool isBoolean(T) = is(Unqual!(OriginalType!T) == bool);
325 
326 ///
327 @nogc nothrow pure @safe unittest
328 {
329     static assert(isBoolean!bool);
330     static assert(isBoolean!(shared const bool));
331     static assert(!isBoolean!(ubyte));
332     static assert(!isBoolean!(byte));
333 
334     enum E : bool
335     {
336         t = true,
337         f = false,
338     }
339     static assert(isBoolean!E);
340 
341     static struct S1
342     {
343         bool b;
344         alias b this;
345     }
346     static assert(!isBoolean!S1);
347 
348     static struct S2
349     {
350         bool opCast(T : bool)()
351         {
352             return true;
353         }
354     }
355     static assert(!isBoolean!S2);
356 }
357 
358 /**
359  * Determines whether $(D_PARAM T) is a character type.
360  *
361  * Character types are:
362  *
363  * $(UL
364  *  $(LI char)
365  *  $(LI wchar)
366  *  $(LI dchar)
367  * )
368  *
369  * Params:
370  *  T = A type.
371  *
372  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a character type,
373  *          $(D_KEYWORD false) otherwise.
374  */
375 enum bool isSomeChar(T) = is(Unqual!(OriginalType!T) == char)
376                        || is(Unqual!(OriginalType!T) == wchar)
377                        || is(Unqual!(OriginalType!T) == dchar);
378 
379 ///
380 @nogc nothrow pure @safe unittest
381 {
382     static assert(isSomeChar!char);
383     static assert(isSomeChar!wchar);
384     static assert(isSomeChar!dchar);
385 
386     static assert(!isSomeChar!byte);
387     static assert(!isSomeChar!ubyte);
388     static assert(!isSomeChar!short);
389     static assert(!isSomeChar!ushort);
390     static assert(!isSomeChar!int);
391     static assert(!isSomeChar!uint);
392 }
393 
394 /**
395  * Determines whether $(D_PARAM T) is a pointer type.
396  *
397  * Params:
398  *  T = A type.
399  *
400  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a pointer type,
401  *          $(D_KEYWORD false) otherwise.
402  */
403 template isPointer(T)
404 {
405     static if (is(T U : U*))
406     {
407         enum bool isPointer = !is(Unqual!(OriginalType!T) == typeof(null));
408     }
409     else
410     {
411         enum bool isPointer = false;
412     }
413 }
414 
415 ///
416 @nogc nothrow pure @safe unittest
417 {
418     static assert(isPointer!(bool*));
419     static assert(isPointer!(const bool*));
420     static assert(isPointer!(const shared bool*));
421     static assert(!isPointer!bool);
422 }
423 
424 /**
425  * Determines whether $(D_PARAM T) is an array type (dynamic or static, but
426  * not an associative one).
427  *
428  * Params:
429  *  T = A type.
430  *
431  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an array type,
432  *          $(D_KEYWORD false) otherwise.
433  *
434  * See_Also: $(D_PSYMBOL isAssociativeArray).
435  */
436 template isArray(T)
437 {
438     static if (is(T U : U[]))
439     {
440         enum bool isArray = true;
441     }
442     else
443     {
444         enum bool isArray = false;
445     }
446 }
447 
448 ///
449 @nogc nothrow pure @safe unittest
450 {
451     static assert(isArray!(bool[]));
452     static assert(isArray!(const bool[]));
453     static assert(isArray!(shared bool[]));
454     static assert(isArray!(bool[8]));
455     static assert(!isArray!bool);
456     static assert(!isArray!(bool[string]));
457 }
458 
459 /**
460  * Determines whether $(D_PARAM T) is a static array type.
461  *
462  * Params:
463  *  T = A type.
464  *
465  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a static array type,
466  *          $(D_KEYWORD false) otherwise.
467  *
468  * See_Also: $(D_PSYMBOL isArray).
469  */
470 template isStaticArray(T)
471 {
472     static if (is(T U : U[L], size_t L))
473     {
474         enum bool isStaticArray = true;
475     }
476     else
477     {
478         enum bool isStaticArray = false;
479     }
480 }
481 
482 ///
483 @nogc nothrow pure @safe unittest
484 {
485     static assert(isStaticArray!(bool[8]));
486     static assert(isStaticArray!(const bool[8]));
487     static assert(isStaticArray!(shared bool[8]));
488     static assert(!isStaticArray!(bool[]));
489     static assert(!isStaticArray!bool);
490     static assert(!isStaticArray!(bool[string]));
491 }
492 
493 /**
494  * Determines whether $(D_PARAM T) is a dynamic array type.
495  *
496  * Params:
497  *  T = A type.
498  *
499  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a dynamic array type,
500  *          $(D_KEYWORD false) otherwise.
501  *
502  * See_Also: $(D_PSYMBOL isArray).
503  */
504 enum bool isDynamicArray(T) = isArray!T && !isStaticArray!T;
505 
506 ///
507 @nogc nothrow pure @safe unittest
508 {
509     static assert(isDynamicArray!(bool[]));
510     static assert(isDynamicArray!(const bool[]));
511     static assert(isDynamicArray!(shared bool[]));
512     static assert(!isDynamicArray!(bool[8]));
513     static assert(!isDynamicArray!bool);
514     static assert(!isDynamicArray!(bool[string]));
515 }
516 
517 /**
518  * Determines whether $(D_PARAM T) is an associative array type.
519  *
520  * Params:
521  *  T = A type.
522  *
523  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an associative array type,
524  *          $(D_KEYWORD false) otherwise.
525  *
526  * See_Also: $(D_PSYMBOL isArray).
527  */
528 template isAssociativeArray(T)
529 {
530     static if (is(T U : U[L], L))
531     {
532         enum bool isAssociativeArray = true;
533     }
534     else
535     {
536         enum bool isAssociativeArray = false;
537     }
538 }
539 
540 ///
541 @nogc nothrow pure @safe unittest
542 {
543     static assert(isAssociativeArray!(bool[string]));
544     static assert(isAssociativeArray!(const bool[string]));
545     static assert(isAssociativeArray!(shared const bool[string]));
546     static assert(!isAssociativeArray!(bool[]));
547     static assert(!isAssociativeArray!(bool[8]));
548     static assert(!isAssociativeArray!bool);
549 }
550 
551 /**
552  * Determines whether $(D_PARAM T) is an aggregate type.
553  *
554  * Aggregate types are:
555  *
556  * $(UL
557  *  $(LI $(D_KEYWORD struct)s)
558  *  $(LI $(D_KEYWORD class)es)
559  *  $(LI $(D_KEYWORD interface)s)
560  *  $(LI $(D_KEYWORD union)s)
561  * )
562  *
563  * Params:
564  *  T = A type.
565  *
566  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an aggregate type,
567  *          $(D_KEYWORD false) otherwise.
568  */
569 enum bool isAggregateType(T) = is(T == struct)
570                             || is(T == class)
571                             || is(T == interface)
572                             || is(T == union);
573 
574 ///
575 @nogc nothrow pure @safe unittest
576 {
577     static struct S;
578     class C;
579     interface I;
580     union U;
581     enum E;
582 
583     static assert(isAggregateType!S);
584     static assert(isAggregateType!C);
585     static assert(isAggregateType!I);
586     static assert(isAggregateType!U);
587     static assert(!isAggregateType!E);
588     static assert(!isAggregateType!void);
589 }
590 
591 /**
592  * Determines whether $(D_PARAM T) is a narrow string, i.e. consists of
593  * $(D_KEYWORD char) or $(D_KEYWORD wchar).
594  *
595  * The character type of the string can be qualified with $(D_KEYWORD const),
596  * $(D_KEYWORD immutable) or $(D_KEYWORD inout), but an occurrence of
597  * $(D_KEYWORD shared) in the character type results in returning
598  * $(D_KEYWORD false).
599  * The string itself (in contrast to its character type) can have any type
600  * qualifiers.
601  *
602  * Static $(D_KEYWORD char) and $(D_KEYWORD wchar) arrays are not considered
603  * strings.
604  *
605  * Params:
606  *  T = A Type.
607  *
608  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a narrow string,
609  *          $(D_KEYWORD false) otherwise.
610  *
611  * See_Also: $(D_PSYMBOL isWideString).
612  */
613 enum bool isNarrowString(T) = (is(T : const char[]) || is (T : const wchar[]))
614                            && !isStaticArray!T;
615 
616 ///
617 @nogc nothrow pure @safe unittest
618 {
619     static assert(isNarrowString!(char[]));
620     static assert(isNarrowString!(wchar[]));
621     static assert(!isNarrowString!(dchar[]));
622 
623     static assert(isNarrowString!string);
624     static assert(isNarrowString!wstring);
625     static assert(!isNarrowString!dstring);
626 
627     static assert(isNarrowString!(const string));
628     static assert(isNarrowString!(const wstring));
629     static assert(!isNarrowString!(const dstring));
630 
631     static assert(isNarrowString!(shared string));
632     static assert(isNarrowString!(shared wstring));
633     static assert(!isNarrowString!(shared dstring));
634 
635     static assert(isNarrowString!(const(char)[]));
636     static assert(isNarrowString!(inout(char)[]));
637     static assert(!isNarrowString!(shared(const(char))[]));
638     static assert(!isNarrowString!(shared(char)[]));
639     static assert(!isNarrowString!(char[10]));
640 }
641 
642 /**
643  * Determines whether $(D_PARAM T) is a string, i.e. consists of
644  * $(D_KEYWORD char), $(D_KEYWORD wchar) or $(D_KEYWORD dchar).
645  *
646  * The character type of the string can be qualified with $(D_KEYWORD const),
647  * $(D_KEYWORD immutable) or $(D_KEYWORD inout), but an occurrence of
648  * $(D_KEYWORD shared) in the character type results in returning
649  * $(D_KEYWORD false).
650  * The string itself (in contrast to its character type) can have any type
651  * qualifiers.
652  *
653  * Static character arrays are not considered strings.
654  *
655  * Params:
656  *  T = A Type.
657  *
658  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a string,
659  *          $(D_KEYWORD false) otherwise.
660  *
661  * See_Also: $(D_PSYMBOL isNarrowString), $(D_PSYMBOL isWideString).
662  */
663 enum bool isSomeString(T) = isNarrowString!T || isWideString!T;
664 
665 ///
666 @nogc nothrow pure @safe unittest
667 {
668     static assert(isSomeString!(dchar[]));
669     static assert(isSomeString!(char[]));
670     static assert(isSomeString!(wchar[]));
671 
672     static assert(isSomeString!dstring);
673     static assert(isSomeString!string);
674     static assert(isSomeString!wstring);
675 
676     static assert(isSomeString!(const dstring));
677     static assert(isSomeString!(const string));
678     static assert(isSomeString!(const wstring));
679 
680     static assert(isSomeString!(shared dstring));
681     static assert(isSomeString!(shared string));
682     static assert(isSomeString!(shared wstring));
683 
684     static assert(isSomeString!(const(char)[]));
685     static assert(isSomeString!(inout(char)[]));
686     static assert(!isSomeString!(shared(const(char))[]));
687     static assert(!isSomeString!(shared(char)[]));
688     static assert(!isSomeString!(char[10]));
689 }
690 
691 /**
692  * Determines whether the type $(D_PARAM T) is copyable.
693  *
694  * Only structs can be not copyable if their postblit constructor or the
695  * postblit constructor of one of its fields is disabled, i.e. annotated with
696  * $(D_KEYWORD @disable).
697  *
698  * Params:
699  *  T = A type.
700  *
701  * Returns: $(D_PARAM true) if $(D_PARAM T) can be copied,
702  *          $(D_PARAM false) otherwise.
703  */
704 enum bool isCopyable(T) = is(typeof({ T s1 = T.init; T s2 = s1; }));
705 
706 ///
707 @nogc nothrow pure @safe unittest
708 {
709     static struct S1
710     {
711     }
712     static struct S2
713     {
714         this(this)
715         {
716         }
717     }
718     static struct S3
719     {
720         @disable this(this);
721     }
722     static struct S4
723     {
724         S3 s;
725     }
726     class C
727     {
728     }
729 
730     static assert(isCopyable!S1);
731     static assert(isCopyable!S2);
732     static assert(!isCopyable!S3);
733     static assert(!isCopyable!S4);
734 
735     static assert(isCopyable!C);
736     static assert(isCopyable!bool);
737 }
738 
739 /**
740  * Determines whether $(D_PARAM T) is an abstract class.
741  *
742  * Abstract class is a class marked as such or a class that has any abstract
743  * methods or doesn't implement all methods of abstract base classes.
744  *
745  * Params:
746  *  T = A type.
747  *
748  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is an abstract class,
749  *          $(D_KEYWORD false) otherwise.
750  *
751  * See_Also: $(D_PSYMBOL isAbstractFunction).
752  */
753 enum bool isAbstractClass(T) = __traits(isAbstractClass, T);
754 
755 ///
756 @nogc nothrow pure @safe unittest
757 {
758     class A
759     {
760     }
761     abstract class B
762     {
763     }
764     class C
765     {
766         abstract void func();
767     }
768     class D : C
769     {
770     }
771     class E : C
772     {
773         override void func()
774         {
775         }
776     }
777     static assert(!isAbstractClass!A);
778     static assert(isAbstractClass!B);
779     static assert(isAbstractClass!C);
780     static assert(isAbstractClass!D);
781     static assert(!isAbstractClass!E);
782 }
783 
784 /**
785  * Checks whether $(D_PARAM T) is a type, same as `is(T)` does.
786  *
787  * Params:
788  *  T = A symbol.
789  *
790  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a type, $(D_KEYWORD false)
791  *          otherwise.
792  */
793 enum bool isType(alias T) = is(T);
794 
795 /// ditto
796 enum bool isType(T) = true;
797 
798 /**
799  * Determines whether $(D_PARAM Args) contains only types.
800  *
801  * Params:
802  *  Args = Alias sequence.
803  *
804  * Returns: $(D_KEYWORD true) if $(D_PARAM Args) consists only of types,
805  *          $(D_KEYWORD false) otherwise.
806  */
807 enum bool isTypeTuple(Args...) = allSatisfy!(isType, Args);
808 
809 ///
810 @nogc nothrow pure @safe unittest
811 {
812     static assert(isTypeTuple!(int, uint, Object));
813     static assert(isTypeTuple!());
814     static assert(!isTypeTuple!(int, 8, Object));
815     static assert(!isTypeTuple!(5, 8, 2));
816 
817     class C
818     {
819     }
820     enum E : bool
821     {
822         t,
823         f,
824     }
825     union U
826     {
827     }
828     static struct T()
829     {
830     }
831 
832     static assert(isTypeTuple!C);
833     static assert(isTypeTuple!E);
834     static assert(isTypeTuple!U);
835     static assert(isTypeTuple!void);
836     static assert(isTypeTuple!int);
837     static assert(!isTypeTuple!T);
838     static assert(isTypeTuple!(T!()));
839     static assert(!isTypeTuple!5);
840     static assert(!isTypeTuple!(tanya.meta.trait));
841 }
842 
843 /**
844  * Tells whether $(D_PARAM Args) contains only expressions.
845  *
846  * An expression is determined by applying $(D_KEYWORD typeof) to an argument:
847  *
848  * ---
849  * static if (is(typeof(Args[i])))
850  * {
851  *  // Args[i] is an expression.
852  * }
853  * else
854  * {
855  *  // Args[i] is not an expression.
856  * }
857  * ---
858  *
859  * Params:
860  *  Args = Alias sequence.
861  *
862  * Returns: $(D_KEYWORD true) if $(D_PARAM Args) consists only of expressions,
863  *          $(D_KEYWORD false) otherwise.
864  */
865 template isExpressions(Args...)
866 {
867     static if (Args.length == 0)
868     {
869         enum bool isExpressions = true;
870     }
871     else static if (is(typeof(Args[0]) U))
872     {
873         enum bool isExpressions = !is(U == void)
874                                && isExpressions!(Args[1 .. $]);
875     }
876     else
877     {
878         enum bool isExpressions = false;
879     }
880 }
881 
882 ///
883 @nogc nothrow pure @safe unittest
884 {
885     static assert(isExpressions!(5, 8, 2));
886     static assert(isExpressions!());
887     static assert(!isExpressions!(int, uint, Object));
888     static assert(!isExpressions!(int, 8, Object));
889 
890     template T(U)
891     {
892     }
893     static assert(!isExpressions!T);
894 }
895 
896 /**
897  * Determines whether $(D_PARAM T) is a final class.
898  *
899  * Params:
900  *  T = A type.
901  *
902  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is a final class,
903  *          $(D_KEYWORD false) otherwise.
904  *
905  * See_Also: $(D_PSYMBOL isFinalFunction).
906  */
907 enum bool isFinalClass(T) = __traits(isFinalClass, T);
908 
909 ///
910 @nogc nothrow pure @safe unittest
911 {
912     final class A
913     {
914     }
915     class B
916     {
917     }
918 
919     static assert(isFinalClass!A);
920     static assert(!isFinalClass!B);
921 }
922 
923 /**
924  * Determines whether $(D_PARAM T) is an abstract method.
925  *
926  * Params:
927  *  F = A symbol.
928  *
929  * Returns: $(D_KEYWORD true) if $(D_PARAM F) is an abstract method,
930  *          $(D_KEYWORD false) otherwise.
931  *
932  * See_Also: $(D_PSYMBOL isAbstractClass).
933  */
934 enum bool isAbstractFunction(alias F) = __traits(isAbstractFunction, F);
935 
936 ///
937 @nogc nothrow pure @safe unittest
938 {
939     class A
940     {
941         void func()
942         {
943         }
944     }
945     class B
946     {
947         abstract void func();
948     }
949     class C : B
950     {
951         override void func()
952         {
953         }
954     }
955     static assert(!isAbstractFunction!(A.func));
956     static assert(isAbstractFunction!(B.func));
957     static assert(!isAbstractFunction!(C.func));
958 }
959 
960 /**
961  * Determines whether $(D_PARAM T) is a final method.
962  *
963  * Params:
964  *  F = A symbol.
965  *
966  * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a final method,
967  *          $(D_KEYWORD false) otherwise.
968  *
969  * See_Also: $(D_PSYMBOL isFinalClass).
970  */
971 enum bool isFinalFunction(alias F) = __traits(isFinalFunction, F);
972 
973 ///
974 @nogc nothrow pure @safe unittest
975 {
976     class A
977     {
978         void virtualFunc()
979         {
980         }
981         final void finalFunc()
982         {
983         }
984     }
985 
986     static assert(isFinalFunction!(A.finalFunc));
987     static assert(!isFinalFunction!(A.virtualFunc));
988 }
989 
990 /**
991  * Function pointer is a pointer to a function. So a simple function is not
992  * a function pointer, but getting the address of such function returns a
993  * function pointer.
994  *
995  * A function pointer doesn't save the context pointer, thus cannot have access
996  * to its outer scope.
997  *
998  * Params:
999  *  F = A symbol.
1000  *
1001  * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a function pointer,
1002  *          $(D_KEYWORD false) otherwise.
1003  *
1004  * See_Also: $(LINK2 http://dlang.org/spec/function.html#closures,
1005  *                   Delegates, Function Pointers, and Closures).
1006  */
1007 template isFunctionPointer(F...)
1008 if (F.length == 1)
1009 {
1010     static if ((is(typeof(F[0]) T : T*) && is(T == function))
1011             || (is(F[0] T : T*) && is(T == function)))
1012     {
1013         enum bool isFunctionPointer = true;
1014     }
1015     else
1016     {
1017         enum bool isFunctionPointer = false;
1018     }
1019 }
1020 
1021 ///
1022 @nogc nothrow pure @safe unittest
1023 {
1024     static assert(isFunctionPointer!(void function()));
1025     static assert(!isFunctionPointer!(void delegate()));
1026 
1027     static assert(isFunctionPointer!(() {}));
1028 
1029     void func()
1030     {
1031     }
1032     static void staticFunc()
1033     {
1034     }
1035     interface I
1036     {
1037         @property int prop();
1038     }
1039 
1040     static assert(!isFunctionPointer!func);
1041     static assert(!isFunctionPointer!staticFunc);
1042 
1043     auto functionPointer = &staticFunc;
1044     auto dg = &func;
1045 
1046     static assert(isFunctionPointer!functionPointer);
1047     static assert(!isFunctionPointer!dg);
1048 
1049     static assert(!isFunctionPointer!(I.prop));
1050 }
1051 
1052 /**
1053  * Delegate stores the function pointer and function context.
1054  *
1055  * Params:
1056  *  F = A symbol.
1057  *
1058  * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a delegate,
1059  *          $(D_KEYWORD false) delegate.
1060  *
1061  * See_Also: $(LINK2 http://dlang.org/spec/function.html#closures,
1062  *                   Delegates, Function Pointers, and Closures).
1063  */
1064 template isDelegate(F...)
1065 if (F.length == 1)
1066 {
1067     static if (is(F[0] == delegate)
1068             || is(typeof(F[0]) == delegate))
1069     {
1070         enum bool isDelegate = true;
1071     }
1072     else
1073     {
1074         enum bool isDelegate = false;
1075     }
1076 }
1077 
1078 ///
1079 @nogc nothrow pure @safe unittest
1080 {
1081     static assert(isDelegate!(void delegate()));
1082     static assert(!isDelegate!(void function()));
1083 
1084     static assert(!isDelegate!(() {}));
1085 
1086     void func()
1087     {
1088     }
1089     static void staticFunc()
1090     {
1091     }
1092     interface I
1093     {
1094         @property int prop();
1095     }
1096 
1097     static assert(!isDelegate!func);
1098     static assert(!isDelegate!staticFunc);
1099 
1100     auto functionPointer = &staticFunc;
1101     auto dg = &func;
1102 
1103     static assert(!isDelegate!functionPointer);
1104     static assert(isDelegate!dg);
1105 
1106     static assert(!isDelegate!(I.prop));
1107 }
1108 
1109 /**
1110  * $(D_PSYMBOL isFunction) returns $(D_KEYWORD true) only for plain functions,
1111  * not function pointers or delegates. Use $(D_PSYMBOL isFunctionPointer) or
1112  * $(D_PSYMBOL isDelegate) to detect them or $(D_PSYMBOL isSomeFunction)
1113  * for detecting a function of any type.
1114  *
1115  * Params:
1116  *  F = A symbol.
1117  *
1118  * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a function,
1119  *          $(D_KEYWORD false) otherwise.
1120  *
1121  * See_Also: $(LINK2 http://dlang.org/spec/function.html#closures,
1122  *                   Delegates, Function Pointers, and Closures).
1123  */
1124 template isFunction(F...)
1125 if (F.length == 1)
1126 {
1127     static if (is(F[0] == function)
1128             || is(typeof(&F[0]) T == delegate)
1129             || (is(typeof(&F[0]) T : T*) && is(T == function)))
1130     {
1131         enum bool isFunction = true;
1132     }
1133     else
1134     {
1135         enum bool isFunction = false;
1136     }
1137 }
1138 
1139 ///
1140 @nogc nothrow pure @safe unittest
1141 {
1142     static assert(!isFunction!(void function()));
1143     static assert(!isFunction!(() {}));
1144     static assert(!isFunction!(void delegate()));
1145 
1146     void func()
1147     {
1148     }
1149     static void staticFunc()
1150     {
1151     }
1152     interface I
1153     {
1154         @property int prop();
1155     }
1156 
1157     static assert(isFunction!func);
1158     static assert(isFunction!staticFunc);
1159 
1160     auto functionPointer = &staticFunc;
1161     auto dg = &func;
1162 
1163     static assert(!isFunction!functionPointer);
1164     static assert(!isFunction!dg);
1165 
1166     static assert(isFunction!(I.prop));
1167 }
1168 
1169 /**
1170  * Params:
1171  *  F = A symbol.
1172  *
1173  * Returns: $(D_KEYWORD true) if $(D_PARAM F) is a function, function pointer
1174  *           or delegate, $(D_KEYWORD false) otherwise.
1175  *
1176  * See_Also: $(D_PSYMBOL isFunction),
1177  *           $(D_PSYMBOL isDelegate),
1178  *           $(D_PSYMBOL isFunctionPointer).
1179  */
1180 template isSomeFunction(F...)
1181 if (F.length == 1)
1182 {
1183     enum bool isSomeFunction = isFunctionPointer!F
1184                             || isFunction!F
1185                             || isDelegate!F;
1186 }
1187 
1188 ///
1189 @nogc nothrow pure @safe unittest
1190 {
1191     static assert(isSomeFunction!(void function()));
1192     static assert(isSomeFunction!(() {}));
1193     static assert(isSomeFunction!(void delegate()));
1194 
1195     void func()
1196     {
1197     }
1198     static void staticFunc()
1199     {
1200     }
1201 
1202     static assert(isSomeFunction!func);
1203     static assert(isSomeFunction!staticFunc);
1204 
1205     auto functionPointer = &staticFunc;
1206     auto dg = &func;
1207 
1208     static assert(isSomeFunction!functionPointer);
1209     static assert(isSomeFunction!dg);
1210 
1211     static assert(!isSomeFunction!int);
1212 }
1213 
1214 /**
1215  * Params:
1216  *  F = A symbol.
1217  *
1218  * Returns: $(D_KEYWORD true) if $(D_PARAM F) is callable,
1219  *          $(D_KEYWORD false) otherwise.
1220  */
1221 template isCallable(F...)
1222 if (F.length == 1)
1223 {
1224     static if (isSomeFunction!F
1225             || (is(typeof(F[0].opCall)) && isFunction!(F[0].opCall)))
1226     {
1227         enum bool isCallable = true;
1228     }
1229     else
1230     {
1231         enum bool isCallable = false;
1232     }
1233 }
1234 
1235 ///
1236 @nogc nothrow pure @safe unittest
1237 {
1238     static struct S
1239     {
1240         void opCall()
1241         {
1242         }
1243     }
1244     class C
1245     {
1246         static void opCall()
1247         {
1248         }
1249     }
1250     interface I
1251     {
1252     }
1253     S s;
1254 
1255     static assert(isCallable!s);
1256     static assert(isCallable!C);
1257     static assert(isCallable!S);
1258     static assert(!isCallable!I);
1259 }
1260 
1261 /**
1262  * Determines whether $(D_PARAM T) defines a symbol $(D_PARAM member).
1263  *
1264  * Params:
1265  *  T      = Aggregate type.
1266  *  member = Symbol name.
1267  *
1268  * Returns: $(D_KEYWORD true) if $(D_PARAM T) defines a symbol
1269  *          $(D_PARAM member), $(D_KEYWORD false) otherwise.
1270  */
1271 enum bool hasMember(T, string member) = __traits(hasMember, T, member);
1272 
1273 ///
1274 @nogc nothrow pure @safe unittest
1275 {
1276     static struct S
1277     {
1278          int member1;
1279          void member2()
1280          {
1281          }
1282          static int member3;
1283          static void member4()
1284          {
1285          }
1286     }
1287     static assert(hasMember!(S, "member1"));
1288     static assert(hasMember!(S, "member2"));
1289     static assert(hasMember!(S, "member3"));
1290     static assert(hasMember!(S, "member4"));
1291     static assert(!hasMember!(S, "member6"));
1292 }
1293 
1294 /**
1295  * Determines whether $(D_PARAM T) is mutable, i.e. has one of the following
1296  * qualifiers or a combination of them:
1297  *
1298  * $(UL
1299  *  $(LI $(D_KEYWORD const))
1300  *  $(LI $(D_KEYWORD immutable))
1301  *  $(LI $(D_KEYWORD const))
1302  * )
1303  *
1304  * Params:
1305  *  T = A type.
1306  *
1307  * Returns: $(D_KEYWORD true) if $(D_PARAM T) is mutable,
1308  *          $(D_KEYWORD false) otherwise.
1309  */
1310 template isMutable(T)
1311 {
1312     static if (is(T U == const U)
1313             || is(T U == inout U)
1314             || is(T U == inout const U)
1315             || is(T U == immutable U)
1316             || is(T U == shared const U)
1317             || is(T U == shared inout U)
1318             || is(T U == shared inout const U))
1319     {
1320         enum bool isMutable = false;
1321     }
1322     else
1323     {
1324         enum bool isMutable = true;
1325     }
1326 }
1327 
1328 ///
1329 @nogc nothrow pure @safe unittest
1330 {
1331     static struct S
1332     {
1333         void method()
1334         {
1335             static assert(isMutable!(typeof(this)));
1336         }
1337 
1338         void method() inout
1339         {
1340             static assert(!isMutable!(typeof(this)));
1341         }
1342 
1343         void immMethod() const
1344         {
1345             static assert(!isMutable!(typeof(this)));
1346         }
1347         void immMethod() immutable
1348         {
1349             static assert(!isMutable!(typeof(this)));
1350         }
1351     }
1352 }
1353 
1354 /**
1355  * Determines whether $(D_PARAM T) is a nested type, i.e. $(D_KEYWORD class),
1356  * $(D_KEYWORD struct) or $(D_KEYWORD union), which internally stores a context
1357  * pointer.
1358  *
1359  * Params:
1360  *  T = $(D_KEYWORD class), $(D_KEYWORD struct) or $(D_KEYWORD union) type.
1361  *
1362  * Returns: $(D_KEYWORD true) if the argument is a nested type which internally
1363  *          stores a context pointer, $(D_KEYWORD false) otherwise.
1364  */
1365 template isNested(T)
1366 if (is(T == class) || is(T == struct) || is(T == union))
1367 {
1368     enum bool isNested = __traits(isNested, T);
1369 }
1370 
1371 ///
1372 @nogc pure nothrow @safe unittest
1373 {
1374     static struct S
1375     {
1376     }
1377     static assert(!isNested!S);
1378 
1379     class C
1380     {
1381         void method()
1382         {
1383         }
1384     }
1385     static assert(isNested!C);
1386 }
1387 
1388 /**
1389  * Determines whether $(D_PARAM T) is a nested function.
1390  *
1391  * Params:
1392  *  F = A function.
1393  *
1394  * Returns $(D_KEYWORD true) if the $(D_PARAM T) is a nested function,
1395  *         $(D_KEYWORD false) otherwise.
1396  */
1397 enum bool isNestedFunction(alias F) = __traits(isNested, F);
1398 
1399 ///
1400 @nogc nothrow pure @safe unittest
1401 {
1402     void func()
1403     {
1404         void nestedFunc()
1405         {
1406         }
1407         static assert(isNestedFunction!nestedFunc);
1408     }
1409 }
1410 
1411 /**
1412  * Determines the type of the callable $(D_PARAM F).
1413  *
1414  * Params:
1415  *  F = A function.
1416  *
1417  * Returns: Type of the function $(D_PARAM F).
1418  */
1419 template FunctionTypeOf(F...)
1420 if (isCallable!F)
1421 {
1422     static if ((is(typeof(F[0]) T : T*) && is(T == function))
1423             || (is(F[0] T : T*) && is(T == function))
1424             || is(F[0] T == delegate)
1425             || is(typeof(F[0]) T == delegate)
1426             || is(F[0] T == function)
1427             || is(typeof(&F[0]) T == delegate)
1428             || (is(typeof(&F[0]) T : T*) && is(T == function)))
1429     {
1430         alias FunctionTypeOf = T;
1431     }
1432     else
1433     {
1434         alias FunctionTypeOf = FunctionTypeOf!(F[0].opCall);
1435     }
1436 }
1437 
1438 ///
1439 @nogc nothrow pure @safe unittest
1440 {
1441     static assert(is(FunctionTypeOf!(void function()) == function));
1442     static assert(is(FunctionTypeOf!(() {}) == function));
1443 }
1444 
1445 /**
1446  * Determines the return type of the callable $(D_PARAM F).
1447  *
1448  * Params:
1449  *  F = A callable object.
1450  *
1451  * Returns: Return type of $(D_PARAM F).
1452  */
1453 template ReturnType(F...)
1454 if (isCallable!F)
1455 {
1456     static if (is(FunctionTypeOf!(F[0]) T == return))
1457     {
1458         alias ReturnType = T;
1459     }
1460     else
1461     {
1462         static assert(false, "Argument is not a callable");
1463     }
1464 }
1465 
1466 ///
1467 @nogc nothrow pure @safe unittest
1468 {
1469     static assert(is(ReturnType!(int delegate()) == int));
1470     static assert(is(ReturnType!(bool function()) == bool));
1471 }
1472 
1473 /**
1474  * Determines the template $(D_PARAM T) is an instance of.
1475  *
1476  * Params:
1477  *  T = Template instance.
1478  *
1479  * Returns: Template $(D_PARAM T) is an instance of.
1480  */
1481 alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
1482 
1483 ///
1484 @nogc nothrow pure @safe unittest
1485 {
1486     static struct S(T)
1487     {
1488     }
1489     static assert(__traits(isSame, TemplateOf!(S!int), S));
1490 
1491     static void func(T)()
1492     {
1493     }
1494     static assert(__traits(isSame, TemplateOf!(func!int), func));
1495 
1496     template T(U)
1497     {
1498     }
1499     static assert(__traits(isSame, TemplateOf!(T!int), T));
1500 }
1501 
1502 /**
1503  * Returns the mangled name of the symbol $(D_PARAM T).
1504  *
1505  * Params:
1506  *  T = A symbol.
1507  *
1508  * Returns: Mangled name of $(D_PARAM T).
1509  */
1510 enum string mangledName(T) = T.mangleof;
1511 
1512 ///
1513 enum string mangledName(alias T) = T.mangleof;
1514 
1515 /**
1516  * Tests whether $(D_PARAM I) is an instance of template $(D_PARAM T).
1517  *
1518  * Params:
1519  *  T = Template.
1520  *  I = Template instance.
1521  *
1522  * Returns: $(D_KEYWORD true) if $(D_PARAM I) is an instance of $(D_PARAM T),
1523  *          $(D_KEYWORD false) otherwise.
1524  */
1525 enum bool isInstanceOf(alias T, I) = is(I == T!Args, Args...);
1526 
1527 template isInstanceOf(alias T, alias I)
1528 {
1529     static if (is(typeof(TemplateOf!I)))
1530     {
1531         enum bool isInstanceOf = __traits(isSame, TemplateOf!I, T);
1532     }
1533     else
1534     {
1535         enum bool isInstanceOf = false;
1536     }
1537 }
1538 
1539 ///
1540 @nogc nothrow pure @safe unittest
1541 {
1542     static struct S(T)
1543     {
1544     }
1545     static assert(isInstanceOf!(S, S!int));
1546 
1547     static void func(T)();
1548     static assert(isInstanceOf!(func, func!int));
1549 
1550     template T(U)
1551     {
1552     }
1553     static assert(isInstanceOf!(T, T!int));
1554 }
1555 
1556 /**
1557  * Checks whether $(D_PARAM From) is implicitly (without explicit
1558  * $(D_KEYWORD cast)) to $(D_PARAM To).
1559  *
1560  * Params:
1561  *  From = Source type.
1562  *  To   = Conversion target type.
1563  *
1564  * Returns: $(D_KEYWORD true) if $(D_PARAM From) is implicitly convertible to
1565  *          $(D_PARAM To), $(D_KEYWORD false) if not.
1566  */
1567 enum bool isImplicitlyConvertible(From, To) = is(From : To);
1568 
1569 ///
1570 @nogc nothrow pure @safe unittest
1571 {
1572     static assert(isImplicitlyConvertible!(const(byte), byte));
1573     static assert(isImplicitlyConvertible!(byte, char));
1574     static assert(isImplicitlyConvertible!(byte, short));
1575     static assert(!isImplicitlyConvertible!(short, byte));
1576     static assert(isImplicitlyConvertible!(string, const(char)[]));
1577 }
1578 
1579 /**
1580  * Returns a tuple of base classes and interfaces of $(D_PARAM T).
1581  *
1582  * $(D_PSYMBOL BaseTypeTuple) returns only classes and interfaces $(D_PARAM T)
1583  * directly inherits from, but not the base classes and interfaces of its parents.
1584  *
1585  * Params:
1586  *  T = Class or interface type.
1587  *
1588  * Returns: A tuple of base classes or interfaces of ($D_PARAM T).
1589  *
1590  * See_Also: $(D_PSYMBOL TransitiveBaseTypeTuple).
1591  */
1592 template BaseTypeTuple(T)
1593 if (is(T == class) || (is(T == interface)))
1594 {
1595     static if (is(T Tuple == super))
1596     {
1597         alias BaseTypeTuple = Tuple;
1598     }
1599     else
1600     {
1601         static assert(false, "Argument isn't a class or interface");
1602     }
1603 }
1604 
1605 ///
1606 @nogc nothrow pure @safe unittest
1607 {
1608     interface I1
1609     {
1610     }
1611     interface I2
1612     {
1613     }
1614     interface I3 : I1, I2
1615     {
1616     }
1617     interface I4
1618     {
1619     }
1620     class A : I3, I4
1621     {
1622     }
1623     static assert(is(BaseTypeTuple!A == AliasSeq!(Object, I3, I4)));
1624     static assert(BaseTypeTuple!Object.length == 0);
1625 }
1626 
1627 /**
1628  * Returns a tuple of all base classes and interfaces of $(D_PARAM T).
1629  *
1630  * $(D_PSYMBOL TransitiveBaseTypeTuple) returns first the parent class, then
1631  * grandparent and so on. The last class is $(D_PSYMBOL Object). Then the interfaces
1632  * follow.
1633  *
1634  * Params:
1635  *  T = Class or interface type.
1636  *
1637  * Returns: A tuple of all base classes and interfaces of ($D_PARAM T).
1638  *
1639  * See_Also: $(D_PSYMBOL BaseTypeTuple).
1640  */
1641 template TransitiveBaseTypeTuple(T)
1642 if (is(T == class) || is(T == interface))
1643 {
1644     private template Impl(T...)
1645     {
1646         static if (T.length == 0)
1647         {
1648             alias Impl = AliasSeq!();
1649         }
1650         else
1651         {
1652             alias Impl = AliasSeq!(BaseTypeTuple!(T[0]),
1653                                    Map!(ImplCopy, BaseTypeTuple!(T[0])));
1654         }
1655     }
1656     private alias ImplCopy = Impl; // To avoid recursive template expansion.
1657     private enum bool cmp(A, B) = is(B == interface) && is(A == class);
1658 
1659     alias TransitiveBaseTypeTuple = NoDuplicates!(Sort!(cmp, Impl!T));
1660 }
1661 
1662 ///
1663 @nogc nothrow pure @safe unittest
1664 {
1665     interface I1
1666     {
1667     }
1668     interface I2 : I1
1669     {
1670     }
1671     class A : I2
1672     {
1673     }
1674     class B : A, I1
1675     {
1676     }
1677     class C : B, I2
1678     {
1679     }
1680     alias Expected = AliasSeq!(B, A, Object, I2, I1);
1681     static assert(is(TransitiveBaseTypeTuple!C == Expected));
1682 
1683     static assert(is(TransitiveBaseTypeTuple!Object == AliasSeq!()));
1684     static assert(is(TransitiveBaseTypeTuple!I2 == AliasSeq!(I1)));
1685 }
1686 
1687 /**
1688  * Returns all the base classes of $(D_PARAM T), the direct parent class comes
1689  * first, $(D_PSYMBOL Object) ist the last one.
1690  *
1691  * The only type that doesn't have any base class is $(D_PSYMBOL Object).
1692  *
1693  * Params:
1694  *  T = Class type.
1695  *
1696  * Returns: Base classes of $(D_PARAM T).
1697  */
1698 template BaseClassesTuple(T)
1699 if (is(T == class))
1700 {
1701     static if (is(T == Object))
1702     {
1703         alias BaseClassesTuple = AliasSeq!();
1704     }
1705     else
1706     {
1707         private alias Parents = BaseTypeTuple!T;
1708         alias BaseClassesTuple = AliasSeq!(Parents[0], BaseClassesTuple!(Parents[0]));
1709     }
1710 }
1711 
1712 ///
1713 @nogc nothrow pure @safe unittest
1714 {
1715     interface I1
1716     {
1717     }
1718     interface I2
1719     {
1720     }
1721     class A : I1, I2
1722     {
1723     }
1724     class B : A, I1
1725     {
1726     }
1727     class C : B, I2
1728     {
1729     }
1730     static assert(is(BaseClassesTuple!C == AliasSeq!(B, A, Object)));
1731     static assert(BaseClassesTuple!Object.length == 0);
1732 }
1733 
1734 /**
1735  * Returns all the interfaces $(D_PARAM T) inherits from.
1736  *
1737  * Params:
1738  *  T = Class or interface type.
1739  *
1740  * Returns: Interfaces $(D_PARAM T) inherits from.
1741  */
1742 template InterfacesTuple(T)
1743 if (is(T == class) || is(T == interface))
1744 {
1745     alias InterfacesTuple = Filter!(isInterface, TransitiveBaseTypeTuple!T);
1746 }
1747 
1748 ///
1749 @nogc nothrow pure @safe unittest
1750 {
1751     interface I1
1752     {
1753     }
1754     interface I2 : I1
1755     {
1756     }
1757     class A : I2
1758     {
1759     }
1760     class B : A, I1
1761     {
1762     }
1763     class C : B, I2
1764     {
1765     }
1766     static assert(is(InterfacesTuple!C == AliasSeq!(I2, I1)));
1767 
1768     static assert(is(InterfacesTuple!Object == AliasSeq!()));
1769     static assert(is(InterfacesTuple!I1 == AliasSeq!()));
1770 }
1771 
1772 /**
1773  * Tests whether a value of type $(D_PARAM Rhs) can be assigned to a variable
1774  * of type $(D_PARAM Lhs).
1775  *
1776  * If $(D_PARAM Rhs) isn't specified, $(D_PSYMBOL isAssignable) tests whether a
1777  * value of type $(D_PARAM Lhs) can be assigned to a variable of the same type.
1778  *
1779  * $(D_PSYMBOL isAssignable) tells whether $(D_PARAM Rhs) can be assigned by
1780  * value as well by reference.
1781  *
1782  * Params:
1783  *  Lhs = Variable type.
1784  *  Rhs = Expression type.
1785  *
1786  * Returns: $(D_KEYWORD true) if a value of type $(D_PARAM Rhs) can be assigned
1787  *          to a variable of type $(D_PARAM Lhs), $(D_KEYWORD false) otherwise.
1788  */
1789 template isAssignable(Lhs, Rhs = Lhs)
1790 {
1791     enum bool isAssignable = is(typeof({
1792         Lhs lhs = Lhs.init;
1793         Rhs rhs = Rhs.init;
1794         lhs = ((inout ref Rhs) => Rhs.init)(rhs);
1795     }));
1796 }
1797 
1798 ///
1799 @nogc nothrow pure @safe unittest
1800 {
1801     static struct S1
1802     {
1803         @disable this();
1804         @disable this(this);
1805     }
1806     static struct S2
1807     {
1808         void opAssign(S1 s) pure nothrow @safe @nogc
1809         {
1810         }
1811     }
1812     static struct S3
1813     {
1814         void opAssign(ref S1 s) pure nothrow @safe @nogc
1815         {
1816         }
1817     }
1818     static assert(isAssignable!(S2, S1));
1819     static assert(!isAssignable!(S3, S1));
1820 
1821     static assert(isAssignable!(const(char)[], string));
1822     static assert(!isAssignable!(string, char[]));
1823 
1824     static assert(isAssignable!int);
1825     static assert(!isAssignable!(const int, int));
1826 }
1827 
1828 /**
1829  * Returns template parameters of $(D_PARAM T).
1830  *
1831  * Params:
1832  *  T = Template instance.
1833  *
1834  * Returns: Template parameters of $(D_PARAM T).
1835  */
1836 alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args;
1837 
1838 ///
1839 @nogc nothrow pure @safe unittest
1840 {
1841     template T(A, B)
1842     {
1843     }
1844     static assert(is(TemplateArgsOf!(T!(int, uint)) == AliasSeq!(int, uint)));
1845 }
1846 
1847 /**
1848  * Returns a tuple with parameter types of a function.
1849  *
1850  * Params:
1851  *  F = A function.
1852  *
1853  * Returns: Tuple with parameter types of a function.
1854  */
1855 template Parameters(F...)
1856 if (isCallable!F)
1857 {
1858     static if (is(FunctionTypeOf!F T == function))
1859     {
1860         alias Parameters = T;
1861     }
1862     else
1863     {
1864         static assert(false, "Function has no parameters");
1865     }
1866 }
1867 
1868 ///
1869 @nogc nothrow pure @safe unittest
1870 {
1871     int func(Object, uint[]);
1872     static assert(is(Parameters!func == AliasSeq!(Object, uint[])));
1873 }
1874 
1875 /**
1876  * Returns a string array with all parameter names of a function.
1877  *
1878  * If a parameter has no name, an empty string is placed into array.
1879  *
1880  * Params:
1881  *  F = A function.
1882  *
1883  * Returns: Function parameter names.
1884  */
1885 template ParameterIdentifierTuple(F...)
1886 if (isCallable!F)
1887 {
1888     static if (is(FunctionTypeOf!F Params == __parameters))
1889     {
1890         string[] Impl()
1891         {
1892             string[] tuple;
1893 
1894             foreach (k, P; Params)
1895             {
1896                 static if (is(typeof(__traits(identifier, Params[k .. $]))))
1897                 {
1898                     tuple ~= __traits(identifier, Params[k .. $]);
1899                 }
1900                 else
1901                 {
1902                     tuple ~= "";
1903                 }
1904             }
1905 
1906             return tuple;
1907         }
1908         enum string[] ParameterIdentifierTuple = Impl();
1909     }
1910     else
1911     {
1912         static assert(false, "Function has no parameters");
1913     }
1914 }
1915 
1916 ///
1917 @nogc nothrow pure @safe unittest
1918 {
1919     int func(ref Object stuff, uint[] = null, scope uint k = 1);
1920     alias P = ParameterIdentifierTuple!func;
1921     static assert(P[0] == "stuff");
1922     static assert(P[1] == "");
1923     static assert(P[2] == "k");
1924 }
1925 
1926 /// Attributes can be attached to a function.
1927 enum FunctionAttribute : uint
1928 {
1929     none = 0x0000,
1930     pure_ = 0x0001,
1931     nothrow_ = 0x0002,
1932     ref_ = 0x0004,
1933     property = 0x0008,
1934     trusted = 0x0010,
1935     safe = 0x0020,
1936     nogc = 0x0040,
1937     system = 0x0080,
1938     const_ = 0x0100,
1939     immutable_ = 0x0200,
1940     inout_ = 0x0400,
1941     shared_ = 0x0800,
1942     return_ = 0x1000,
1943     scope_ = 0x2000,
1944 }
1945 
1946 /**
1947  * Retrieves the attributes of the function $(D_PARAM F).
1948  *
1949  * The attributes are returned as a bit-mask of
1950  * $(D_PSYMBOL FunctionAttribute) values.
1951  *
1952  * Params: A function.
1953  *
1954  * Returns: Attributes of the function $(D_PARAM F).
1955  *
1956  * See_Also: $(D_PSYMBOL FunctionAttribute).
1957  */
1958 template functionAttributes(F...)
1959 if (isCallable!F)
1960 {
1961     uint Impl()
1962     {
1963         uint attrs = FunctionAttribute.none;
1964         foreach (a; __traits(getFunctionAttributes, F[0]))
1965         {
1966             static if (a == "const")
1967             {
1968                 attrs |= FunctionAttribute.const_;
1969             }
1970             else static if (a == "immutable")
1971             {
1972                 attrs |= FunctionAttribute.immutable_;
1973             }
1974             else static if (a == "inout")
1975             {
1976                 attrs |= FunctionAttribute.inout_;
1977             }
1978             else static if (a == "@nogc")
1979             {
1980                 attrs |= FunctionAttribute.nogc;
1981             }
1982             else static if (a == "nothrow")
1983             {
1984                 attrs |= FunctionAttribute.nothrow_;
1985             }
1986             else static if (a == "@property")
1987             {
1988                 attrs |= FunctionAttribute.property;
1989             }
1990             else static if (a == "pure")
1991             {
1992                 attrs |= FunctionAttribute.pure_;
1993             }
1994             else static if (a == "ref")
1995             {
1996                 attrs |= FunctionAttribute.ref_;
1997             }
1998             else static if (a == "return")
1999             {
2000                 attrs |= FunctionAttribute.return_;
2001             }
2002             else static if (a == "@safe")
2003             {
2004                 attrs |= FunctionAttribute.safe;
2005             }
2006             else static if (a == "scope")
2007             {
2008                 attrs |= FunctionAttribute.scope_;
2009             }
2010             else static if (a == "shared")
2011             {
2012                 attrs |= FunctionAttribute.shared_;
2013             }
2014             else static if (a == "@system")
2015             {
2016                 attrs |= FunctionAttribute.system;
2017             }
2018             else static if (a == "@trusted")
2019             {
2020                 attrs |= FunctionAttribute.trusted;
2021             }
2022         }
2023         return attrs;
2024     }
2025     enum uint functionAttributes = Impl();
2026 }
2027 
2028 ///
2029 @nogc nothrow pure @safe unittest
2030 {
2031     @property ref int func1() pure nothrow @safe @nogc shared scope;
2032     static assert((functionAttributes!func1 & FunctionAttribute.pure_)
2033                == FunctionAttribute.pure_);
2034     static assert((functionAttributes!func1 & FunctionAttribute.nothrow_)
2035                == FunctionAttribute.nothrow_);
2036     static assert((functionAttributes!func1 & FunctionAttribute.safe)
2037                == FunctionAttribute.safe);
2038     static assert((functionAttributes!func1 & FunctionAttribute.nogc)
2039                == FunctionAttribute.nogc);
2040     static assert((functionAttributes!func1 & FunctionAttribute.shared_)
2041                == FunctionAttribute.shared_);
2042     static assert((functionAttributes!func1 & FunctionAttribute.ref_)
2043                == FunctionAttribute.ref_);
2044     static assert((functionAttributes!func1 & FunctionAttribute.property)
2045                == FunctionAttribute.property);
2046     static assert((functionAttributes!func1 & FunctionAttribute.scope_)
2047                == FunctionAttribute.scope_);
2048     static assert((functionAttributes!func1 & FunctionAttribute.system) == 0);
2049     static assert((functionAttributes!func1 & FunctionAttribute.trusted) == 0);
2050     static assert((functionAttributes!func1 & FunctionAttribute.return_) == 0);
2051 }
2052 
2053 /**
2054  * Determines whether a function has attribute.
2055  *
2056  * This template should get at least two arguments: the function itself and the
2057  * attributes it should be tested for. If more than one attribute is given,
2058  * $(D_PSYMBOL hasFunctionAttributes) evaluates to $(D_KEYWORD true) if all of
2059  * them are present. The attributes should be $(D_PSYMBOL FunctionAttribute)
2060  * members.
2061  *
2062  * Params:
2063  *  Args = The function and attributes.
2064  *
2065  * Returns:
2066  *
2067  * See_Also: $(D_PSYMBOL FunctionAttribute).
2068  */
2069 template hasFunctionAttributes(Args...)
2070 if (Args.length > 1
2071  && is(typeof(Args[1]) == FunctionAttribute)
2072  && isCallable!(Args[0])
2073  && allSameType!(Map!(TypeOf, Args[1 .. $])))
2074 {
2075     enum uint pred(Args_...) = Args_[0] | Args_[1];
2076 
2077     template Reduce(Args_...)
2078     {
2079         static if (Args_.length == 1)
2080         {
2081             enum uint Reduce = Args_[0];
2082         }
2083         else
2084         {
2085             enum uint Reduce = Reduce!(pred!(Args_[0], Args_[1]), Args_[2 .. $]);
2086         }
2087     }
2088     enum uint field = Reduce!(0, Args[1 .. $]);
2089     enum hasFunctionAttributes = (functionAttributes!(Args[0]) & field) == field;
2090 }
2091 
2092 ///
2093 @nogc nothrow pure @safe unittest
2094 {
2095     static struct Range
2096     {
2097         @property auto front() inout
2098         {
2099             return 8;
2100         }
2101     }
2102     static assert(hasFunctionAttributes!(Range.init.front, FunctionAttribute.inout_));
2103     static assert(!hasFunctionAttributes!(Range.init.front, FunctionAttribute.const_));
2104     static assert(!hasFunctionAttributes!(Range.init.front,
2105                   FunctionAttribute.inout_, FunctionAttribute.const_));
2106 }
2107 
2108 /**
2109  * Returns a tuple with default values of the parameters to $(D_PARAM F).
2110  *
2111  * If a parameter doesn't have a default value, $(D_KEYWORD void) is returned.
2112  *
2113  * Params:
2114  *  F = A function.
2115  *
2116  * Returns: Default values of the parameters to $(D_PARAM F).
2117  */
2118 template ParameterDefaults(F...)
2119 if (isCallable!F)
2120 {
2121     static if (is(FunctionTypeOf!F T == __parameters))
2122     {
2123         private template GetDefault(size_t i)
2124         {
2125             static if (i == T.length)
2126             {
2127                 alias GetDefault = AliasSeq!();
2128             }
2129             else
2130             {
2131                 auto getDefault(T[i .. i + 1] name)
2132                 {
2133                     return name[0];
2134                 }
2135                 static if (is(typeof(getDefault())))
2136                 {
2137                     alias Default = Alias!(getDefault());
2138                 }
2139                 else
2140                 {
2141                     alias Default = void;
2142                 }
2143                 alias GetDefault = AliasSeq!(Default, GetDefault!(i + 1));
2144             }
2145         }
2146 
2147         alias ParameterDefaults = GetDefault!0;
2148     }
2149 }
2150 
2151 ///
2152 @nogc nothrow pure @safe unittest
2153 {
2154     void func1(int k, uint b = 5, int[] = [1, 2]);
2155     alias Defaults = ParameterDefaults!func1;
2156     static assert(is(Defaults[0] == void));
2157     static assert(Defaults[1 .. 3] == AliasSeq!(5, [1, 2]));
2158 }
2159 
2160 /**
2161  * Determines whether $(D_PARAM T) has an elaborate destructor.
2162  *
2163  * Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the
2164  * length greater than`0` can have elaborate destructors, for all other types
2165  * $(D_PSYMBOL hasElaborateDestructor) evaluates to $(D_KEYWORD false).
2166  *
2167  * An elaborate destructor is an explicitly defined destructor or one generated
2168  * by the compiler. The compiler generates a destructor for a
2169  * $(D_KEYWORD struct) if it has members with an elaborate destructor.
2170  *
2171  * Params:
2172  *  T = A type.
2173  *
2174  * Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate destructor,
2175  *          $(D_KEYWORD false) otherwise.
2176  */
2177 template hasElaborateDestructor(T)
2178 {
2179     static if (is(T E : E[L], size_t L))
2180     {
2181         enum bool hasElaborateDestructor = L > 0 && hasElaborateDestructor!E;
2182     }
2183     else
2184     {
2185         enum bool hasElaborateDestructor = is(T == struct)
2186                                         && hasMember!(T, "__xdtor");
2187     }
2188 }
2189 
2190 ///
2191 @nogc nothrow pure @safe unittest
2192 {
2193     class C
2194     {
2195         ~this()
2196         {
2197         }
2198     }
2199     static assert(!hasElaborateDestructor!C);
2200 
2201     static struct S
2202     {
2203         ~this()
2204         {
2205         }
2206     }
2207     static struct S1
2208     {
2209         S s;
2210     }
2211     static struct S2
2212     {
2213     }
2214     static assert(hasElaborateDestructor!S); // Explicit destructor.
2215     static assert(hasElaborateDestructor!S1); // Compiler-generated destructor.
2216     static assert(!hasElaborateDestructor!S2); // No destructor.
2217 
2218     static assert(hasElaborateDestructor!(S[1]));
2219     static assert(!hasElaborateDestructor!(S[0]));
2220 }
2221 
2222 /**
2223  * Determines whether $(D_PARAM T) has an elaborate postblit constructor.
2224  *
2225  * Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the
2226  * length greater than`0` can have elaborate postblit constructors, for all
2227  * other types $(D_PSYMBOL hasElaborateCopyConstructor) evaluates to
2228  * $(D_KEYWORD false).
2229  *
2230  * An elaborate postblit constructor is an explicitly defined postblit
2231  * constructor or one generated by the compiler. The compiler generates a
2232  * postblit constructor for a
2233  * $(D_KEYWORD struct) if it has members with an elaborate postblit
2234  * constructor.
2235  *
2236  * Params:
2237  *  T = A type.
2238  *
2239  * Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate postblit
2240  *          constructor, $(D_KEYWORD false) otherwise.
2241  */
2242 template hasElaborateCopyConstructor(T)
2243 {
2244     static if (is(T E : E[L], size_t L))
2245     {
2246         enum bool hasElaborateCopyConstructor = L > 0
2247                                              && hasElaborateCopyConstructor!E;
2248     }
2249     else
2250     {
2251         enum bool hasElaborateCopyConstructor = is(T == struct)
2252                                              && hasMember!(T, "__xpostblit");
2253     }
2254 }
2255 
2256 ///
2257 @nogc nothrow pure @safe unittest
2258 {
2259     static assert(!hasElaborateCopyConstructor!int);
2260 
2261     static struct S
2262     {
2263         this(this)
2264         {
2265         }
2266     }
2267     static struct S1
2268     {
2269         S s;
2270     }
2271     static struct S2
2272     {
2273     }
2274     static assert(hasElaborateCopyConstructor!S); // Explicit destructor.
2275     static assert(hasElaborateCopyConstructor!S1); // Compiler-generated destructor.
2276     static assert(!hasElaborateCopyConstructor!S2); // No destructor.
2277     static assert(hasElaborateCopyConstructor!(S[1]));
2278     static assert(!hasElaborateCopyConstructor!(S[0]));
2279 }
2280 
2281 /**
2282  * Determines whether $(D_PARAM T) has an elaborate assign.
2283  *
2284  * Only $(D_KEYWORD struct)s and static arrays of $(D_KEYWORD struct)s with the
2285  * length greater than`0` can have an elaborate assign, for all
2286  * other types $(D_PSYMBOL hasElaborateAssign) evaluates to $(D_KEYWORD false).
2287  *
2288  * An elaborate assign is defined with $(D_INLINECODE opAssign(typeof(this)))
2289  * or $(D_INLINECODE opAssign(ref typeof(this))). An elaborate assign can be
2290  * generated for a $(D_KEYWORD struct) by the compiler if one of the members of
2291  * this $(D_KEYWORD struct) has an elaborate assign.
2292  *
2293  * Params:
2294  *  T = A type.
2295  *
2296  * Returns: $(D_KEYWORD true) if $(D_PARAM T) has an elaborate assign,
2297  *          $(D_KEYWORD false) otherwise.
2298  */
2299 template hasElaborateAssign(T)
2300 {
2301     static if (is(T E : E[L], size_t L))
2302     {
2303         enum bool hasElaborateAssign = L > 0 && hasElaborateAssign!E;
2304     }
2305     else static if (is(T == struct))
2306     {
2307         private enum bool valueAssign = is(typeof({ T.init.opAssign(T()); }));
2308         enum bool hasElaborateAssign = valueAssign || is(typeof({
2309             T s;
2310             s.opAssign(s);
2311         }));
2312     }
2313     else
2314     {
2315         enum bool hasElaborateAssign = false;
2316     }
2317 }
2318 
2319 /**
2320  * Returns all members of $(D_KEYWORD enum) $(D_PARAM T).
2321  *
2322  * The members of $(D_PARAM T) are typed as $(D_PARAM T), not as a base type
2323  * of the enum.
2324  *
2325  * $(D_PARAM EnumMembers) returns all members of $(D_PARAM T), also if there
2326  * are some duplicates.
2327  *
2328  * Params:
2329  *  T = A $(D_KEYWORD enum).
2330  *
2331  * Returns: All members of $(D_PARAM T).
2332  */
2333 template EnumMembers(T)
2334 if (is(T == enum))
2335 {
2336     private template getEnumMembers(Args...)
2337     {
2338         static if (Args.length == 1)
2339         {
2340             enum T getEnumMembers = __traits(getMember, T, Args[0]);
2341         }
2342         else
2343         {
2344             alias getEnumMembers = AliasSeq!(__traits(getMember, T, Args[0]),
2345                                              getEnumMembers!(Args[1 .. $]));
2346         }
2347     }
2348     private alias allMembers = AliasSeq!(__traits(allMembers, T));
2349     static if (allMembers.length == 1)
2350     {
2351         alias EnumMembers = AliasSeq!(__traits(getMember, T, allMembers));
2352     }
2353     else
2354     {
2355         alias EnumMembers = getEnumMembers!allMembers;
2356     }
2357 }
2358 
2359 ///
2360 @nogc nothrow pure @safe unittest
2361 {
2362     enum E : int
2363     {
2364         one,
2365         two,
2366         three,
2367     }
2368     static assert([EnumMembers!E] == [E.one, E.two, E.three]);
2369 }
2370 
2371 /**
2372  * Different than $(D_INLINECODE T.alignof), which is the same for all class
2373  * types,  $(D_PSYMBOL classInstanceOf) determines the alignment of the class
2374  * instance and not of its reference.
2375  *
2376  * Params:
2377  *  T = A class.
2378  *
2379  * Returns: Alignment of an instance of the class $(D_PARAM T).
2380  */
2381 template classInstanceAlignment(T)
2382 if (is(T == class))
2383 {
2384     private enum ptrdiff_t pred(U1, U2) = U1.alignof - U2.alignof;
2385     private alias Fields = typeof(T.tupleof);
2386     enum size_t classInstanceAlignment = Max!(pred, T, Fields).alignof;
2387 }
2388 
2389 ///
2390 @nogc nothrow pure @safe unittest
2391 {
2392     class C1
2393     {
2394     }
2395     static assert(classInstanceAlignment!C1 == C1.alignof);
2396 
2397     static struct S
2398     {
2399         align(8)
2400         uint s;
2401 
2402         int i;
2403     }
2404     class C2
2405     {
2406         S s;
2407     }
2408     static assert(classInstanceAlignment!C2 == S.alignof);
2409 }
2410 
2411 /**
2412  * Returns the size in bytes of the state that needs to be allocated to hold an
2413  * object of type $(D_PARAM T).
2414  *
2415  * There is a difference between the `.sizeof`-property and
2416  * $(D_PSYMBOL stateSize) if $(D_PARAM T) is a class or an interface.
2417  * `T.sizeof` is constant on the given architecture then and is the same as
2418  * `size_t.sizeof` and `ptrdiff_t.sizeof`. This is because classes and
2419  * interfaces are reference types and `.sizeof` returns the size of the
2420  * reference which is the same as the size of a pointer. $(D_PSYMBOL stateSize)
2421  * returns the size of the instance itself.
2422  *
2423  * The size of a dynamic array is `size_t.sizeof * 2` since a dynamic array
2424  * stores its length and a data pointer. The size of the static arrays is
2425  * calculated differently since they are value types. It is the array length
2426  * multiplied by the element size.
2427  *
2428  * `stateSize!void` is `1` since $(D_KEYWORD void) is mostly used as a synonym
2429  * for $(D_KEYWORD byte)/$(D_KEYWORD ubyte) in `void*`.
2430  *
2431  * Params:
2432  *  T = Object type.
2433  *
2434  * Returns: Size of an instance of type $(D_PARAM T).
2435  */
2436 template stateSize(T)
2437 {
2438     static if (isPolymorphicType!T)
2439     {
2440         enum size_t stateSize = __traits(classInstanceSize, T);
2441     }
2442     else
2443     {
2444         enum size_t stateSize = T.sizeof;
2445     }
2446 }
2447 
2448 ///
2449 @nogc nothrow pure @safe unittest
2450 {
2451     static assert(stateSize!int == 4);
2452     static assert(stateSize!bool == 1);
2453     static assert(stateSize!(int[]) == (size_t.sizeof * 2));
2454     static assert(stateSize!(short[3]) == 6);
2455 
2456     static struct Empty
2457     {
2458     }
2459     static assert(stateSize!Empty == 1);
2460     static assert(stateSize!void == 1);
2461 }
2462 
2463 /**
2464  * Tests whether $(D_INLINECODE pred(T)) can be used as condition in an
2465  * $(D_KEYWORD if)-statement or a ternary operator.
2466  *
2467  * $(D_PARAM pred) is an optional parameter. By default $(D_PSYMBOL ifTestable)
2468  * tests whether $(D_PARAM T) itself is usable as condition in an
2469  * $(D_KEYWORD if)-statement or a ternary operator, i.e. if it a value of type
2470  * $(D_PARAM T) can be converted to a boolean.
2471  *
2472  * Params:
2473  *  T    = A type.
2474  *  pred = Function with one argument.
2475  *
2476  * Returns: $(D_KEYWORD true) if $(D_INLINECODE pred(T)) can be used as
2477  *          condition in an $(D_KEYWORD if)-statement or a ternary operator.
2478  */
2479 template ifTestable(T, alias pred = a => a)
2480 {
2481     enum bool ifTestable = is(typeof(pred(T.init) ? true : false));
2482 }
2483 
2484 ///
2485 @nogc nothrow pure @safe unittest
2486 {
2487     static assert(ifTestable!int);
2488 
2489     static struct S1
2490     {
2491     }
2492     static assert(!ifTestable!S1);
2493 
2494     static struct S2
2495     {
2496         bool opCast(T : bool)()
2497         {
2498             return true;
2499         }
2500     }
2501     static assert(ifTestable!S2);
2502 }
2503 
2504 /**
2505  * Returns a compile-time tuple of user-defined attributes (UDA) attached to
2506  * $(D_PARAM symbol).
2507  *
2508  * $(D_PARAM symbol) can be:
2509  *
2510  * $(DL
2511  *  $(DT Template)
2512  *  $(DD The attribute is matched if it is an instance of the template
2513  *       $(D_PARAM attr).)
2514  *  $(DT Type)
2515  *  $(DD The attribute is matched if it its type is $(D_PARAM attr).)
2516  *  $(DT Expression)
2517  *  $(DD The attribute is matched if it equals to $(D_PARAM attr).)
2518  * )
2519  *
2520  * If $(D_PARAM attr) isn't given, all user-defined attributes of
2521  * $(D_PARAM symbol) are returned.
2522  *
2523  * Params:
2524  *  symbol = A symbol.
2525  *  attr   = User-defined attribute.
2526  *
2527  * Returns: A tuple of user-defined attributes attached to $(D_PARAM symbol)
2528  *          and matching $(D_PARAM attr).
2529  *
2530  * See_Also: $(LINK2 https://dlang.org/spec/attribute.html#uda,
2531  *                   User Defined Attributes).
2532  */
2533 template getUDAs(alias symbol, alias attr)
2534 {
2535     private template FindUDA(T...)
2536     {
2537         static if (T.length == 0)
2538         {
2539             alias FindUDA = AliasSeq!();
2540         }
2541         else static if ((isTypeTuple!attr && is(TypeOf!(T[0]) == attr))
2542                      || (is(typeof(T[0] == attr)) && (T[0] == attr))
2543                      || isInstanceOf!(attr, TypeOf!(T[0])))
2544         {
2545             alias FindUDA = AliasSeq!(T[0], FindUDA!(T[1 .. $]));
2546         }
2547         else
2548         {
2549             alias FindUDA = FindUDA!(T[1 .. $]);
2550         }
2551     }
2552     alias getUDAs = FindUDA!(__traits(getAttributes, symbol));
2553 }
2554 
2555 ///
2556 alias getUDAs(alias symbol) = AliasSeq!(__traits(getAttributes, symbol));
2557 
2558 ///
2559 @nogc nothrow pure @safe unittest
2560 {
2561     static struct Attr
2562     {
2563         int i;
2564     }
2565     @Attr int a;
2566     static assert(getUDAs!(a, Attr).length == 1);
2567 
2568     @Attr(8) int b;
2569     static assert(getUDAs!(b, Attr).length == 1);
2570     static assert(getUDAs!(b, Attr)[0].i == 8);
2571     static assert(getUDAs!(b, Attr(8)).length == 1);
2572     static assert(getUDAs!(b, Attr(7)).length == 0);
2573 
2574     @("string", 5) int c;
2575     static assert(getUDAs!(c, "string").length == 1);
2576     static assert(getUDAs!(c, 5).length == 1);
2577     static assert(getUDAs!(c, "String").length == 0);
2578     static assert(getUDAs!(c, 4).length == 0);
2579 
2580     static struct T(U)
2581     {
2582         enum U s = 7;
2583         U i;
2584     }
2585     @T!int @T!int(8) int d;
2586     static assert(getUDAs!(d, T).length == 2);
2587     static assert(getUDAs!(d, T)[0].s == 7);
2588     static assert(getUDAs!(d, T)[1].i == 8);
2589 
2590     @T int e;
2591     static assert(getUDAs!(e, T).length == 0);
2592 }
2593 
2594 /**
2595  * Determines whether $(D_PARAM symbol) has user-defined attribute
2596  * $(D_PARAM attr) attached to it.
2597  *
2598  * Params:
2599  *  symbol = A symbol.
2600  *  attr   = User-defined attribute.
2601  *
2602  * Returns: $(D_KEYWORD true) if $(D_PARAM symbol) has user-defined attribute
2603  *          $(D_PARAM attr), $(D_KEYWORD false) otherwise.
2604  *
2605  * See_Also: $(LINK2 https://dlang.org/spec/attribute.html#uda,
2606  *                   User Defined Attributes).
2607  */
2608 template hasUDA(alias symbol, alias attr)
2609 {
2610     enum bool hasUDA = getUDAs!(symbol, attr).length != 0;
2611 }
2612 
2613 ///
2614 @nogc nothrow pure @safe unittest
2615 {
2616     static struct Attr1
2617     {
2618     }
2619     static struct Attr2
2620     {
2621     }
2622     @Attr1 int a;
2623     static assert(hasUDA!(a, Attr1));
2624     static assert(!hasUDA!(a, Attr2));
2625 }
2626 
2627 /**
2628  * If $(D_PARAM T) is a type, constructs its default value, otherwise
2629  * $(D_PSYMBOL evalUDA) aliases itself to $(D_PARAM T).
2630  *
2631  * This template is useful when working with UDAs with default parameters,
2632  * i.e. if an attribute can be given as `@Attr` or `@Attr("param")`,
2633  * $(D_PSYMBOL evalUDA) makes `@Attr()` from `@Attr`, but returns
2634  * `@Attr("param")` as is.
2635  *
2636  * $(D_PARAM T) (or its type if it isn't a type already) should have a default
2637  * constructor.
2638  *
2639  * Params:
2640  *  T = User Defined Attribute.
2641  */
2642 alias evalUDA(alias T) = T;
2643 
2644 /// ditto
2645 alias evalUDA(T) = Alias!(T());
2646 
2647 ///
2648 @nogc nothrow pure @safe unittest
2649 {
2650     static struct Length
2651     {
2652         size_t length = 8;
2653     }
2654     @Length @Length(0) int i;
2655     alias uda = AliasSeq!(__traits(getAttributes, i));
2656 
2657     alias attr1 = evalUDA!(uda[0]);
2658     alias attr2 = evalUDA!(uda[1]);
2659 
2660     static assert(is(typeof(attr1) == Length));
2661     static assert(is(typeof(attr2) == Length));
2662 
2663     static assert(attr1.length == 8);
2664     static assert(attr2.length == 0);
2665 }
2666 
2667 /**
2668  * Tests whether $(D_PARAM T) is an inner class, i.e. a class nested inside
2669  * another class.
2670  *
2671  * All inner classes get `outer` propery automatically generated, which points
2672  * to its parent class, though it can be explicitly defined to be something
2673  * different. If $(D_PARAM T) does this, $(D_PSYMBOL isInnerClass)
2674  * evaluates to $(D_KEYWORD false).
2675  *
2676  * Params:
2677  *  T = Class to be tested.
2678  *
2679  * Returns $(D_KEYWORD true) if $(D_PARAM T) is an inner class,
2680  *         $(D_KEYWORD false) otherwise.
2681  */
2682 template isInnerClass(T)
2683 {
2684     static if (is(T == class) && is(typeof(T.outer) == class))
2685     {
2686         enum bool isInnerClass = !canFind!("outer", __traits(allMembers, T));
2687     }
2688     else
2689     {
2690         enum bool isInnerClass = false;
2691     }
2692 }
2693 
2694 ///
2695 @nogc nothrow pure @safe unittest
2696 {
2697     class A
2698     {
2699     }
2700     class O
2701     {
2702         class I
2703         {
2704         }
2705         class Fake
2706         {
2707             bool outer;
2708         }
2709     }
2710     static assert(!isInnerClass!(O));
2711     static assert(isInnerClass!(O.I));
2712     static assert(!isInnerClass!(O.Fake));
2713 }
2714 
2715 /**
2716  * Returns the types of all members of $(D_PARAM T).
2717  *
2718  * If $(D_PARAM T) is a $(D_KEYWORD struct) or $(D_KEYWORD union) or
2719  * $(D_KEYWORD class), returns the types of all its fields. It is actually the
2720  * same as `T.tupleof`, but the content pointer for the nested type isn't
2721  * included.
2722  *
2723  * If $(D_PARAM T) is neither a $(D_KEYWORD struct) nor $(D_KEYWORD union) nor
2724  * $(D_KEYWORD class), $(D_PSYMBOL Fields) returns an $(D_PSYMBOL AliasSeq)
2725  * with the single element $(D_PARAM T).
2726  *
2727  * Params:
2728  *  T = A type.
2729  *
2730  * Returns: $(D_PARAM T)'s fields.
2731  */
2732 template Fields(T)
2733 {
2734     static if ((is(T == struct) || is(T == union)) && isNested!T)
2735     {
2736         // The last element of .tupleof of a nested struct or union is "this",
2737         // the context pointer, type "void*".
2738         alias Fields = typeof(T.tupleof[0 .. $ - 1]);
2739     }
2740     else static if (is(T == class) || is(T == struct) || is(T == union))
2741     {
2742         alias Fields = typeof(T.tupleof);
2743     }
2744     else
2745     {
2746         alias Fields = AliasSeq!T;
2747     }
2748 }
2749 
2750 ///
2751 @nogc nothrow pure @safe unittest
2752 {
2753     struct Nested
2754     {
2755         int i;
2756 
2757         void func()
2758         {
2759         }
2760     }
2761     static assert(is(Fields!Nested == AliasSeq!int));
2762 
2763     class C
2764     {
2765         uint u;
2766     }
2767     static assert(is(Fields!C == AliasSeq!uint));
2768 
2769     static assert(is(Fields!short == AliasSeq!short));
2770 }
2771 
2772 /**
2773  * Determines whether all $(D_PARAM Types) are the same.
2774  *
2775  * If $(D_PARAM Types) is empty, returns $(D_KEYWORD true).
2776  *
2777  * Params:
2778  *  Types = Type sequence.
2779  *
2780  * Returns: $(D_KEYWORD true) if all $(D_PARAM Types) are the same,
2781  *          $(D_KEYWORD false) otherwise.
2782  */
2783 template allSameType(Types...)
2784 {
2785     static if (Types.length == 0)
2786     {
2787         enum bool allSameType = true;
2788     }
2789     else
2790     {
2791         private enum bool sameType(T) = is(T == Types[0]);
2792 
2793         enum bool allSameType = allSatisfy!(sameType, Types[1 .. $]);
2794     }
2795 }
2796 
2797 ///
2798 @nogc nothrow pure @safe unittest
2799 {
2800     static assert(allSameType!());
2801     static assert(allSameType!int);
2802     static assert(allSameType!(int, int, int));
2803     static assert(!allSameType!(int, uint, int));
2804     static assert(!allSameType!(int, uint, short));
2805 }
2806 
2807 /**
2808  * Determines whether values of type $(D_PARAM T) can be compared for equality,
2809  * i.e. using `==` or `!=` binary operators.
2810  *
2811  * Params:
2812  *  T = Type to test.
2813  *
2814  * Returns: $(D_KEYWORD true) if $(D_PARAM T) can be compared for equality,
2815  *          $(D_KEYWORD false) otherwise.
2816  */
2817 enum bool isEqualityComparable(T) = ifTestable!(T, a => a == a);
2818 
2819 ///
2820 @nogc nothrow pure @safe unittest
2821 {
2822     static assert(isEqualityComparable!int);
2823 }
2824 
2825 /**
2826  * Determines whether values of type $(D_PARAM T) can be compared for ordering,
2827  * i.e. using `>`, `>=`, `<` or `<=` binary operators.
2828  *
2829  * Params:
2830  *  T = Type to test.
2831  *
2832  * Returns: $(D_KEYWORD true) if $(D_PARAM T) can be compared for ordering,
2833  *          $(D_KEYWORD false) otherwise.
2834  */
2835 enum bool isOrderingComparable(T) = ifTestable!(T, a => a > a);
2836 
2837 ///
2838 @nogc nothrow pure @safe unittest
2839 {
2840     static assert(isOrderingComparable!int);
2841 }