1 /**
2 * Contains traits for runtime internal usage.
3 *
4 * Copyright: Copyright Digital Mars 2014 -.
5 * License: $(WEB 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;
10
11 /// taken from std.typetuple.TypeTuple
TypeTuple(TList...)12 template TypeTuple(TList...)
13 {
14 alias TypeTuple = TList;
15 }
16
trustedCast(T,U)17 T trustedCast(T, U)(auto ref U u) @trusted pure nothrow
18 {
19 return cast(T)u;
20 }
21
Unconst(T)22 template Unconst(T)
23 {
24 static if (is(T U == immutable U)) alias Unconst = U;
25 else static if (is(T U == inout const U)) alias Unconst = U;
26 else static if (is(T U == inout U)) alias Unconst = U;
27 else static if (is(T U == const U)) alias Unconst = U;
28 else alias Unconst = T;
29 }
30
31 /// taken from std.traits.Unqual
Unqual(T)32 template Unqual(T)
33 {
34 version (none) // Error: recursive alias declaration @@@BUG1308@@@
35 {
36 static if (is(T U == const U)) alias Unqual = Unqual!U;
37 else static if (is(T U == immutable U)) alias Unqual = Unqual!U;
38 else static if (is(T U == inout U)) alias Unqual = Unqual!U;
39 else static if (is(T U == shared U)) alias Unqual = Unqual!U;
40 else alias Unqual = T;
41 }
42 else // workaround
43 {
44 static if (is(T U == immutable U)) alias Unqual = U;
45 else static if (is(T U == shared inout const U)) alias Unqual = U;
46 else static if (is(T U == shared inout U)) alias Unqual = U;
47 else static if (is(T U == shared const U)) alias Unqual = U;
48 else static if (is(T U == shared U)) alias Unqual = U;
49 else static if (is(T U == inout const U)) alias Unqual = U;
50 else static if (is(T U == inout U)) alias Unqual = U;
51 else static if (is(T U == const U)) alias Unqual = U;
52 else alias Unqual = T;
53 }
54 }
55
56 // Substitute all `inout` qualifiers that appears in T to `const`
substInout(T)57 template substInout(T)
58 {
59 static if (is(T == immutable))
60 {
61 alias substInout = T;
62 }
63 else static if (is(T : shared const U, U) || is(T : const U, U))
64 {
65 // U is top-unqualified
66 mixin("alias substInout = "
67 ~ (is(T == shared) ? "shared " : "")
68 ~ (is(T == const) || is(T == inout) ? "const " : "") // substitute inout to const
69 ~ "substInoutForm!U;");
70 }
71 else
72 static assert(0);
73 }
74
substInoutForm(T)75 private template substInoutForm(T)
76 {
77 static if (is(T == struct) || is(T == class) || is(T == union) || is(T == interface))
78 {
79 alias substInoutForm = T; // prevent matching to the form of alias-this-ed type
80 }
81 else static if (is(T : V[K], K, V)) alias substInoutForm = substInout!V[substInout!K];
82 else static if (is(T : U[n], U, size_t n)) alias substInoutForm = substInout!U[n];
83 else static if (is(T : U[], U)) alias substInoutForm = substInout!U[];
84 else static if (is(T : U*, U)) alias substInoutForm = substInout!U*;
85 else alias substInoutForm = T;
86 }
87
88 /// used to declare an extern(D) function that is defined in a different module
89 template externDFunc(string fqn, T:FT*, FT) if (is(FT == function))
90 {
91 static if (is(FT RT == return) && is(FT Args == function))
92 {
93 import core.demangle : mangleFunc;
94 enum decl = {
95 string s = "extern(D) RT externDFunc(Args)";
96 foreach (attr; __traits(getFunctionAttributes, FT))
97 s ~= " " ~ attr;
98 return s ~ ";";
99 }();
100 pragma(mangle, mangleFunc!T(fqn)) mixin(decl);
101 }
102 else
103 static assert(0);
104 }
105
staticIota(int beg,int end)106 template staticIota(int beg, int end)
107 {
108 static if (beg + 1 >= end)
109 {
110 static if (beg >= end)
111 {
112 alias staticIota = TypeTuple!();
113 }
114 else
115 {
116 alias staticIota = TypeTuple!(+beg);
117 }
118 }
119 else
120 {
121 enum mid = beg + (end - beg) / 2;
122 alias staticIota = TypeTuple!(staticIota!(beg, mid), staticIota!(mid, end));
123 }
124 }
125
dtorIsNothrow(T)126 template dtorIsNothrow(T)
127 {
128 enum dtorIsNothrow = is(typeof(function{T t=void;}) : void function() nothrow);
129 }
130
131 /*
132 Tests whether all given items satisfy a template predicate, i.e. evaluates to
133 $(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])).
134 */
135 package(core.internal)
allSatisfy(alias F,T...)136 template allSatisfy(alias F, T...)
137 {
138 static if (T.length == 0)
139 {
140 enum allSatisfy = true;
141 }
142 else static if (T.length == 1)
143 {
144 enum allSatisfy = F!(T[0]);
145 }
146 else
147 {
148 static if (allSatisfy!(F, T[0 .. $/2]))
149 enum allSatisfy = allSatisfy!(F, T[$/2 .. $]);
150 else
151 enum allSatisfy = false;
152 }
153 }
154
anySatisfy(alias F,T...)155 template anySatisfy(alias F, T...)
156 {
157 static if (T.length == 0)
158 {
159 enum anySatisfy = false;
160 }
161 else static if (T.length == 1)
162 {
163 enum anySatisfy = F!(T[0]);
164 }
165 else
166 {
167 enum anySatisfy =
168 anySatisfy!(F, T[ 0 .. $/2]) ||
169 anySatisfy!(F, T[$/2 .. $ ]);
170 }
171 }
172
173 // simplified from std.traits.maxAlignment
maxAlignment(U...)174 template maxAlignment(U...)
175 {
176 static if (U.length == 0)
177 static assert(0);
178 else static if (U.length == 1)
179 enum maxAlignment = U[0].alignof;
180 else static if (U.length == 2)
181 enum maxAlignment = U[0].alignof > U[1].alignof ? U[0].alignof : U[1].alignof;
182 else
183 {
184 enum a = maxAlignment!(U[0 .. ($+1)/2]);
185 enum b = maxAlignment!(U[($+1)/2 .. $]);
186 enum maxAlignment = a > b ? a : b;
187 }
188 }
189
190 template classInstanceAlignment(T)
191 if (is(T == class))
192 {
193 alias classInstanceAlignment = maxAlignment!(void*, typeof(T.tupleof));
194 }
195
196 // Somehow fails for non-static nested structs without support for aliases
hasElaborateDestructor(T...)197 template hasElaborateDestructor(T...)
198 {
199 static if (is(T[0]))
200 alias S = T[0];
201 else
202 alias S = typeof(T[0]);
203
204 static if (is(S : E[n], E, size_t n) && S.length)
205 {
206 enum bool hasElaborateDestructor = hasElaborateDestructor!E;
207 }
208 else static if (is(S == struct))
209 {
210 enum hasElaborateDestructor = __traits(hasMember, S, "__dtor")
211 || anySatisfy!(.hasElaborateDestructor, S.tupleof);
212 }
213 else
214 enum bool hasElaborateDestructor = false;
215 }
216
217 // Somehow fails for non-static nested structs without support for aliases
hasElaborateCopyConstructor(T...)218 template hasElaborateCopyConstructor(T...)
219 {
220 static if (is(T[0]))
221 alias S = T[0];
222 else
223 alias S = typeof(T[0]);
224
225 static if (is(S : E[n], E, size_t n) && S.length)
226 {
227 enum bool hasElaborateCopyConstructor = hasElaborateCopyConstructor!E;
228 }
229 else static if (is(S == struct))
230 {
231 enum hasElaborateCopyConstructor = __traits(hasMember, S, "__postblit")
232 || anySatisfy!(.hasElaborateCopyConstructor, S.tupleof);
233 }
234 else
235 enum bool hasElaborateCopyConstructor = false;
236 }
237
238 // std.meta.Filter
Filter(alias pred,TList...)239 template Filter(alias pred, TList...)
240 {
241 static if (TList.length == 0)
242 {
243 alias Filter = TypeTuple!();
244 }
245 else static if (TList.length == 1)
246 {
247 static if (pred!(TList[0]))
248 alias Filter = TypeTuple!(TList[0]);
249 else
250 alias Filter = TypeTuple!();
251 }
252 else
253 {
254 alias Filter =
255 TypeTuple!(
256 Filter!(pred, TList[ 0 .. $/2]),
257 Filter!(pred, TList[$/2 .. $ ]));
258 }
259 }
260