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);