1 /** 2 This module is a container for a set of templates that are used across library and aren't bound to some specific module. 3 License: 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 28 Authors: 29 Alexandru Ermicioi 30 **/ 31 module aermicioi.util.traits.traits; 32 import std.traits; 33 import std.typetuple; 34 import std.algorithm; 35 import std.array; 36 37 public { 38 39 enum bool isHashable(T) = isBasicType!(T) || hasMember!(T, "toHash") || is(T == string) || is(T == enum); 40 enum bool isPublic(alias T) = __traits(getProtection, T) == "public"; 41 enum bool isPublic(T, string member) = isPublic!(__traits(getMember, T, member)); 42 enum bool isMethod(alias T, string member) = isSomeFunction!(__traits(getMember, T, member)); 43 enum bool evaluateMember(alias pred, T, string member) = pred!(__traits(getMember, T, member)); 44 enum bool isPropertyGetter(alias func) = (variadicFunctionStyle!func == Variadic.no) && (arity!func == 0) && (functionAttributes!func & FunctionAttribute.property); 45 enum bool isPropertySetter(alias func) = (variadicFunctionStyle!func == Variadic.no) && (arity!func == 1) && (functionAttributes!func & FunctionAttribute.property); 46 47 enum bool isValue(alias T) = is(typeof(T)) && !is(typeof(T) == void); 48 enum bool isValue(T) = false; 49 enum bool isType(alias T) = is(T); 50 enum bool isProperty(alias T) = 51 (isBasicType!(typeof(T)) || 52 isArray!(typeof(T)) || 53 isAssociativeArray!(typeof(T)) || 54 isAggregateType!(typeof(T)) || 55 is(typeof(T) == enum) 56 ) 57 && !isSomeFunction!T 58 && !isTemplate!T; 59 enum bool isProperty(alias T, string member) = isProperty!(getMember!(T, member)); 60 enum bool isTypeOrValue(alias T) = isValue!T || isType!T; 61 62 enum bool isConstructor(alias T) = isSomeFunction!T && (identifier!T == "__ctor"); 63 enum bool isDestructor(alias T) = isSomeFunction!T && (identifier!T == "__dtor"); 64 65 enum bool isConstructor(string T) = T == "__ctor"; 66 enum bool isDestructor(string T) = T == "__dtor"; 67 68 enum bool isTrue(bool state) = state == true; 69 alias isFalse = templateNot!isTrue; 70 71 template getProperty(alias T, string member) { 72 static if (isProperty!(T, member)) { 73 alias getProperty = member; 74 } else { 75 alias getProperty = TypeTuple!(); 76 } 77 } 78 79 template identifier(alias T) { 80 alias identifier = Identity!(__traits(identifier, T)); 81 } 82 83 template isEmpty(T...) { 84 enum bool isEmpty = T.length == 0; 85 } 86 87 template templateTryGetOverloads(alias symbol) { 88 static if (__traits(compiles, getOverloads!symbol)) { 89 90 alias templateTryGetOverloads = getOverloads!symbol; 91 } else { 92 93 alias templateTryGetOverloads = symbol; 94 } 95 } 96 97 template allMembers(alias Type) { 98 alias allMembers = TypeTuple!(__traits(allMembers, Type)); 99 } 100 101 template equals(alias first, alias second) { 102 static if (isValue!first && isValue!second && typeCompare!(first, second)) { 103 enum bool equals = first == second; 104 } else { 105 enum bool equals = typeCompare!(first, second); 106 } 107 } 108 109 template isClassOrStructMagicMethods(string member) { 110 enum bool isClassOrStructMagicMethods = equals!(member, "this") || equals!(member, "__ctor") || equals!(member, "__dtor"); 111 } 112 113 template staticMapWith(alias pred, alias Type, T...) { 114 static if (T.length > 1) { 115 alias staticMapWith = TypeTuple!(staticMapWith!(pred, Type, T[0 .. $ / 2]), staticMapWith!(pred, Type, T[$ / 2 .. $])); 116 } else static if (T.length == 1) { 117 alias staticMapWith = TypeTuple!(pred!(Type, T[0])); 118 } else { 119 alias staticMapWith = TypeTuple!(); 120 } 121 } 122 123 template getMember(alias T, string member) { 124 125 alias getMember = Identity!(__traits(getMember, T, member)); 126 } 127 128 template getOverloads(alias T, string member) { 129 130 alias getOverloads = AliasSeq!(__traits(getOverloads, T, member)); 131 } 132 133 template getOverloadsOrMember(alias T, string member) { 134 static if (isSomeFunction!(getMember!(T, member))) { 135 alias getOverloadsOrMember = getOverloads!(T, member); 136 } else { 137 alias getOverloadsOrMember = getMember!(T, member); 138 } 139 } 140 141 template typeCompare(alias first, alias second) { 142 static if (isValue!first) { 143 static if (isValue!second) { 144 145 enum bool typeCompare = is(typeof(first) : typeof(second)); 146 } else static if (isType!second) { 147 148 enum bool typeCompare = is(typeof(first) : second); 149 } else { 150 151 enum bool typeCompare = false; 152 } 153 } else static if (isType!first) { 154 static if (isValue!second) { 155 156 enum bool typeCompare = is(first : typeof(second)); 157 } else static if (isType!second) { 158 159 enum bool typeCompare = is(first : second); 160 } else { 161 162 enum bool typeCompare = false; 163 } 164 } 165 } 166 167 template typeCompare(first, second) { 168 enum bool typeCompare = is(first : second); 169 } 170 171 template typeOf(alias T) { 172 static if (isValue!T) { 173 alias typeOf = typeof(T); 174 } else { 175 alias typeOf = T; 176 } 177 } 178 179 template emptyIf(alias pred) { 180 template emptyIf(alias T) { 181 static if (pred!(T)) { 182 alias emptyIf = TypeTuple!(); 183 } else { 184 alias emptyIf = T; 185 } 186 } 187 } 188 189 template notEmptyIf(alias pred) { 190 template notEmptyIf(alias T) { 191 static if (pred!(T)) { 192 alias notEmptyIf = T; 193 } else { 194 alias notEmptyIf = TypeTuple!(); 195 } 196 } 197 } 198 199 template templateStringof(alias T) { 200 enum string templateStringof = T.stringof; 201 } 202 203 template isTemplate(alias T) { 204 enum bool isTemplate = __traits(isTemplate, T); 205 } 206 207 template execute(alias pred, Args...) { 208 static if (isTemplate!pred) { 209 alias execute = pred!Args; 210 } else static if (isSomeFunction!pred) { 211 auto execute = pred(Args); 212 } 213 } 214 215 template compiles(alias pred, args...) { 216 enum bool compiles = __traits(compiles, pred!args); 217 } 218 219 template pragmaMsg(args...) { 220 pragma(msg, args); 221 } 222 223 template getAttributes(alias symbol) { 224 alias getAttributes = TypeTuple!(__traits(getAttributes, symbol)); 225 } 226 227 template requiredArity(alias symbol) { 228 enum bool requiredArity = Filter!(partialPrefixed!(isType, void), ParameterDefaults!symbol); 229 } 230 231 template isType(Type, alias symbol) { 232 enum bool isType = is(symbol == Type); 233 } 234 235 template isType(Type, Second) { 236 enum bool isType = is(symbol == Type); 237 } 238 239 template isReferenceType(Type) { 240 enum bool isReferenceType = is(Type == class) || is(Type == interface); 241 } 242 243 template getProtection(alias T, string member) { 244 245 static if (__traits(compiles, __traits(getProtection, __traits(getMember, T, member)))) { 246 enum auto getProtection = __traits(getProtection, __traits(getMember, T, member)); 247 } else { 248 enum auto getProtection = "private"; 249 } 250 } 251 252 template getProtection(alias symbol) { 253 static if (__traits(compiles, __traits(getProtection, symbol))) { 254 enum auto getProtection = __traits(getProtection, symbol); 255 } else { 256 enum auto getProtection = "private"; 257 } 258 } 259 260 template isProtection(alias T, string member, string protection = "public") { 261 enum bool isProtection = getProtection!(T, member) == protection; 262 } 263 264 template isProtection(T, string member, string protection = "public") { 265 enum bool isProtection = getProtection!(T, member) == protection; 266 } 267 268 template isProtection(alias symbol, string protection) { 269 enum bool isProtection = getProtection!symbol == protection; 270 } 271 272 template getMembersWithProtection(T, string member, string protection = "public") { 273 import aermicioi.util.traits.partial : chain, eq; 274 275 alias getMembersWithProtection = Filter!( 276 chain!( 277 eq!"public", 278 getProtection 279 ), 280 __traits(getOverloads, T, member) 281 ); 282 } 283 284 template StringOf(alias Symbol) { 285 enum auto StringOf = Symbol.stringof; 286 } 287 288 template hasMembers(alias Symbol) { 289 enum bool hasMembers = __traits(compiles, __traits(allMembers, Symbol)); 290 } 291 292 template hasMembers(Symbol) { 293 enum bool hasMembers = __traits(compiles, __traits(allMembers, Symbol)); 294 } 295 296 template templateSpecs(alias T : Base!Args, alias Base, Args...) { 297 alias Template = Base; 298 alias Args = Args; 299 } 300 301 template templateSpecs(T : Base!Args, alias Base, Args...) { 302 alias Template = Base; 303 alias Args = Args; 304 } 305 306 template concat(args...) { 307 static if (args.length > 1) { 308 enum auto concat = args[0] ~ concat!(args[1 .. $]); 309 } else { 310 enum auto concat = args[0]; 311 } 312 } 313 314 template isField(T, string field) { 315 316 auto isField() { 317 import aermicioi.util.traits.partial : eq; 318 static if (Filter!(eq!field, FieldNameTuple!T).length > 0) { 319 return true; 320 } else { 321 return false; 322 } 323 } 324 } 325 326 enum bool isDerived(alias T, alias Z) = is(T : Z); 327 enum bool isEq(alias T, alias Z) = is(T == Z); 328 329 enum bool isStaticFunction(alias method) = Identity!(__traits(isStaticFunction, method)); 330 } 331 332 private { 333 alias Identity(alias A) = A; 334 } 335