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 orange.util.Traits;
8 
9 import orange.serialization.Serializable;
10 import orange.serialization.archives.Archive;
11 import orange.util._;
12 
13 
14 import Phobos = std.traits;
15 
16 ///
17 alias Phobos.BaseTypeTuple BaseTypeTupleOf;
18 
19 /// Evaluates to true if $(D_PARAM T) is a primitive type.
20 template isPrimitive (T)
21 {
22     enum bool isPrimitive = is(T == bool) ||
23                         is(T == byte) ||
24                         is(T == cdouble) ||
25                         //is(T == cent) ||
26                         is(T == cfloat) ||
27                         is(T == char) ||
28                         is(T == creal) ||
29                         is(T == dchar) ||
30                         is(T == double) ||
31                         is(T == float) ||
32                         is(T == idouble) ||
33                         is(T == ifloat) ||
34                         is(T == int) ||
35                         is(T == ireal) ||
36                         is(T == long) ||
37                         is(T == real) ||
38                         is(T == short) ||
39                         is(T == ubyte) ||
40                         //is(T == ucent) ||
41                         is(T == uint) ||
42                         is(T == ulong) ||
43                         is(T == ushort) ||
44                         is(T == wchar);
45 }
46 
47 /// Evaluates to true if $(D_PARAM T) is a floating point type.
48 template isFloatingPoint (T)
49 {
50     enum bool isFloatingPoint = is(T == float) || is(T == double) || is(T == real) ||
51                                  is(T == cfloat) || is(T == cdouble) || is(T == creal) ||
52                                    is(T == ifloat) || is(T == idouble) || is(T == ireal);
53 }
54 
55 /// Evaluates to true if $(D_PARAM T) is class.
56 template isClass (T)
57 {
58     enum bool isClass = is(T == class);
59 }
60 
61 /// Evaluates to true if $(D_PARAM T) is an interface.
62 template isInterface (T)
63 {
64     enum bool isInterface = is(T == interface);
65 }
66 
67 /// Evaluates to true if $(D_PARAM T) is a class or an interface.
68 template isObject (T)
69 {
70     enum bool isObject = isClass!(T) || isInterface!(T);
71 }
72 
73 /// Evaluates to true if $(D_PARAM T) is a struct.
74 template isStruct (T)
75 {
76     enum bool isStruct = is(T == struct);
77 }
78 
79 /// Evaluates to true if $(D_PARAM T) is an array.
80 template isArray (T)
81 {
82     static if (is(T U : U[]))
83         enum bool isArray = true;
84 
85     else
86         enum bool isArray = false;
87 }
88 
89 /// Evaluates to true if $(D_PARAM T) is a static array.
90 enum isStaticArray (T) = is(T : U[n], U, size_t n);
91 
92 /// Evaluates to true if $(D_PARAM T) is a string.
93 template isString (T)
94 {
95     enum bool isString = is(T : string) || is(T : wstring) || is(T : dstring);
96 }
97 
98 /// Evaluates to true if $(D_PARAM T) is a an associative array.
99 template isAssociativeArray (T)
100 {
101     enum bool isAssociativeArray = is(typeof(T.init.values[0])[typeof(T.init.keys[0])] == T);
102 }
103 
104 /// Evaluates to true if $(D_PARAM T) is a pointer.
105 template isPointer (T)
106 {
107     static if (is(T U : U*))
108         enum bool isPointer = true;
109 
110     else
111         enum bool isPointer = false;
112 }
113 
114 /// Evaluates to true if $(D_PARAM T) is a function pointer.
115 template isFunctionPointer (T)
116 {
117     enum bool isFunctionPointer = is(typeof(*T) == function);
118 }
119 
120 /// Evaluates to true if $(D_PARAM T) is an enum.
121 template isEnum (T)
122 {
123     enum bool isEnum = is(T == enum);
124 }
125 
126 /// Evaluates to true if $(D_PARAM T) is an object or a pointer.
127 template isReference (T)
128 {
129     enum bool isReference = isObject!(T) || isPointer!(T);
130 }
131 
132 /// Evaluates to true if $(D_PARAM T) is void.
133 template isVoid (T)
134 {
135     enum bool isVoid = is(T == void);
136 }
137 
138 /// Evaluates the type of the element of the array.
139 template ElementTypeOfArray(T : T[])
140 {
141     alias T ElementTypeOfArray;
142 }
143 
144 /// Evaluates to the type the pointer points to.
145 template BaseTypeOfPointer (T)
146 {
147     static if (is(T U : U*))
148         alias BaseTypeOfPointer!(U) BaseTypeOfPointer;
149 
150     else
151         alias T BaseTypeOfPointer;
152 }
153 
154 /// Evaluates to the base type of the enum.
155 template BaseTypeOfEnum (T)
156 {
157     static if (is(T U == enum))
158         alias BaseTypeOfEnum!(U) BaseTypeOfEnum;
159 
160     else
161         alias T BaseTypeOfEnum;
162 }
163 
164 /// Evaluates to the key type of the associative array.
165 template KeyTypeOfAssociativeArray (T)
166 {
167     static assert(isAssociativeArray!(Unqual!(T)), "The type needs to be an associative array");
168     alias typeof(T.init.keys[0]) KeyTypeOfAssociativeArray;
169 }
170 
171 /// Evaluates to the value type of the associative array.
172 template ValueTypeOfAssociativeArray (T)
173 {
174     static assert(isAssociativeArray!(Unqual!(T)), "The type needs to be an associative array");
175     alias typeof(T.init.values[0]) ValueTypeOfAssociativeArray;
176 }
177 
178 /// Evaluates to the type of the data type.
179 template TypeOfDataType (T)
180 {
181     alias T.DataType TypeOfDataType;
182 }
183 
184 /// Unqualifies the given type, i.e. removing const, immutable and so on.
185 alias Phobos.Unqual Unqual;
186 
187 /// Evaluates to true if the given symbol is a type.
188 template isType (alias symbol)
189 {
190     enum isType = __traits(compiles, expectType!(symbol));
191 }
192 
193 private template expectType (T) {}
194 
195 /**
196  * Evaluates to the type of the given expression or type. The built-in $(D_KEYWORD typeof)
197  * only accepts expressions, not types. If given a type, this will just evaluate to the given
198  * type as is.
199  */
200 template TypeOf (alias expr)
201 {
202     static if (isType!(expr))
203         alias expr TypeOf;
204 
205     else
206         alias typeof(expr) TypeOf;
207 }
208 
209 /// Evaluates to true if the given argument is a symbol.
210 template isSymbol (alias arg)
211 {
212     enum isSymbol = __traits(compiles, __traits(getAttributes, arg));
213 }