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