1 /*******************************************************************************
2
3 Traits specializing in finding out indirections within compound
4 types.
5
6 NB: because this module is often used as purely compile-time dependency it
7 used built-in asserts instead of `ocean.core.Test` to reduce amount of
8 cyclic imports. `ocean.meta` modules in general are not supposed to
9 import anything outside of `ocean.meta`.
10
11 Copyright:
12 Copyright (c) 2017 dunnhumby Germany GmbH.
13 All rights reserved.
14
15 License:
16 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
17 Alternatively, this file may be distributed under the terms of the Tango
18 3-Clause BSD License (see LICENSE_BSD.txt for details).
19
20 *******************************************************************************/
21
22 module ocean.meta.traits.Indirections;
23
24 import ocean.meta.types.ReduceType;
25 import ocean.meta.types.Arrays;
26 import ocean.meta.traits.Basic;
27
28 version (unittest)
29 {
30 import ocean.meta.types.Qualifiers;
31 }
32
33 /*******************************************************************************
34
35 Evaluates to true if a variable of any type in T is a reference type or has
36 members or elements of reference types. References are
37 - dynamic and associative arrays,
38 - pointers (including function pointers) and delegates,
39 - classes.
40
41 Types that are not suitable to declare a variable, i.e. ``void`` and
42 function types (the base types of function pointers) are not references.
43
44 If T is empty then the result is false.
45
46 Params:
47 T = types to check (with no type the result is false)
48
49 *******************************************************************************/
50
51 public template hasIndirections ( T... )
52 {
53 static immutable hasIndirections = ReduceType!(T, HasIndirectionsReducer);
54 }
55
56 ///
57 unittest
58 {
59 static assert (!hasIndirections!(int));
60 static assert ( hasIndirections!(int[int]));
61 static assert (!hasIndirections!(void));
62
63 static struct S
64 {
65 union
66 {
67 int[] arr;
68 double f;
69 }
70 }
71
72 static assert ( hasIndirections!(S[5]));
73 }
74
75 unittest
76 {
77 static struct S1 { }
78
79 static struct S2
80 {
81 const(S1)[5] a;
82
83 union
84 {
85 immutable(int)[2][2] x;
86 S1 y;
87 }
88 }
89
90 static assert (!hasIndirections!(S2));
91
92 static struct S3
93 {
94 void delegate(int) x;
95 }
96
97 static assert ( hasIndirections!(S3));
98
99 static struct S4
100 {
101 immutable(int[])[10] x;
102 }
103
104 static assert ( hasIndirections!(S4));
105 }
106
107 private struct HasIndirectionsReducer
108 {
109 alias bool Result;
110
111 Result visit ( T ) ( )
112 {
113 return isReferenceType!(T);
114 }
115 }
116
117 /*******************************************************************************
118
119 Checks if T or any of its subtypes is a multi-dimensional dynamic array.
120
121 Params:
122 T = type to check
123
124 Returns:
125 true if T or any of its subtypes is a multi-dimensional dynamic array or
126 false otherwise.
127
128 *******************************************************************************/
129
130 public template containsMultiDimensionalDynamicArrays ( T )
131 {
132 static immutable containsMultiDimensionalDynamicArrays =
133 ReduceType!(T, MultiDimArraysReducer);
134 }
135
136 ///
137 unittest
138 {
139 static assert (!containsMultiDimensionalDynamicArrays!(int));
140 static assert ( containsMultiDimensionalDynamicArrays!(int[][]));
141
142 static struct S
143 {
144 int[][] arr;
145 }
146
147 static assert ( containsMultiDimensionalDynamicArrays!(S));
148 }
149
150 private struct MultiDimArraysReducer
151 {
152 alias bool Result;
153
154 Result visit ( T ) ( )
155 {
156 static if (isArrayType!(T) == ArrayKind.Dynamic)
157 return isArrayType!(ElementTypeOf!(T)) == ArrayKind.Dynamic;
158 else
159 return false;
160 }
161 }
162
163 unittest
164 {
165 static assert(!containsMultiDimensionalDynamicArrays!(int));
166 static assert(!containsMultiDimensionalDynamicArrays!(int[ ]));
167 static assert(!containsMultiDimensionalDynamicArrays!(int[3]));
168
169 static assert( containsMultiDimensionalDynamicArrays!(int[ ][ ]));
170 static assert(!containsMultiDimensionalDynamicArrays!(int[3][ ]));
171 static assert(!containsMultiDimensionalDynamicArrays!(int[ ][3]));
172 static assert(!containsMultiDimensionalDynamicArrays!(int[3][3]));
173
174 static assert( containsMultiDimensionalDynamicArrays!(int[ ][ ][ ]));
175 static assert( containsMultiDimensionalDynamicArrays!(int[3][ ][ ]));
176 static assert(!containsMultiDimensionalDynamicArrays!(int[ ][3][ ]));
177 static assert(!containsMultiDimensionalDynamicArrays!(int[3][3][ ]));
178 static assert( containsMultiDimensionalDynamicArrays!(int[ ][ ][3]));
179 static assert(!containsMultiDimensionalDynamicArrays!(immutable(int[3])[ ][3]));
180 static assert(!containsMultiDimensionalDynamicArrays!(int[ ][3][3]));
181 static assert(!containsMultiDimensionalDynamicArrays!(int[3][3][3]));
182
183 static assert(!containsMultiDimensionalDynamicArrays!(void));
184 static assert(!containsMultiDimensionalDynamicArrays!(void[]));
185 static assert( containsMultiDimensionalDynamicArrays!(const(void[])[]));
186 static assert(!containsMultiDimensionalDynamicArrays!(void[][3]));
187
188 struct A
189 {
190 int x;
191 char[] y;
192 float[][][3][] z;
193 }
194
195 struct B
196 {
197 A[] a;
198 }
199
200 static assert(containsMultiDimensionalDynamicArrays!(A));
201
202 struct C
203 {
204 int x;
205 float[][3][] y;
206 const(char)[] z;
207 }
208
209 static assert(!containsMultiDimensionalDynamicArrays!(C));
210 }
211
212 /*******************************************************************************
213
214 Checks if T or any of its subtypes is a dynamic array.
215
216 Params:
217 T = type to check
218
219 Returns:
220 true if T or any of its subtypes is a dynamic array or
221 false otherwise.
222
223 *******************************************************************************/
224
225 public template containsDynamicArray ( T )
226 {
227 static immutable containsDynamicArray =
228 ReduceType!(T, DynArrayReducer);
229 }
230
231 ///
232 unittest
233 {
234 static assert (!containsDynamicArray!(void));
235
236 static struct S
237 {
238 int[] x;
239 }
240 static assert ( containsDynamicArray!(const(S)));
241
242 static struct S2
243 {
244 struct Arr { const(int[]) x; }
245 Arr[3][4] arr;
246 }
247
248 static assert( containsDynamicArray!(immutable(S2)));
249 }
250
251 private struct DynArrayReducer
252 {
253 alias bool Result;
254
255 Result visit ( T ) ( )
256 {
257 return isArrayType!(T) == ArrayKind.Dynamic;
258 }
259 }