1 /**
2  * Copyright: Copyright (c) 2010-2011 Jacob Carlborg.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: Jan 26, 2010
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module mambo.util.Traits;
8 
9 import Tango = tango.core.Traits;
10 import Phobos = std.traits;
11 
12 import mambo.core..string;
13 
14 ///
15 alias Tango.BaseTypeTupleOf BaseTypeTupleOf;
16 
17 ///
18 alias Tango.ParameterTupleOf ParameterTupleOf;
19 
20 ///
21 alias Tango.ReturnTypeOf ReturnTypeOf;
22 
23 /// Evaluates to true if $(D_PARAM T) is a primitive type.
24 template isPrimitive (T)
25 {
26 	enum bool isPrimitive = is(T == bool) ||
27 						is(T == byte) ||
28 						is(T == cdouble) ||
29 						//is(T == cent) ||
30 						is(T == cfloat) ||
31 						is(T == char) ||
32 						is(T == creal) ||
33 						is(T == dchar) ||
34 						is(T == double) ||
35 						is(T == float) ||
36 						is(T == idouble) ||
37 						is(T == ifloat) ||
38 						is(T == int) ||
39 						is(T == ireal) ||
40 						is(T == long) ||
41 						is(T == real) ||
42 						is(T == short) ||
43 						is(T == ubyte) ||
44 						//is(T == ucent) ||
45 						is(T == uint) ||
46 						is(T == ulong) ||
47 						is(T == ushort) ||
48 						is(T == wchar);
49 }
50 
51 /// Evaluates to true if $(D_PARAM T) is a character type.
52 template isChar (T)
53 {
54 	enum bool isChar = is(T == char) ||
55 		is(T == wchar) ||
56 		is(T == dchar) ||
57 		is(T == immutable(char)) ||
58 		is(T == immutable(wchar)) ||
59 		is(T == immutable(dchar));
60 }
61 
62 /// Evaluates to true if $(D_PARAM T) is a floating point type.
63 template isFloatingPoint (T)
64 {
65 	enum bool isFloatingPoint = is(T == float) || is(T == double) || is(T == real) ||
66 								 is(T == cfloat) || is(T == cdouble) || is(T == creal) ||
67 						  		 is(T == ifloat) || is(T == idouble) || is(T == ireal);
68 }
69 
70 /// Evaluates to true if $(D_PARAM T) is class.
71 template isClass (T)
72 {
73 	enum bool isClass = is(T == class);
74 }
75 
76 /// Evaluates to true if $(D_PARAM T) is an interface.
77 template isInterface (T)
78 {
79 	enum bool isInterface = is(T == interface);
80 }
81 
82 /// Evaluates to true if $(D_PARAM T) is a class or an interface.
83 template isObject (T)
84 {
85 	enum bool isObject = isClass!(T) || isInterface!(T);
86 }
87 
88 /// Evaluates to true if $(D_PARAM T) is a struct.
89 template isStruct (T)
90 {
91 	enum bool isStruct = is(T == struct);
92 }
93 
94 /// Evaluates to true if $(D_PARAM T) is a union.
95 template isUnion (T)
96 {
97 	enum bool isUnion = is(T == union);
98 }
99 
100 /// Evaluates to true if $(D_PARAM T) is an array.
101 template isArray (T)
102 {
103 	static if (is(T U : U[]))
104 		enum bool isArray = true;
105 
106 	else
107 		enum bool isArray = false;
108 }
109 
110 /// Evaluates to true if $(D_PARAM T) is a string.
111 template isString (T)
112 {
113 	enum bool isString = is(T : string) || is(T : wstring) || is(T : dstring);
114 }
115 
116 /// Evaluates to true if $(D_PARAM T) is a an associative array.
117 template isAssociativeArray (T)
118 {
119 	enum bool isAssociativeArray = is(typeof(T.init.values[0])[typeof(T.init.keys[0])] == T) ||
120 		is(AssociativeArray!(typeof(T.init.keys[0]), typeof(T.init.values[0])));
121 }
122 
123 /// Evaluates to true if $(D_PARAM T) is a pointer.
124 template isPointer (T)
125 {
126 	static if (is(T U : U*))
127 		enum bool isPointer = true;
128 
129 	else
130 		enum bool isPointer = false;
131 }
132 
133 /// Evaluates to true if $(D_PARAM T) is a function pointer.
134 template isFunctionPointer (T)
135 {
136 	enum bool isFunctionPointer = is(typeof(*T) == function);
137 }
138 
139 /// Evaluates to true if $(D_PARAM T) is an enum.
140 template isEnum (T)
141 {
142 	enum bool isEnum = is(T == enum);
143 }
144 
145 /// Evaluates to true if $(D_PARAM T) is an object or a pointer.
146 template isReference (T)
147 {
148 	enum bool isReference = isObject!(T) || isPointer!(T);
149 }
150 
151 /// Evaluates to true if $(D_PARAM T) is a typedef.
152 template isTypedef (T)
153 {
154 	enum bool isTypedef = is(T == typedef);
155 }
156 
157 /// Evaluates to true if $(D_PARAM T) is void.
158 template isVoid (T)
159 {
160 	enum bool isVoid = is(T == void);
161 }
162 
163 /// Evaluates the type of the element of the array.
164 template ElementTypeOfArray(T : T[])
165 {
166 	alias T ElementTypeOfArray;
167 }
168 
169 /// Evaluates to the type the pointer points to.
170 template BaseTypeOfPointer (T)
171 {
172 	static if (is(T U : U*))
173 		alias BaseTypeOfPointer!(U) BaseTypeOfPointer;
174 
175 	else
176 		alias T BaseTypeOfPointer;
177 }
178 
179 /// Evaluates to the base type of the typedef.
180 template BaseTypeOfTypedef (T)
181 {
182 	static if (is(T U == typedef))
183 		alias BaseTypeOfTypedef!(U) BaseTypeOfTypedef;
184 
185 	else
186 		alias T BaseTypeOfTypedef;
187 }
188 
189 /// Evaluates to the base type of the enum.
190 template BaseTypeOfEnum (T)
191 {
192 	static if (is(T U == enum))
193 		alias BaseTypeOfEnum!(U) BaseTypeOfEnum;
194 
195 	else
196 		alias T BaseTypeOfEnum;
197 }
198 
199 /// Evaluates to the key type of the associative array.
200 template KeyTypeOfAssociativeArray (T)
201 {
202 	static assert(isAssociativeArray!(T), "The type needs to be an associative array");
203 	alias typeof(T.init.keys[0]) KeyTypeOfAssociativeArray;
204 }
205 
206 /// Evaluates to the value type of the associative array.
207 template ValueTypeOfAssociativeArray (T)
208 {
209 	static assert(isAssociativeArray!(T), "The type needs to be an associative array");
210 	alias typeof(T.init.values[0]) ValueTypeOfAssociativeArray;
211 }
212 
213 template isPredicate (alias predicate, Args...)
214 {
215 	enum isPredicate = __traits(compiles, {
216 		bool r = predicate(Args.init);
217 	});
218 }
219 
220 template isAssociativeArrayPredicate (alias predicate, T)
221 {
222 	enum isAssociativeArrayPredicate = isPredicate!(predicate,
223 		KeyTypeOfAssociativeArray!(T),
224 		ValueTypeOfAssociativeArray!(T));
225 }
226 
227 /// Unqualifies the given type, i.e. removing const, immutable and so on.
228 alias Phobos.Unqual Unqual;
229 
230 /// Evaluates to true if the given symbol is a type.
231 template isType (alias symbol)
232 {
233 	enum isType = __traits(compiles, expectType!(symbol));
234 }
235 
236 private template expectType (T) {}
237 
238 /**
239  * Evaluates to the type of the given expression or type. The built-in $(D_KEYWORD typeof)
240  * only accepts expressions, not types. If given a type, this will just evaluate to the given
241  * type as is.
242  */
243 template TypeOf (alias expr)
244 {
245 	static if (isType!(expr))
246 		alias expr TypeOf;
247 
248 	else
249 		alias typeof(expr) TypeOf;
250 }
251 
252 /// Evaluates to true if the given argument is a symbol.
253 template isSymbol (alias arg)
254 {
255 	enum isSymbol = __traits(compiles, __traits(getAttributes, arg));
256 }