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