1 /**
2 * This module is contains utility templates used by the other modules in
3 * $(CALIB_ABSTRACT).
4 *
5 * Take a look the various modules in $(CALIB_ABSTRACT) for usage examples.
6 */
7 
8 module caLib_abstract.util;
9 
10 
11 
12 /**
13 * return `true` if `T` has an `alias` named `CellStateType`. `False` if not
14 */
15 template hasCellStateType(T)
16 {
17 	enum hasCellStateType =
18 		is(T.CellStateType) &&
19 		is(T.init.CellStateType);
20 }
21 
22 ///
23 unittest
24 {
25 	struct Foo {
26 		alias CellStateType = void;
27 	}
28 
29 	static assert( hasCellStateType!Foo);
30 	static assert(!hasCellStateType!string);
31 }
32 
33 
34 
35 /**
36 * Return true all of the given arguments are types that can be impliciltly
37 * converted to one-another
38 *
39 * It is unclear if it behaves the way it should in all cases and should
40 * not be used .
41 */
42 deprecated template isCellStateTypesCompatible(T...)
43 {
44 	static assert(T.length != 0);
45 
46 	static if(T.length == 1)
47 	{
48 		enum isCellStateTypesCompatible = true;
49 	}
50 	else
51 	{
52 		enum isCellStateTypesCompatible =
53 			__traits(compiles, (() {
54 						static assert(is(T[0] : T[1]));
55 					})() ) &&
56 			isDimensionsCompatible!(T[1..$]);
57 	}
58 }
59 
60 ///
61 unittest
62 {
63 	static assert( isCellStateTypesCompatible!(int));
64 	static assert( isCellStateTypesCompatible!(int, uint));
65 	static assert(!isCellStateTypesCompatible!(int, string));
66 }
67 
68 
69 
70 /**
71 * return `true` if `T` has an `alias` named `DisplayValueType`. `False` if not
72 */
73 template hasDisplayValueType(T)
74 {
75 	enum hasDisplayValueType =
76 		is(T.DisplayValueType) &&
77 		is(T.init.DisplayValueType);
78 }
79 
80 ///
81 unittest
82 {
83 	struct Foo {
84 		alias DisplayValueType = uint;
85 	}
86 
87 	static assert( hasDisplayValueType!Foo);
88 	static assert(!hasDisplayValueType!string);
89 }
90 
91 
92 
93 /**
94 * Return true all of the given arguments are types that can be impliciltly
95 * converted to one-another
96 *
97 * It is unclear if it behaves the way it should in all cases and should
98 * not be used .
99 */
100 deprecated template isDisplayValueTypesCompatible(T...)
101 {
102 	static assert(T.length != 0);
103 
104 	static if(T.length == 1)
105 	{
106 		enum isCellStateTypesCompatible = true;
107 	}
108 	else
109 	{
110 		enum isCellStateTypesCompatible =
111 			__traits(compiles, (() {
112 						static assert(is(T[0] : T[1]));
113 					})() ) &&
114 			isDimensionsCompatible!(T[1..$]);
115 	}
116 }
117 
118 ///
119 unittest
120 {
121 	static assert( isCellStateTypesCompatible!(int));
122 	static assert( isCellStateTypesCompatible!(int, uint));
123 	static assert(!isCellStateTypesCompatible!(int, string));
124 }
125 
126 
127 
128 /**
129 * return `true` if `T` has an `enum uint` named `Dimension`. `False` if not
130 */
131 template hasDimension(T)
132 {
133 	enum hasDimension =
134 		is(typeof(T.Dimension) : int) &&
135 		is(typeof(T.init.Dimension) : int);
136 }
137 
138 ///
139 unittest
140 {
141 	struct Foo {
142 		static immutable int Dimension = 0;
143 	}
144 
145 	static assert( hasDimension!Foo);
146 	static assert(!hasDimension!int);
147 }
148 
149 
150 
151 /**
152 * Return true all of the given arguments are types that can be impliciltly
153 * converted to one-another
154 *
155 * It is unclear if it behaves the way it should in all cases and should
156 * not be used .
157 */
158 deprecated template isDimensionsCompatible(T...)
159 {
160 	static assert(T.length != 0);
161 
162 	static if(T.length == 1)
163 	{
164 		enum isDimensionsCompatible = true;
165 	}
166 	else
167 	{
168 		enum isDimensionsCompatible =
169 			__traits(compiles, (() {
170 						static assert(T[0] == T[1]);
171 					})() ) &&
172 			isDimensionsCompatible!(T[1..$]);
173 			
174 	}
175 }
176 
177 ///
178 unittest
179 {
180 	static assert( isDimensionsCompatible!(0));
181 	static assert( isDimensionsCompatible!(0, 0u));
182 	static assert( isDimensionsCompatible!(0, 0u, byte(0)));
183 	static assert(!isDimensionsCompatible!(0, 0.1f));
184 }
185 
186 
187 
188 /**
189 * return `true` if `T` has an `alias` named `NeighbourhoodType`. `False` if not
190 *
191 * return `true` if `T` has an `alias` named `NeighbourhoodType`. `False` if not.
192 * $(B Note) that `NeighbourhoodType` need not actually be a neighbourhood.
193 * It can be any type
194 */
195 template hasNeighbourhoodType(T)
196 {
197 	enum hasNeighbourhoodType =
198 		is(T.NeighbourhoodType) &&
199 		is(T.init.NeighbourhoodType);
200 }
201 
202 ///
203 unittest
204 {
205 	struct Foo {
206 		alias NeighbourhoodType = char; //car is is not a neighbourhood
207 	}
208 
209 	static assert( hasNeighbourhoodType!Foo); //but this return true anyways
210 	static assert(!hasNeighbourhoodType!int);
211 }