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 }