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 }