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