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.traits,
36        std.typetuple;
37 
38 
39 struct FuncAttr 
40 {
41   static:
42     /*
43     proxy std.traits.functionAttributes
44     */
45     private template hasFA(FunctionAttribute fa, func...)
46     if(func.length == 1 && isCallable!func)
47     {
48         enum bool hasFA = !!(functionAttributes!func & fa);
49     }
50 
51 
52     /**
53     true if func is pure
54     */
55     template isPure(func...)
56     if(func.length == 1 && isCallable!func)
57     {
58         enum isPure = hasFA!(FunctionAttribute.pure_, func);
59     }
60 
61     unittest
62     {
63         void foo() pure {}
64         void bar() {}
65 
66         static assert(isPure!foo);
67         static assert(!isPure!bar);
68 
69         static void hoge() pure {}
70         static void hage() {}
71 
72         static assert(isPure!hoge);
73         static assert(!isPure!hage);
74     }
75 
76 
77     /**
78     true if func is nothrow
79     */
80     template isNothrow(func...)
81     if(func.length == 1 && isCallable!func)
82     {
83         enum isNothrow = hasFA!(FunctionAttribute.nothrow_, func);
84     }
85 
86 
87     /**
88     true if func is ref
89     */
90     template isRef(func...)
91     if(func.length == 1 && isCallable!func)
92     {
93         enum isNothrow = hasFA!(FunctionAttribute.ref_, func);
94     }
95 
96 
97     /**
98     true if func is property
99     */
100     template isProperty(func...)
101     if(func.length == 1 && isCallable!func)
102     {
103         enum isNothrow = hasFA!(FunctionAttribute.property_, func);
104     }
105 
106 
107     /**
108     true if func is trusted
109     */
110     template isTrusted(func...)
111     if(func.length == 1 && isCallable!func)
112     {
113         enum isNothrow = hasFA!(FunctionAttribute.trusted, func);
114     }
115 }
116 
117 
118 /**
119 This template return arity of a function.
120 
121 Example:
122 ---
123 template Generator0(size_t N)
124 {
125     alias TypeNuple!(int, N) Generator0;
126 }
127 
128 alias argumentInfo!(( (a, b, c) => a), Generator0) Result0;
129 
130 static assert(Result0.arity == 3);
131 static assert(Result0.endN == 3);
132 static assert(is(Result0.ParameterTypeTuple == Generator0!3));
133 static assert(is(Result0.ReturnType == int));
134 
135 
136 template Generator1(size_t N)
137 {
138     alias TypeTuple!(int, ushort, long, double*, uint, real[])[N] Generator1;
139 }
140 
141 static assert(Result1.arity == 1);
142 static assert(Result1.endN == 3);
143 static assert(is(Result1.ParameterTypeTuple == double*));
144 static assert(is(Result1.ReturnType == double*));
145 ---
146 
147 Authors: Kazuki Komatsu(k3_kaimu)
148 */
149 template argumentInfo(alias templateFun, alias ParamGenRange)
150 if(isTemplateRange!ParamGenRange && !ParamGenRange.empty)
151 {
152     template checkArity(alias pgr)
153     {
154         static if(!pgr.empty)
155         {
156             static if(is(typeof(templateFun(pgr.front.init))))
157                 alias checkArity = pgr.front;
158             else
159                 alias checkArity = checkArity!(pgr.tail!());
160         }
161         else
162             static assert(0, "arity Error : " ~ templateFun.stringof);
163     }
164 
165 
166     alias ParameterTypeTuple = TypeTuple!(checkArity!(ParamGenRange));
167     enum size_t arity = ParameterTypeTuple.length;
168     alias ReturnType = typeof(templateFun(ParameterTypeTuple.init));
169 }
170 
171 unittest 
172 {
173     template Generator0(T...)
174     {
175         enum bool empty = false;
176 
177         alias front = T;
178 
179         template tail()
180         {
181             alias tail = Generator0!(T, int);
182         }
183     }
184 
185     alias argumentInfo!(( (a, b, c) => a), Generator0!()) Result0;
186 
187     static assert(Result0.arity == 3);
188     static assert(is(Result0.ParameterTypeTuple == TypeTuple!(int, int, int)));
189     static assert(is(Result0.ReturnType == int));
190 
191 
192     template Generator1(size_t idx)
193     {
194         enum bool empty = idx >= 6;
195 
196       static if(!empty)
197       {
198         alias front = TypeTuple!(int, ushort, long, double*, uint, real[])[idx];
199 
200         template tail()
201         {
202             alias tail = Generator1!(idx+1);
203         }
204       }
205     }
206 
207     alias argumentInfo!(((double* a) => a), Generator1!0) Result1;
208 
209     static assert(Result1.arity == 1);
210     static assert(is(Result1.ParameterTypeTuple[0] == double*));
211     static assert(is(Result1.ReturnType == double*));
212 }