tree-optimization/118653 - ICE in vectorizable_live_operation
[gcc.git] / libphobos / libdruntime / core / internal / traits.d
blobb1b29130eff308cb6af8453b64d7a861dd95b003
1 /**
2 * Contains traits for runtime internal usage.
4 * Copyright: Copyright Digital Mars 2014 -.
5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 * Authors: Martin Nowak
7 * Source: $(DRUNTIMESRC core/internal/_traits.d)
8 */
9 module core.internal.traits;
11 alias AliasSeq(TList...) = TList;
13 template Fields(T)
15 static if (is(T == struct) || is(T == union))
16 alias Fields = typeof(T.tupleof[0 .. $ - __traits(isNested, T)]);
17 else static if (is(T == class) || is(T == interface))
18 alias Fields = typeof(T.tupleof);
19 else
20 alias Fields = AliasSeq!T;
23 T trustedCast(T, U)(auto ref U u) @trusted pure nothrow
25 return cast(T)u;
28 alias Unconst(T : const U, U) = U;
30 /// taken from std.traits.Unqual
31 template Unqual(T : const U, U)
33 static if (is(U == shared V, V))
34 alias Unqual = V;
35 else
36 alias Unqual = U;
39 template BaseElemOf(T)
41 static if (is(OriginalType!T == E[N], E, size_t N))
42 alias BaseElemOf = BaseElemOf!E;
43 else
44 alias BaseElemOf = T;
47 unittest
49 static assert(is(BaseElemOf!(int) == int));
50 static assert(is(BaseElemOf!(int[1]) == int));
51 static assert(is(BaseElemOf!(int[1][2]) == int));
52 static assert(is(BaseElemOf!(int[1][]) == int[1][]));
53 static assert(is(BaseElemOf!(int[][1]) == int[]));
54 enum E : int[2]{ test = [0, 1] }
55 static assert(is(BaseElemOf!(E) == int));
58 // [For internal use]
59 template ModifyTypePreservingTQ(alias Modifier, T)
61 static if (is(T U == immutable U)) alias ModifyTypePreservingTQ = immutable Modifier!U;
62 else static if (is(T U == shared inout const U)) alias ModifyTypePreservingTQ = shared inout const Modifier!U;
63 else static if (is(T U == shared inout U)) alias ModifyTypePreservingTQ = shared inout Modifier!U;
64 else static if (is(T U == shared const U)) alias ModifyTypePreservingTQ = shared const Modifier!U;
65 else static if (is(T U == shared U)) alias ModifyTypePreservingTQ = shared Modifier!U;
66 else static if (is(T U == inout const U)) alias ModifyTypePreservingTQ = inout const Modifier!U;
67 else static if (is(T U == inout U)) alias ModifyTypePreservingTQ = inout Modifier!U;
68 else static if (is(T U == const U)) alias ModifyTypePreservingTQ = const Modifier!U;
69 else alias ModifyTypePreservingTQ = Modifier!T;
71 @safe unittest
73 alias Intify(T) = int;
74 static assert(is(ModifyTypePreservingTQ!(Intify, real) == int));
75 static assert(is(ModifyTypePreservingTQ!(Intify, const real) == const int));
76 static assert(is(ModifyTypePreservingTQ!(Intify, inout real) == inout int));
77 static assert(is(ModifyTypePreservingTQ!(Intify, inout const real) == inout const int));
78 static assert(is(ModifyTypePreservingTQ!(Intify, shared real) == shared int));
79 static assert(is(ModifyTypePreservingTQ!(Intify, shared const real) == shared const int));
80 static assert(is(ModifyTypePreservingTQ!(Intify, shared inout real) == shared inout int));
81 static assert(is(ModifyTypePreservingTQ!(Intify, shared inout const real) == shared inout const int));
82 static assert(is(ModifyTypePreservingTQ!(Intify, immutable real) == immutable int));
85 // Substitute all `inout` qualifiers that appears in T to `const`
86 template substInout(T)
88 static if (is(T == immutable))
90 alias substInout = T;
92 else static if (is(T : shared const U, U) || is(T : const U, U))
94 // U is top-unqualified
95 mixin("alias substInout = "
96 ~ (is(T == shared) ? "shared " : "")
97 ~ (is(T == const) || is(T == inout) ? "const " : "") // substitute inout to const
98 ~ "substInoutForm!U;");
100 else
101 static assert(0);
104 private template substInoutForm(T)
106 static if (is(T == struct) || is(T == class) || is(T == union) || is(T == interface))
108 alias substInoutForm = T; // prevent matching to the form of alias-this-ed type
110 else static if (is(T : V[K], K, V)) alias substInoutForm = substInout!V[substInout!K];
111 else static if (is(T : U[n], U, size_t n)) alias substInoutForm = substInout!U[n];
112 else static if (is(T : U[], U)) alias substInoutForm = substInout!U[];
113 else static if (is(T : U*, U)) alias substInoutForm = substInout!U*;
114 else alias substInoutForm = T;
117 /// used to declare an extern(D) function that is defined in a different module
118 template externDFunc(string fqn, T:FT*, FT) if (is(FT == function))
120 static if (is(FT RT == return) && is(FT Args == function))
122 import core.demangle : mangleFunc;
123 enum decl = {
124 string s = "extern(D) RT externDFunc(Args)";
125 foreach (attr; __traits(getFunctionAttributes, FT))
126 s ~= " " ~ attr;
127 return s ~ ";";
128 }();
129 pragma(mangle, mangleFunc!T(fqn)) mixin(decl);
131 else
132 static assert(0);
135 template staticIota(int beg, int end)
137 static if (beg + 1 >= end)
139 static if (beg >= end)
141 alias staticIota = AliasSeq!();
143 else
145 alias staticIota = AliasSeq!(+beg);
148 else
150 enum mid = beg + (end - beg) / 2;
151 alias staticIota = AliasSeq!(staticIota!(beg, mid), staticIota!(mid, end));
155 private struct __InoutWorkaroundStruct {}
156 @property T rvalueOf(T)(T val) { return val; }
157 @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
158 @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init);
160 // taken from std.traits.isAssignable
161 template isAssignable(Lhs, Rhs = Lhs)
163 enum isAssignable = __traits(compiles, lvalueOf!Lhs = rvalueOf!Rhs) && __traits(compiles, lvalueOf!Lhs = lvalueOf!Rhs);
166 // taken from std.traits.isInnerClass
167 template isInnerClass(T) if (is(T == class))
169 static if (is(typeof(T.outer)))
171 template hasOuterMember(T...)
173 static if (T.length == 0)
174 enum hasOuterMember = false;
175 else
176 enum hasOuterMember = T[0] == "outer" || hasOuterMember!(T[1 .. $]);
178 enum isInnerClass = __traits(isSame, typeof(T.outer), __traits(parent, T)) && !hasOuterMember!(__traits(allMembers, T));
180 else
181 enum isInnerClass = false;
184 template dtorIsNothrow(T)
186 enum dtorIsNothrow = is(typeof(function{T t=void;}) : void function() nothrow);
189 // taken from std.meta.allSatisfy
190 template allSatisfy(alias F, T...)
192 static foreach (Ti; T)
194 static if (!is(typeof(allSatisfy) == bool) && // not yet defined
195 !F!(Ti))
197 enum allSatisfy = false;
200 static if (!is(typeof(allSatisfy) == bool)) // if not yet defined
202 enum allSatisfy = true;
206 // taken from std.meta.anySatisfy
207 template anySatisfy(alias F, Ts...)
209 static foreach (T; Ts)
211 static if (!is(typeof(anySatisfy) == bool) && // not yet defined
212 F!T)
214 enum anySatisfy = true;
217 static if (!is(typeof(anySatisfy) == bool)) // if not yet defined
219 enum anySatisfy = false;
223 // simplified from std.traits.maxAlignment
224 template maxAlignment(Ts...)
225 if (Ts.length > 0)
227 enum maxAlignment =
229 size_t result = 0;
230 static foreach (T; Ts)
231 if (T.alignof > result) result = T.alignof;
232 return result;
233 }();
236 template classInstanceAlignment(T)
237 if (is(T == class))
239 enum classInstanceAlignment = __traits(classInstanceAlignment, T);
242 /// See $(REF hasElaborateMove, std,traits)
243 template hasElaborateMove(S)
245 static if (__traits(isStaticArray, S))
247 enum bool hasElaborateMove = S.sizeof && hasElaborateMove!(BaseElemOf!S);
249 else static if (is(S == struct))
251 enum hasElaborateMove = (is(typeof(S.init.opPostMove(lvalueOf!S))) &&
252 !is(typeof(S.init.opPostMove(rvalueOf!S)))) ||
253 anySatisfy!(.hasElaborateMove, Fields!S);
255 else
257 enum bool hasElaborateMove = false;
261 // std.traits.hasElaborateDestructor
262 template hasElaborateDestructor(S)
264 static if (__traits(isStaticArray, S))
266 enum bool hasElaborateDestructor = S.sizeof && hasElaborateDestructor!(BaseElemOf!S);
268 else static if (is(S == struct))
270 // Once https://issues.dlang.org/show_bug.cgi?id=24865 is fixed, then
271 // this should be the implementation, but until that's fixed, we need the
272 // uncommented code.
273 // enum hasElaborateDestructor = __traits(hasMember, S, "__xdtor");
275 enum hasElaborateDestructor = hasDtor([__traits(allMembers, S)]);
277 else
279 enum bool hasElaborateDestructor = false;
283 private bool hasDtor(string[] members)
285 foreach (name; members)
287 if (name == "__xdtor")
288 return true;
291 return false;
294 @safe unittest
296 static struct NoDestructor {}
297 static assert(!hasElaborateDestructor!NoDestructor);
298 static assert(!hasElaborateDestructor!(NoDestructor[42]));
299 static assert(!hasElaborateDestructor!(NoDestructor[0]));
300 static assert(!hasElaborateDestructor!(NoDestructor[]));
302 static struct HasDestructor { ~this() {} }
303 static assert( hasElaborateDestructor!HasDestructor);
304 static assert( hasElaborateDestructor!(HasDestructor[42]));
305 static assert(!hasElaborateDestructor!(HasDestructor[0]));
306 static assert(!hasElaborateDestructor!(HasDestructor[]));
308 static struct HasDestructor2 { HasDestructor s; }
309 static assert( hasElaborateDestructor!HasDestructor2);
310 static assert( hasElaborateDestructor!(HasDestructor2[42]));
311 static assert(!hasElaborateDestructor!(HasDestructor2[0]));
312 static assert(!hasElaborateDestructor!(HasDestructor2[]));
314 static class HasFinalizer { ~this() {} }
315 static assert(!hasElaborateDestructor!HasFinalizer);
317 static struct HasUnion { union { HasDestructor s; } }
318 static assert(!hasElaborateDestructor!HasUnion);
319 static assert(!hasElaborateDestructor!(HasUnion[42]));
320 static assert(!hasElaborateDestructor!(HasUnion[0]));
321 static assert(!hasElaborateDestructor!(HasUnion[]));
323 static assert(!hasElaborateDestructor!int);
324 static assert(!hasElaborateDestructor!(int[0]));
325 static assert(!hasElaborateDestructor!(int[42]));
326 static assert(!hasElaborateDestructor!(int[]));
329 // https://issues.dlang.org/show_bug.cgi?id=24865
330 @safe unittest
332 static struct S2 { ~this() {} }
333 static struct S3 { S2 field; }
334 static struct S6 { S3[0] field; }
336 static assert( hasElaborateDestructor!S2);
337 static assert( hasElaborateDestructor!S3);
338 static assert(!hasElaborateDestructor!S6);
341 // std.traits.hasElaborateCopyDestructor
342 template hasElaborateCopyConstructor(S)
344 static if (__traits(isStaticArray, S))
346 enum bool hasElaborateCopyConstructor = S.sizeof && hasElaborateCopyConstructor!(BaseElemOf!S);
348 else static if (is(S == struct))
350 enum hasElaborateCopyConstructor = __traits(hasCopyConstructor, S) || __traits(hasPostblit, S);
352 else
354 enum bool hasElaborateCopyConstructor = false;
358 @safe unittest
360 static struct S
362 int x;
363 this(return scope ref typeof(this) rhs) { }
364 this(int x, int y) {}
367 static assert( hasElaborateCopyConstructor!S);
368 static assert(!hasElaborateCopyConstructor!(S[0][1]));
370 static struct S2
372 int x;
373 this(int x, int y) {}
376 static assert(!hasElaborateCopyConstructor!S2);
378 static struct S3
380 int x;
381 this(return scope ref typeof(this) rhs, int x = 42) { }
382 this(int x, int y) {}
385 static assert( hasElaborateCopyConstructor!S3);
387 static struct S4 { union { S s; } }
389 static assert(!hasElaborateCopyConstructor!S4);
392 template hasElaborateAssign(S)
394 static if (__traits(isStaticArray, S))
396 enum bool hasElaborateAssign = S.sizeof && hasElaborateAssign!(BaseElemOf!S);
398 else static if (is(S == struct))
400 enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) ||
401 is(typeof(S.init.opAssign(lvalueOf!S)));
403 else
405 enum bool hasElaborateAssign = false;
409 unittest
412 static struct S {}
413 static assert(!hasElaborateAssign!S);
414 static assert(!hasElaborateAssign!(S[10]));
415 static assert(!hasElaborateAssign!(S[0]));
416 static assert(!hasElaborateAssign!(S[]));
419 static struct S { int i; }
420 static assert(!hasElaborateAssign!S);
421 static assert(!hasElaborateAssign!(S[10]));
422 static assert(!hasElaborateAssign!(S[0]));
423 static assert(!hasElaborateAssign!(S[]));
426 static struct S { void opAssign(S) {} }
427 static assert( hasElaborateAssign!S);
428 static assert( hasElaborateAssign!(S[10]));
429 static assert(!hasElaborateAssign!(S[0]));
430 static assert(!hasElaborateAssign!(S[]));
433 static struct S { void opAssign(ref S) {} }
434 static assert( hasElaborateAssign!S);
435 static assert( hasElaborateAssign!(S[10]));
436 static assert(!hasElaborateAssign!(S[0]));
437 static assert(!hasElaborateAssign!(S[]));
440 static struct S { void opAssign(int) {} }
441 static assert(!hasElaborateAssign!S);
442 static assert(!hasElaborateAssign!(S[10]));
443 static assert(!hasElaborateAssign!(S[0]));
444 static assert(!hasElaborateAssign!(S[]));
447 static struct S { this(this) {} }
448 static assert( hasElaborateAssign!S);
449 static assert( hasElaborateAssign!(S[10]));
450 static assert(!hasElaborateAssign!(S[0]));
451 static assert(!hasElaborateAssign!(S[]));
453 // https://issues.dlang.org/show_bug.cgi?id=24834
456 static struct S { this(ref S) {} }
457 static assert( hasElaborateAssign!S);
458 static assert( hasElaborateAssign!(S[10]));
459 static assert(!hasElaborateAssign!(S[0]));
460 static assert(!hasElaborateAssign!(S[]));
464 static struct S { ~this() {} }
465 static assert( hasElaborateAssign!S);
466 static assert( hasElaborateAssign!(S[10]));
467 static assert(!hasElaborateAssign!(S[0]));
468 static assert(!hasElaborateAssign!(S[]));
471 static struct S { @disable void opAssign(S); }
472 static assert(!hasElaborateAssign!S);
473 static assert(!hasElaborateAssign!(S[10]));
474 static assert(!hasElaborateAssign!(S[0]));
475 static assert(!hasElaborateAssign!(S[]));
478 static struct Member {}
479 static struct S { Member member; }
480 static assert(!hasElaborateAssign!S);
481 static assert(!hasElaborateAssign!(S[10]));
482 static assert(!hasElaborateAssign!(S[0]));
483 static assert(!hasElaborateAssign!(S[]));
486 static struct Member { void opAssign(Member) {} }
487 static struct S { Member member; }
488 static assert( hasElaborateAssign!S);
489 static assert( hasElaborateAssign!(S[10]));
490 static assert(!hasElaborateAssign!(S[0]));
491 static assert(!hasElaborateAssign!(S[]));
494 static struct Member {}
495 static struct S { Member member; void opAssign(S) {} }
496 static assert( hasElaborateAssign!S);
497 static assert( hasElaborateAssign!(S[10]));
498 static assert(!hasElaborateAssign!(S[0]));
499 static assert(!hasElaborateAssign!(S[]));
502 static struct Member { @disable void opAssign(Member); }
503 static struct S { Member member; }
504 static assert(!hasElaborateAssign!S);
505 static assert(!hasElaborateAssign!(S[10]));
506 static assert(!hasElaborateAssign!(S[0]));
507 static assert(!hasElaborateAssign!(S[]));
510 static struct Member { @disable void opAssign(Member); }
511 static struct S { Member member; void opAssign(S) {} }
512 static assert( hasElaborateAssign!S);
513 static assert( hasElaborateAssign!(S[10]));
514 static assert(!hasElaborateAssign!(S[0]));
515 static assert(!hasElaborateAssign!(S[]));
518 static struct Member { void opAssign(Member) {} }
519 static struct S { Member member; @disable void opAssign(S); }
520 static assert(!hasElaborateAssign!S);
521 static assert(!hasElaborateAssign!(S[10]));
522 static assert(!hasElaborateAssign!(S[0]));
523 static assert(!hasElaborateAssign!(S[]));
526 static struct Member { void opAssign(Member) {} }
527 static struct S { union { Member member; } }
528 static assert(!hasElaborateAssign!S);
529 static assert(!hasElaborateAssign!(S[10]));
530 static assert(!hasElaborateAssign!(S[0]));
531 static assert(!hasElaborateAssign!(S[]));
534 static assert(!hasElaborateAssign!int);
535 static assert(!hasElaborateAssign!(string[]));
536 static assert(!hasElaborateAssign!Object);
539 template hasIndirections(T)
541 static if (is(T == enum))
542 enum hasIndirections = hasIndirections!(OriginalType!T);
543 else static if (is(T == struct) || is(T == union))
544 enum hasIndirections = anySatisfy!(.hasIndirections, typeof(T.tupleof));
545 else static if (__traits(isAssociativeArray, T) || is(T == class) || is(T == interface))
546 enum hasIndirections = true;
547 else static if (is(T == E[N], E, size_t N))
548 enum hasIndirections = T.sizeof && (is(E == void) || hasIndirections!(BaseElemOf!E));
549 else static if (isFunctionPointer!T)
550 enum hasIndirections = false;
551 else
552 enum hasIndirections = isPointer!T || isDelegate!T || isDynamicArray!T;
555 @safe unittest
557 static assert(!hasIndirections!int);
558 static assert(!hasIndirections!(const int));
560 static assert( hasIndirections!(int*));
561 static assert( hasIndirections!(const int*));
563 static assert( hasIndirections!(int[]));
564 static assert(!hasIndirections!(int[42]));
565 static assert(!hasIndirections!(int[0]));
567 static assert( hasIndirections!(int*));
568 static assert( hasIndirections!(int*[]));
569 static assert( hasIndirections!(int*[42]));
570 static assert(!hasIndirections!(int*[0]));
572 static assert( hasIndirections!string);
573 static assert( hasIndirections!(string[]));
574 static assert( hasIndirections!(string[42]));
575 static assert(!hasIndirections!(string[0]));
577 static assert( hasIndirections!(void[]));
578 static assert( hasIndirections!(void[17]));
579 static assert(!hasIndirections!(void[0]));
581 static assert( hasIndirections!(string[int]));
582 static assert( hasIndirections!(string[int]*));
583 static assert( hasIndirections!(string[int][]));
584 static assert( hasIndirections!(string[int][12]));
585 static assert(!hasIndirections!(string[int][0]));
587 static assert(!hasIndirections!(int function(string)));
588 static assert( hasIndirections!(int delegate(string)));
589 static assert(!hasIndirections!(const(int function(string))));
590 static assert( hasIndirections!(const(int delegate(string))));
591 static assert(!hasIndirections!(immutable(int function(string))));
592 static assert( hasIndirections!(immutable(int delegate(string))));
594 static class C {}
595 static assert( hasIndirections!C);
597 static interface I {}
598 static assert( hasIndirections!I);
601 enum E : int { a }
602 static assert(!hasIndirections!E);
605 enum E : int* { a }
606 static assert( hasIndirections!E);
609 enum E : string { a = "" }
610 static assert( hasIndirections!E);
613 enum E : int[] { a = null }
614 static assert( hasIndirections!E);
617 enum E : int[3] { a = [1, 2, 3] }
618 static assert(!hasIndirections!E);
621 enum E : int*[3] { a = [null, null, null] }
622 static assert( hasIndirections!E);
625 enum E : int*[0] { a = int*[0].init }
626 static assert(!hasIndirections!E);
629 enum E : C { a = null }
630 static assert( hasIndirections!E);
633 enum E : I { a = null }
634 static assert( hasIndirections!E);
638 static struct S {}
639 static assert(!hasIndirections!S);
641 enum E : S { a = S.init }
642 static assert(!hasIndirections!S);
645 static struct S { int i; }
646 static assert(!hasIndirections!S);
648 enum E : S { a = S.init }
649 static assert(!hasIndirections!S);
652 static struct S { C c; }
653 static assert( hasIndirections!S);
655 enum E : S { a = S.init }
656 static assert( hasIndirections!S);
659 static struct S { int[] arr; }
660 static assert( hasIndirections!S);
662 enum E : S { a = S.init }
663 static assert( hasIndirections!S);
666 int local;
667 struct S { void foo() { ++local; } }
668 static assert( hasIndirections!S);
670 enum E : S { a = S.init }
671 static assert( hasIndirections!S);
675 static union U {}
676 static assert(!hasIndirections!U);
679 static union U { int i; }
680 static assert(!hasIndirections!U);
683 static union U { C c; }
684 static assert( hasIndirections!U);
687 static union U { int[] arr; }
688 static assert( hasIndirections!U);
692 // https://issues.dlang.org/show_bug.cgi?id=12000
693 @safe unittest
695 static struct S(T)
697 static assert(hasIndirections!T);
700 static class A(T)
702 S!A a;
705 A!int dummy;
708 template hasUnsharedIndirections(T)
710 static if (is(T == immutable))
711 enum hasUnsharedIndirections = false;
712 else static if (is(T == struct) || is(T == union))
713 enum hasUnsharedIndirections = anySatisfy!(.hasUnsharedIndirections, Fields!T);
714 else static if (is(T : E[N], E, size_t N))
715 enum hasUnsharedIndirections = is(E == void) ? false : hasUnsharedIndirections!E;
716 else static if (isFunctionPointer!T)
717 enum hasUnsharedIndirections = false;
718 else static if (isPointer!T)
719 enum hasUnsharedIndirections = !is(T : shared(U)*, U) && !is(T : immutable(U)*, U);
720 else static if (isDynamicArray!T)
721 enum hasUnsharedIndirections = !is(T : shared(V)[], V) && !is(T : immutable(V)[], V);
722 else static if (is(T == class) || is(T == interface))
723 enum hasUnsharedIndirections = !is(T : shared(W), W);
724 else
725 enum hasUnsharedIndirections = isDelegate!T || __traits(isAssociativeArray, T); // TODO: how to handle these?
728 unittest
730 static struct Foo { shared(int)* val; }
732 static assert(!hasUnsharedIndirections!(immutable(char)*));
733 static assert(!hasUnsharedIndirections!(string));
735 static assert(!hasUnsharedIndirections!(Foo));
736 static assert( hasUnsharedIndirections!(Foo*));
737 static assert(!hasUnsharedIndirections!(shared(Foo)*));
738 static assert(!hasUnsharedIndirections!(immutable(Foo)*));
740 int local;
741 struct HasContextPointer { int opCall() { return ++local; } }
742 static assert(hasIndirections!HasContextPointer);
745 enum bool isAggregateType(T) = is(T == struct) || is(T == union) ||
746 is(T == class) || is(T == interface);
748 enum bool isPointer(T) = is(T == U*, U) && !isAggregateType!T;
750 enum bool isDynamicArray(T) = is(DynamicArrayTypeOf!T) && !isAggregateType!T;
752 template OriginalType(T)
754 template Impl(T)
756 static if (is(T U == enum)) alias Impl = OriginalType!U;
757 else alias Impl = T;
760 alias OriginalType = ModifyTypePreservingTQ!(Impl, T);
763 template DynamicArrayTypeOf(T)
765 static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT))
766 alias X = DynamicArrayTypeOf!AT;
767 else
768 alias X = OriginalType!T;
770 static if (is(Unqual!X : E[], E) && !is(typeof({ enum n = X.length; })))
771 alias DynamicArrayTypeOf = X;
772 else
773 static assert(0, T.stringof ~ " is not a dynamic array");
776 private template AliasThisTypeOf(T)
777 if (isAggregateType!T)
779 alias members = __traits(getAliasThis, T);
781 static if (members.length == 1)
782 alias AliasThisTypeOf = typeof(__traits(getMember, T.init, members[0]));
783 else
784 static assert(0, T.stringof~" does not have alias this type");
787 template isFunctionPointer(T...)
788 if (T.length == 1)
790 static if (is(T[0] U) || is(typeof(T[0]) U))
792 static if (is(U F : F*) && is(F == function))
793 enum bool isFunctionPointer = true;
794 else
795 enum bool isFunctionPointer = false;
797 else
798 enum bool isFunctionPointer = false;
801 template isDelegate(T...)
802 if (T.length == 1)
804 static if (is(typeof(& T[0]) U : U*) && is(typeof(& T[0]) U == delegate))
806 // T is a (nested) function symbol.
807 enum bool isDelegate = true;
809 else static if (is(T[0] W) || is(typeof(T[0]) W))
811 // T is an expression or a type. Take the type of it and examine.
812 enum bool isDelegate = is(W == delegate);
814 else
815 enum bool isDelegate = false;
818 // std.meta.Filter
819 template Filter(alias pred, TList...)
821 static if (TList.length == 0)
823 alias Filter = AliasSeq!();
825 else static if (TList.length == 1)
827 static if (pred!(TList[0]))
828 alias Filter = AliasSeq!(TList[0]);
829 else
830 alias Filter = AliasSeq!();
832 /* The next case speeds up compilation by reducing
833 * the number of Filter instantiations
835 else static if (TList.length == 2)
837 static if (pred!(TList[0]))
839 static if (pred!(TList[1]))
840 alias Filter = AliasSeq!(TList[0], TList[1]);
841 else
842 alias Filter = AliasSeq!(TList[0]);
844 else
846 static if (pred!(TList[1]))
847 alias Filter = AliasSeq!(TList[1]);
848 else
849 alias Filter = AliasSeq!();
852 else
854 alias Filter =
855 AliasSeq!(
856 Filter!(pred, TList[ 0 .. $/2]),
857 Filter!(pred, TList[$/2 .. $ ]));
861 // std.meta.staticMap
862 template staticMap(alias F, T...)
864 static if (T.length == 0)
866 alias staticMap = AliasSeq!();
868 else static if (T.length == 1)
870 alias staticMap = AliasSeq!(F!(T[0]));
872 /* Cases 2 to 8 improve compile performance by reducing
873 * the number of recursive instantiations of staticMap
875 else static if (T.length == 2)
877 alias staticMap = AliasSeq!(F!(T[0]), F!(T[1]));
879 else static if (T.length == 3)
881 alias staticMap = AliasSeq!(F!(T[0]), F!(T[1]), F!(T[2]));
883 else static if (T.length == 4)
885 alias staticMap = AliasSeq!(F!(T[0]), F!(T[1]), F!(T[2]), F!(T[3]));
887 else static if (T.length == 5)
889 alias staticMap = AliasSeq!(F!(T[0]), F!(T[1]), F!(T[2]), F!(T[3]), F!(T[4]));
891 else static if (T.length == 6)
893 alias staticMap = AliasSeq!(F!(T[0]), F!(T[1]), F!(T[2]), F!(T[3]), F!(T[4]), F!(T[5]));
895 else static if (T.length == 7)
897 alias staticMap = AliasSeq!(F!(T[0]), F!(T[1]), F!(T[2]), F!(T[3]), F!(T[4]), F!(T[5]), F!(T[6]));
899 else static if (T.length == 8)
901 alias staticMap = AliasSeq!(F!(T[0]), F!(T[1]), F!(T[2]), F!(T[3]), F!(T[4]), F!(T[5]), F!(T[6]), F!(T[7]));
903 else
905 alias staticMap =
906 AliasSeq!(
907 staticMap!(F, T[ 0 .. $/2]),
908 staticMap!(F, T[$/2 .. $ ]));
912 // std.exception.assertCTFEable
913 version (CoreUnittest) package(core)
914 void assertCTFEable(alias dg)()
916 static assert({ cast(void) dg(); return true; }());
917 cast(void) dg();
920 // std.traits.FunctionTypeOf
922 Get the function type from a callable object `func`.
924 Using builtin `typeof` on a property function yields the types of the
925 property value, not of the property function itself. Still,
926 `FunctionTypeOf` is able to obtain function types of properties.
928 Note:
929 Do not confuse function types with function pointer types; function types are
930 usually used for compile-time reflection purposes.
932 template FunctionTypeOf(func...)
933 if (func.length == 1 /*&& isCallable!func*/)
935 static if (is(typeof(& func[0]) Fsym : Fsym*) && is(Fsym == function) || is(typeof(& func[0]) Fsym == delegate))
937 alias FunctionTypeOf = Fsym; // HIT: (nested) function symbol
939 else static if (is(typeof(& func[0].opCall) Fobj == delegate))
941 alias FunctionTypeOf = Fobj; // HIT: callable object
943 else static if (is(typeof(& func[0].opCall) Ftyp : Ftyp*) && is(Ftyp == function))
945 alias FunctionTypeOf = Ftyp; // HIT: callable type
947 else static if (is(func[0] T) || is(typeof(func[0]) T))
949 static if (is(T == function))
950 alias FunctionTypeOf = T; // HIT: function
951 else static if (is(T Fptr : Fptr*) && is(Fptr == function))
952 alias FunctionTypeOf = Fptr; // HIT: function pointer
953 else static if (is(T Fdlg == delegate))
954 alias FunctionTypeOf = Fdlg; // HIT: delegate
955 else
956 static assert(0);
958 else
959 static assert(0);
962 @safe unittest
964 class C
966 int value() @property { return 0; }
968 static assert(is( typeof(C.value) == int ));
969 static assert(is( FunctionTypeOf!(C.value) == function ));
972 @system unittest
974 int test(int a);
975 int propGet() @property;
976 int propSet(int a) @property;
977 int function(int) test_fp;
978 int delegate(int) test_dg;
979 static assert(is( typeof(test) == FunctionTypeOf!(typeof(test)) ));
980 static assert(is( typeof(test) == FunctionTypeOf!test ));
981 static assert(is( typeof(test) == FunctionTypeOf!test_fp ));
982 static assert(is( typeof(test) == FunctionTypeOf!test_dg ));
983 alias int GetterType() @property;
984 alias int SetterType(int) @property;
985 static assert(is( FunctionTypeOf!propGet == GetterType ));
986 static assert(is( FunctionTypeOf!propSet == SetterType ));
988 interface Prop { int prop() @property; }
989 Prop prop;
990 static assert(is( FunctionTypeOf!(Prop.prop) == GetterType ));
991 static assert(is( FunctionTypeOf!(prop.prop) == GetterType ));
993 class Callable { int opCall(int) { return 0; } }
994 auto call = new Callable;
995 static assert(is( FunctionTypeOf!call == typeof(test) ));
997 struct StaticCallable { static int opCall(int) { return 0; } }
998 StaticCallable stcall_val;
999 StaticCallable* stcall_ptr;
1000 static assert(is( FunctionTypeOf!stcall_val == typeof(test) ));
1001 static assert(is( FunctionTypeOf!stcall_ptr == typeof(test) ));
1003 interface Overloads
1005 void test(string);
1006 real test(real);
1007 int test(int);
1008 int test() @property;
1010 alias ov = __traits(getVirtualMethods, Overloads, "test");
1011 alias F_ov0 = FunctionTypeOf!(ov[0]);
1012 alias F_ov1 = FunctionTypeOf!(ov[1]);
1013 alias F_ov2 = FunctionTypeOf!(ov[2]);
1014 alias F_ov3 = FunctionTypeOf!(ov[3]);
1015 static assert(is(F_ov0* == void function(string)));
1016 static assert(is(F_ov1* == real function(real)));
1017 static assert(is(F_ov2* == int function(int)));
1018 static assert(is(F_ov3* == int function() @property));
1020 alias F_dglit = FunctionTypeOf!((int a){ return a; });
1021 static assert(is(F_dglit* : int function(int)));
1024 // std.traits.ReturnType
1026 Get the type of the return value from a function,
1027 a pointer to function, a delegate, a struct
1028 with an opCall, a pointer to a struct with an opCall,
1029 or a class with an `opCall`. Please note that $(D_KEYWORD ref)
1030 is not part of a type, but the attribute of the function
1031 (see template $(LREF functionAttributes)).
1033 template ReturnType(func...)
1034 if (func.length == 1 /*&& isCallable!func*/)
1036 static if (is(FunctionTypeOf!func R == return))
1037 alias ReturnType = R;
1038 else
1039 static assert(0, "argument has no return type");
1043 @safe unittest
1045 int foo();
1046 ReturnType!foo x; // x is declared as int
1049 @safe unittest
1051 struct G
1053 int opCall (int i) { return 1;}
1056 alias ShouldBeInt = ReturnType!G;
1057 static assert(is(ShouldBeInt == int));
1059 G g;
1060 static assert(is(ReturnType!g == int));
1062 G* p;
1063 alias pg = ReturnType!p;
1064 static assert(is(pg == int));
1066 class C
1068 int opCall (int i) { return 1;}
1071 static assert(is(ReturnType!C == int));
1073 C c;
1074 static assert(is(ReturnType!c == int));
1076 class Test
1078 int prop() @property { return 0; }
1080 alias R_Test_prop = ReturnType!(Test.prop);
1081 static assert(is(R_Test_prop == int));
1083 alias R_dglit = ReturnType!((int a) { return a; });
1084 static assert(is(R_dglit == int));
1087 // std.traits.Parameters
1089 Get, as a tuple, the types of the parameters to a function, a pointer
1090 to function, a delegate, a struct with an `opCall`, a pointer to a
1091 struct with an `opCall`, or a class with an `opCall`.
1093 template Parameters(func...)
1094 if (func.length == 1 /*&& isCallable!func*/)
1096 static if (is(FunctionTypeOf!func P == function))
1097 alias Parameters = P;
1098 else
1099 static assert(0, "argument has no parameters");
1103 @safe unittest
1105 int foo(int, long);
1106 void bar(Parameters!foo); // declares void bar(int, long);
1107 void abc(Parameters!foo[1]); // declares void abc(long);
1110 @safe unittest
1112 int foo(int i, bool b) { return 0; }
1113 static assert(is(Parameters!foo == AliasSeq!(int, bool)));
1114 static assert(is(Parameters!(typeof(&foo)) == AliasSeq!(int, bool)));
1116 struct S { real opCall(real r, int i) { return 0.0; } }
1117 S s;
1118 static assert(is(Parameters!S == AliasSeq!(real, int)));
1119 static assert(is(Parameters!(S*) == AliasSeq!(real, int)));
1120 static assert(is(Parameters!s == AliasSeq!(real, int)));
1122 class Test
1124 int prop() @property { return 0; }
1126 alias P_Test_prop = Parameters!(Test.prop);
1127 static assert(P_Test_prop.length == 0);
1129 alias P_dglit = Parameters!((int a){});
1130 static assert(P_dglit.length == 1);
1131 static assert(is(P_dglit[0] == int));
1134 // Return `true` if `Type` has `member` that evaluates to `true` in a static if condition
1135 enum isTrue(Type, string member) = __traits(compiles, { static if (__traits(getMember, Type, member)) {} else static assert(0); });
1137 unittest
1139 static struct T
1141 enum a = true;
1142 enum b = false;
1143 enum c = 1;
1144 enum d = 45;
1145 enum e = "true";
1146 enum f = "";
1147 enum g = null;
1148 alias h = bool;
1151 static assert( isTrue!(T, "a"));
1152 static assert(!isTrue!(T, "b"));
1153 static assert( isTrue!(T, "c"));
1154 static assert( isTrue!(T, "d"));
1155 static assert( isTrue!(T, "e"));
1156 static assert( isTrue!(T, "f"));
1157 static assert(!isTrue!(T, "g"));
1158 static assert(!isTrue!(T, "h"));
1161 template hasUDA(alias symbol, alias attribute)
1163 enum isAttr(T) = is(T == attribute);
1165 enum hasUDA = anySatisfy!(isAttr, __traits(getAttributes, symbol));
1168 unittest
1170 enum SomeUDA;
1172 struct Test
1174 int woUDA;
1175 @SomeUDA int oneUDA;
1176 @SomeUDA @SomeUDA int twoUDAs;
1179 static assert(hasUDA!(Test.oneUDA, SomeUDA));
1180 static assert(hasUDA!(Test.twoUDAs, SomeUDA));
1181 static assert(!hasUDA!(Test.woUDA, SomeUDA));