1 // Written in the D programming language.
2 /*
3 NYSL Version 0.9982
4
5 A. This software is "Everyone'sWare". It means:
6 Anybody who has this software can use it as if he/she is
7 the author.
8
9 A-1. Freeware. No fee is required.
10 A-2. You can freely redistribute this software.
11 A-3. You can freely modify this software. And the source
12 may be used in any software with no limitation.
13 A-4. When you release a modified version to public, you
14 must publish it with your name.
15
16 B. The author is not responsible for any kind of damages or loss
17 while using or misusing this software, which is distributed
18 "AS IS". No warranty of any kind is expressed or implied.
19 You use AT YOUR OWN RISK.
20
21 C. Copyrighted to Kazuki KOMATSU
22
23 D. Above three clauses are applied both to source and binary
24 form of this software.
25 */
26
27 /**
28 このモジュールは、標準ライブラリのstd.traitsを強化します。
29 */
30
31 module carbon.traits;
32
33 import carbon.templates;
34
35 import std.range,
36 std.traits,
37 std.typetuple;
38
39
40 enum bool isBuiltInImaginary(T) = is(T : ireal);
41 enum bool isBuiltInComplex(T) = is(T : creal);
42
43 unittest
44 {
45 static assert(isBuiltInImaginary!(ifloat));
46 static assert(isBuiltInImaginary!(idouble));
47 static assert(isBuiltInImaginary!(ireal));
48
49 static assert(isBuiltInComplex!(cfloat));
50 static assert(isBuiltInComplex!(cdouble));
51 static assert(isBuiltInComplex!(creal));
52 }
53
54
55 struct FuncAttr
56 {
57 static:
58 /*
59 proxy std.traits.functionAttributes
60 */
61 private template hasFA(FunctionAttribute fa, func...)
62 if(func.length == 1 && isCallable!func)
63 {
64 enum bool hasFA = !!(functionAttributes!func & fa);
65 }
66
67
68 /**
69 true if func is pure
70 */
71 template isPure(func...)
72 if(func.length == 1 && isCallable!func)
73 {
74 enum isPure = hasFA!(FunctionAttribute.pure_, func);
75 }
76
77 unittest
78 {
79 void foo() pure {}
80 void bar() {}
81
82 static assert(isPure!foo);
83 static assert(!isPure!bar);
84
85 static void hoge() pure {}
86 static void hage() {}
87
88 static assert(isPure!hoge);
89 static assert(!isPure!hage);
90 }
91
92
93 /**
94 true if func is nothrow
95 */
96 template isNothrow(func...)
97 if(func.length == 1 && isCallable!func)
98 {
99 enum isNothrow = hasFA!(FunctionAttribute.nothrow_, func);
100 }
101
102
103 /**
104 true if func is ref
105 */
106 template isRef(func...)
107 if(func.length == 1 && isCallable!func)
108 {
109 enum isNothrow = hasFA!(FunctionAttribute.ref_, func);
110 }
111
112
113 /**
114 true if func is property
115 */
116 template isProperty(func...)
117 if(func.length == 1 && isCallable!func)
118 {
119 enum isNothrow = hasFA!(FunctionAttribute.property_, func);
120 }
121
122
123 /**
124 true if func is trusted
125 */
126 template isTrusted(func...)
127 if(func.length == 1 && isCallable!func)
128 {
129 enum isNothrow = hasFA!(FunctionAttribute.trusted, func);
130 }
131 }
132
133
134 /**
135 This template return arity of a function.
136
137 Example:
138 ---
139 template Generator0(size_t N)
140 {
141 alias TypeNuple!(int, N) Generator0;
142 }
143
144 alias argumentInfo!(( (a, b, c) => a), Generator0) Result0;
145
146 static assert(Result0.arity == 3);
147 static assert(Result0.endN == 3);
148 static assert(is(Result0.ParameterTypeTuple == Generator0!3));
149 static assert(is(Result0.ReturnType == int));
150
151
152 template Generator1(size_t N)
153 {
154 alias TypeTuple!(int, ushort, long, double*, uint, real[])[N] Generator1;
155 }
156
157 static assert(Result1.arity == 1);
158 static assert(Result1.endN == 3);
159 static assert(is(Result1.ParameterTypeTuple == double*));
160 static assert(is(Result1.ReturnType == double*));
161 ---
162
163 Authors: Kazuki Komatsu(k3_kaimu)
164 */
165 template argumentInfo(alias templateFun, alias ParamGenRange)
166 if(isTemplateRange!ParamGenRange && !ParamGenRange.empty)
167 {
168 template checkArity(alias pgr)
169 {
170 static if(!pgr.empty)
171 {
172 static if(is(typeof(templateFun(pgr.front.init))))
173 alias checkArity = pgr.front;
174 else
175 alias checkArity = checkArity!(pgr.tail!());
176 }
177 else
178 static assert(0, "arity Error : " ~ templateFun.stringof);
179 }
180
181
182 alias ParameterTypeTuple = TypeTuple!(checkArity!(ParamGenRange));
183 enum size_t arity = ParameterTypeTuple.length;
184 alias ReturnType = typeof(templateFun(ParameterTypeTuple.init));
185 }
186
187 unittest
188 {
189 template Generator0(T...)
190 {
191 enum bool empty = false;
192
193 alias front = T;
194
195 template tail()
196 {
197 alias tail = Generator0!(T, int);
198 }
199 }
200
201 alias argumentInfo!(( (a, b, c) => a), Generator0!()) Result0;
202
203 static assert(Result0.arity == 3);
204 static assert(is(Result0.ParameterTypeTuple == TypeTuple!(int, int, int)));
205 static assert(is(Result0.ReturnType == int));
206
207
208 template Generator1(size_t idx)
209 {
210 enum bool empty = idx >= 6;
211
212 static if(!empty)
213 {
214 alias front = TypeTuple!(int, ushort, long, double*, uint, real[])[idx];
215
216 template tail()
217 {
218 alias tail = Generator1!(idx+1);
219 }
220 }
221 }
222
223 alias argumentInfo!(((double* a) => a), Generator1!0) Result1;
224
225 static assert(Result1.arity == 1);
226 static assert(is(Result1.ParameterTypeTuple[0] == double*));
227 static assert(is(Result1.ReturnType == double*));
228 }
229
230
231 /**
232 */
233 template isVersion(string identifier)
234 {
235 mixin(mixin(Lstr!q{
236 version(%[identifier%])
237 enum isVersion = true;
238 else
239 enum isVersion = false;
240 }));
241 }
242
243 ///
244 unittest
245 {
246 version(Windows)
247 static assert(isVersion!"Windows");
248
249 version(OSX)
250 static assert(isVersion!"OSX");
251
252 version(linux)
253 static assert(isVersion!"linux");
254 }
255
256
257 /**
258 InputRangeのチェックを簡単にします
259
260 Examples:
261 --------------
262 isIRangeEx!(int[], int) == isInputRange!(int[]) && is(ElementType!(int[]) : int)
263 --------------
264 */
265 enum bool isIRange(T) = isInputRange!T;
266 enum bool isIRange(T, E) = isInputRange!T && is(ElementType!T : E);
267 enum bool isFRange(T) = isForwardRange!T;
268 enum bool isFRange(T, E) = isForwardRange!T && is(ElementType!T : E);
269 enum bool isBRange(T) = isBidirectionalRange!T;
270 enum bool isBRange(T, E) = isBidirectionalRange!T && is(ElementType!T : E);
271 enum bool isRRange(T) = isRandomAccessRange!T;
272 enum bool isRRange(T, E) = isRandomAccessRange!T && is(ElementType!T : E);