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 struct FuncAttr 41 { 42 static: 43 /* 44 proxy std.traits.functionAttributes 45 */ 46 private template hasFA(FunctionAttribute fa, func...) 47 if(func.length == 1 && isCallable!func) 48 { 49 enum bool hasFA = !!(functionAttributes!func & fa); 50 } 51 52 53 /** 54 true if func is pure 55 */ 56 template isPure(func...) 57 if(func.length == 1 && isCallable!func) 58 { 59 enum isPure = hasFA!(FunctionAttribute.pure_, func); 60 } 61 62 unittest 63 { 64 void foo() pure {} 65 void bar() {} 66 67 static assert(isPure!foo); 68 static assert(!isPure!bar); 69 70 static void hoge() pure {} 71 static void hage() {} 72 73 static assert(isPure!hoge); 74 static assert(!isPure!hage); 75 } 76 77 78 /** 79 true if func is nothrow 80 */ 81 template isNothrow(func...) 82 if(func.length == 1 && isCallable!func) 83 { 84 enum isNothrow = hasFA!(FunctionAttribute.nothrow_, func); 85 } 86 87 88 /** 89 true if func is ref 90 */ 91 template isRef(func...) 92 if(func.length == 1 && isCallable!func) 93 { 94 enum isNothrow = hasFA!(FunctionAttribute.ref_, func); 95 } 96 97 98 /** 99 true if func is property 100 */ 101 template isProperty(func...) 102 if(func.length == 1 && isCallable!func) 103 { 104 enum isNothrow = hasFA!(FunctionAttribute.property_, func); 105 } 106 107 108 /** 109 true if func is trusted 110 */ 111 template isTrusted(func...) 112 if(func.length == 1 && isCallable!func) 113 { 114 enum isNothrow = hasFA!(FunctionAttribute.trusted, func); 115 } 116 } 117 118 119 /** 120 This template return arity of a function. 121 122 Example: 123 --- 124 template Generator0(size_t N) 125 { 126 alias TypeNuple!(int, N) Generator0; 127 } 128 129 alias argumentInfo!(( (a, b, c) => a), Generator0) Result0; 130 131 static assert(Result0.arity == 3); 132 static assert(Result0.endN == 3); 133 static assert(is(Result0.ParameterTypeTuple == Generator0!3)); 134 static assert(is(Result0.ReturnType == int)); 135 136 137 template Generator1(size_t N) 138 { 139 alias TypeTuple!(int, ushort, long, double*, uint, real[])[N] Generator1; 140 } 141 142 static assert(Result1.arity == 1); 143 static assert(Result1.endN == 3); 144 static assert(is(Result1.ParameterTypeTuple == double*)); 145 static assert(is(Result1.ReturnType == double*)); 146 --- 147 148 Authors: Kazuki Komatsu(k3_kaimu) 149 */ 150 template argumentInfo(alias templateFun, alias ParamGenRange) 151 if(isTemplateRange!ParamGenRange && !ParamGenRange.empty) 152 { 153 template checkArity(alias pgr) 154 { 155 static if(!pgr.empty) 156 { 157 static if(is(typeof(templateFun(pgr.front.init)))) 158 alias checkArity = pgr.front; 159 else 160 alias checkArity = checkArity!(pgr.tail!()); 161 } 162 else 163 static assert(0, "arity Error : " ~ templateFun.stringof); 164 } 165 166 167 alias ParameterTypeTuple = TypeTuple!(checkArity!(ParamGenRange)); 168 enum size_t arity = ParameterTypeTuple.length; 169 alias ReturnType = typeof(templateFun(ParameterTypeTuple.init)); 170 } 171 172 unittest 173 { 174 template Generator0(T...) 175 { 176 enum bool empty = false; 177 178 alias front = T; 179 180 template tail() 181 { 182 alias tail = Generator0!(T, int); 183 } 184 } 185 186 alias argumentInfo!(( (a, b, c) => a), Generator0!()) Result0; 187 188 static assert(Result0.arity == 3); 189 static assert(is(Result0.ParameterTypeTuple == TypeTuple!(int, int, int))); 190 static assert(is(Result0.ReturnType == int)); 191 192 193 template Generator1(size_t idx) 194 { 195 enum bool empty = idx >= 6; 196 197 static if(!empty) 198 { 199 alias front = TypeTuple!(int, ushort, long, double*, uint, real[])[idx]; 200 201 template tail() 202 { 203 alias tail = Generator1!(idx+1); 204 } 205 } 206 } 207 208 alias argumentInfo!(((double* a) => a), Generator1!0) Result1; 209 210 static assert(Result1.arity == 1); 211 static assert(is(Result1.ParameterTypeTuple[0] == double*)); 212 static assert(is(Result1.ReturnType == double*)); 213 } 214 215 216 /** 217 */ 218 template isVersion(string identifier) 219 { 220 mixin(mixin(Lstr!q{ 221 version(%[identifier%]) 222 enum isVersion = true; 223 else 224 enum isVersion = false; 225 })); 226 } 227 228 /// 229 unittest 230 { 231 version(Windows) 232 static assert(isVersion!"Windows"); 233 234 version(OSX) 235 static assert(isVersion!"OSX"); 236 237 version(linux) 238 static assert(isVersion!"linux"); 239 } 240 241 242 /** 243 InputRangeのチェックを簡単にします 244 245 Examples: 246 -------------- 247 isIRangeEx!(int[], int) == isInputRange!(int[]) && is(ElementType!(int[]) : int) 248 -------------- 249 */ 250 enum bool isIRange(T) = isInputRange!T; 251 enum bool isIRange(T, E) = isInputRange!T && is(ElementType!T : E); 252 enum bool isFRange(T) = isForwardRange!T; 253 enum bool isFRange(T, E) = isForwardRange!T && is(ElementType!T : E); 254 enum bool isBRange(T) = isBidirectionalRange!T; 255 enum bool isBRange(T, E) = isBidirectionalRange!T && is(ElementType!T : E); 256 enum bool isRRange(T) = isRandomAccessRange!T; 257 enum bool isRRange(T, E) = isRandomAccessRange!T && is(ElementType!T : E);