| 1 |
/** |
|---|
| 2 |
* The traits module defines tools useful for obtaining detailed compile-time |
|---|
| 3 |
* information about a type. Please note that the mixed naming scheme used in |
|---|
| 4 |
* this module is intentional. Templates which evaluate to a type follow the |
|---|
| 5 |
* naming convention used for types, and templates which evaluate to a value |
|---|
| 6 |
* follow the naming convention used for functions. |
|---|
| 7 |
* |
|---|
| 8 |
* Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved. |
|---|
| 9 |
* License: BSD style: $(LICENSE) |
|---|
| 10 |
* Authors: Sean Kelly, Fawzi Mohamed |
|---|
| 11 |
*/ |
|---|
| 12 |
module tango.core.Traits; |
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
/** |
|---|
| 16 |
* Evaluates to true if T is char, wchar, or dchar. |
|---|
| 17 |
*/ |
|---|
| 18 |
template isCharType( T ) |
|---|
| 19 |
{ |
|---|
| 20 |
const bool isCharType = is( T == char ) || |
|---|
| 21 |
is( T == wchar ) || |
|---|
| 22 |
is( T == dchar ); |
|---|
| 23 |
} |
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
/** |
|---|
| 27 |
* Evaluates to true if T is a signed integer type. |
|---|
| 28 |
*/ |
|---|
| 29 |
template isSignedIntegerType( T ) |
|---|
| 30 |
{ |
|---|
| 31 |
const bool isSignedIntegerType = is( T == byte ) || |
|---|
| 32 |
is( T == short ) || |
|---|
| 33 |
is( T == int ) || |
|---|
| 34 |
is( T == long )/+|| |
|---|
| 35 |
is( T == cent )+/; |
|---|
| 36 |
} |
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
/** |
|---|
| 40 |
* Evaluates to true if T is an unsigned integer type. |
|---|
| 41 |
*/ |
|---|
| 42 |
template isUnsignedIntegerType( T ) |
|---|
| 43 |
{ |
|---|
| 44 |
const bool isUnsignedIntegerType = is( T == ubyte ) || |
|---|
| 45 |
is( T == ushort ) || |
|---|
| 46 |
is( T == uint ) || |
|---|
| 47 |
is( T == ulong )/+|| |
|---|
| 48 |
is( T == ucent )+/; |
|---|
| 49 |
} |
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
/** |
|---|
| 53 |
* Evaluates to true if T is a signed or unsigned integer type. |
|---|
| 54 |
*/ |
|---|
| 55 |
template isIntegerType( T ) |
|---|
| 56 |
{ |
|---|
| 57 |
const bool isIntegerType = isSignedIntegerType!(T) || |
|---|
| 58 |
isUnsignedIntegerType!(T); |
|---|
| 59 |
} |
|---|
| 60 |
|
|---|
| 61 |
|
|---|
| 62 |
/** |
|---|
| 63 |
* Evaluates to true if T is a real floating-point type. |
|---|
| 64 |
*/ |
|---|
| 65 |
template isRealType( T ) |
|---|
| 66 |
{ |
|---|
| 67 |
const bool isRealType = is( T == float ) || |
|---|
| 68 |
is( T == double ) || |
|---|
| 69 |
is( T == real ); |
|---|
| 70 |
} |
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 |
/** |
|---|
| 74 |
* Evaluates to true if T is a complex floating-point type. |
|---|
| 75 |
*/ |
|---|
| 76 |
template isComplexType( T ) |
|---|
| 77 |
{ |
|---|
| 78 |
const bool isComplexType = is( T == cfloat ) || |
|---|
| 79 |
is( T == cdouble ) || |
|---|
| 80 |
is( T == creal ); |
|---|
| 81 |
} |
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
/** |
|---|
| 85 |
* Evaluates to true if T is an imaginary floating-point type. |
|---|
| 86 |
*/ |
|---|
| 87 |
template isImaginaryType( T ) |
|---|
| 88 |
{ |
|---|
| 89 |
const bool isImaginaryType = is( T == ifloat ) || |
|---|
| 90 |
is( T == idouble ) || |
|---|
| 91 |
is( T == ireal ); |
|---|
| 92 |
} |
|---|
| 93 |
|
|---|
| 94 |
|
|---|
| 95 |
/** |
|---|
| 96 |
* Evaluates to true if T is any floating-point type: real, complex, or |
|---|
| 97 |
* imaginary. |
|---|
| 98 |
*/ |
|---|
| 99 |
template isFloatingPointType( T ) |
|---|
| 100 |
{ |
|---|
| 101 |
const bool isFloatingPointType = isRealType!(T) || |
|---|
| 102 |
isComplexType!(T) || |
|---|
| 103 |
isImaginaryType!(T); |
|---|
| 104 |
} |
|---|
| 105 |
|
|---|
| 106 |
/// true if T is an atomic type |
|---|
| 107 |
template isAtomicType(T) |
|---|
| 108 |
{ |
|---|
| 109 |
static if( is( T == bool ) |
|---|
| 110 |
|| is( T == char ) |
|---|
| 111 |
|| is( T == wchar ) |
|---|
| 112 |
|| is( T == dchar ) |
|---|
| 113 |
|| is( T == byte ) |
|---|
| 114 |
|| is( T == short ) |
|---|
| 115 |
|| is( T == int ) |
|---|
| 116 |
|| is( T == long ) |
|---|
| 117 |
|| is( T == ubyte ) |
|---|
| 118 |
|| is( T == ushort ) |
|---|
| 119 |
|| is( T == uint ) |
|---|
| 120 |
|| is( T == ulong ) |
|---|
| 121 |
|| is( T == float ) |
|---|
| 122 |
|| is( T == double ) |
|---|
| 123 |
|| is( T == real ) |
|---|
| 124 |
|| is( T == ifloat ) |
|---|
| 125 |
|| is( T == idouble ) |
|---|
| 126 |
|| is( T == ireal ) ) |
|---|
| 127 |
const isAtomicType = true; |
|---|
| 128 |
else |
|---|
| 129 |
const isAtomicType = false; |
|---|
| 130 |
} |
|---|
| 131 |
|
|---|
| 132 |
/** |
|---|
| 133 |
* complex type for the given type |
|---|
| 134 |
*/ |
|---|
| 135 |
template ComplexTypeOf(T){ |
|---|
| 136 |
static if(is(T==float)||is(T==ifloat)||is(T==cfloat)){ |
|---|
| 137 |
alias cfloat ComplexTypeOf; |
|---|
| 138 |
} else static if(is(T==double)|| is(T==idouble)|| is(T==cdouble)){ |
|---|
| 139 |
alias cdouble ComplexTypeOf; |
|---|
| 140 |
} else static if(is(T==real)|| is(T==ireal)|| is(T==creal)){ |
|---|
| 141 |
alias creal ComplexTypeOf; |
|---|
| 142 |
} else static assert(0,"unsupported type in ComplexTypeOf "~T.stringof); |
|---|
| 143 |
} |
|---|
| 144 |
|
|---|
| 145 |
/** |
|---|
| 146 |
* real type for the given type |
|---|
| 147 |
*/ |
|---|
| 148 |
template RealTypeOf(T){ |
|---|
| 149 |
static if(is(T==float)|| is(T==ifloat)|| is(T==cfloat)){ |
|---|
| 150 |
alias float RealTypeOf; |
|---|
| 151 |
} else static if(is(T==double)|| is(T==idouble)|| is(T==cdouble)){ |
|---|
| 152 |
alias double RealTypeOf; |
|---|
| 153 |
} else static if(is(T==real)|| is(T==ireal)|| is(T==creal)){ |
|---|
| 154 |
alias real RealTypeOf; |
|---|
| 155 |
} else static assert(0,"unsupported type in RealTypeOf "~T.stringof); |
|---|
| 156 |
} |
|---|
| 157 |
|
|---|
| 158 |
/** |
|---|
| 159 |
* imaginary type for the given type |
|---|
| 160 |
*/ |
|---|
| 161 |
template ImaginaryTypeOf(T){ |
|---|
| 162 |
static if(is(T==float)|| is(T==ifloat)|| is(T==cfloat)){ |
|---|
| 163 |
alias ifloat ImaginaryTypeOf; |
|---|
| 164 |
} else static if(is(T==double)|| is(T==idouble)|| is(T==cdouble)){ |
|---|
| 165 |
alias idouble ImaginaryTypeOf; |
|---|
| 166 |
} else static if(is(T==real)|| is(T==ireal)|| is(T==creal)){ |
|---|
| 167 |
alias ireal ImaginaryTypeOf; |
|---|
| 168 |
} else static assert(0,"unsupported type in ImaginaryTypeOf "~T.stringof); |
|---|
| 169 |
} |
|---|
| 170 |
|
|---|
| 171 |
/// type with maximum precision |
|---|
| 172 |
template MaxPrecTypeOf(T){ |
|---|
| 173 |
static if (isComplexType!(T)){ |
|---|
| 174 |
alias creal MaxPrecTypeOf; |
|---|
| 175 |
} else static if (isImaginaryType!(T)){ |
|---|
| 176 |
alias ireal MaxPrecTypeOf; |
|---|
| 177 |
} else { |
|---|
| 178 |
alias real MaxPrecTypeOf; |
|---|
| 179 |
} |
|---|
| 180 |
} |
|---|
| 181 |
|
|---|
| 182 |
|
|---|
| 183 |
/** |
|---|
| 184 |
* Evaluates to true if T is a pointer type. |
|---|
| 185 |
*/ |
|---|
| 186 |
template isPointerType(T) |
|---|
| 187 |
{ |
|---|
| 188 |
const isPointerType = false; |
|---|
| 189 |
} |
|---|
| 190 |
|
|---|
| 191 |
template isPointerType(T : T*) |
|---|
| 192 |
{ |
|---|
| 193 |
const isPointerType = true; |
|---|
| 194 |
} |
|---|
| 195 |
|
|---|
| 196 |
debug( UnitTest ) |
|---|
| 197 |
{ |
|---|
| 198 |
unittest |
|---|
| 199 |
{ |
|---|
| 200 |
static assert( isPointerType!(void*) ); |
|---|
| 201 |
static assert( !isPointerType!(char[]) ); |
|---|
| 202 |
static assert( isPointerType!(char[]*) ); |
|---|
| 203 |
static assert( !isPointerType!(char*[]) ); |
|---|
| 204 |
static assert( isPointerType!(real*) ); |
|---|
| 205 |
static assert( !isPointerType!(uint) ); |
|---|
| 206 |
static assert( is(MaxPrecTypeOf!(float)==real)); |
|---|
| 207 |
static assert( is(MaxPrecTypeOf!(cfloat)==creal)); |
|---|
| 208 |
static assert( is(MaxPrecTypeOf!(ifloat)==ireal)); |
|---|
| 209 |
|
|---|
| 210 |
class Ham |
|---|
| 211 |
{ |
|---|
| 212 |
void* a; |
|---|
| 213 |
} |
|---|
| 214 |
|
|---|
| 215 |
static assert( !isPointerType!(Ham) ); |
|---|
| 216 |
|
|---|
| 217 |
union Eggs |
|---|
| 218 |
{ |
|---|
| 219 |
void* a; |
|---|
| 220 |
uint b; |
|---|
| 221 |
}; |
|---|
| 222 |
|
|---|
| 223 |
static assert( !isPointerType!(Eggs) ); |
|---|
| 224 |
static assert( isPointerType!(Eggs*) ); |
|---|
| 225 |
|
|---|
| 226 |
struct Bacon {}; |
|---|
| 227 |
|
|---|
| 228 |
static assert( !isPointerType!(Bacon) ); |
|---|
| 229 |
|
|---|
| 230 |
} |
|---|
| 231 |
} |
|---|
| 232 |
|
|---|
| 233 |
/** |
|---|
| 234 |
* Evaluates to true if T is a a pointer, class, interface, or delegate. |
|---|
| 235 |
*/ |
|---|
| 236 |
template isReferenceType( T ) |
|---|
| 237 |
{ |
|---|
| 238 |
|
|---|
| 239 |
const bool isReferenceType = isPointerType!(T) || |
|---|
| 240 |
is( T == class ) || |
|---|
| 241 |
is( T == interface ) || |
|---|
| 242 |
is( T == delegate ); |
|---|
| 243 |
} |
|---|
| 244 |
|
|---|
| 245 |
|
|---|
| 246 |
/** |
|---|
| 247 |
* Evaulates to true if T is a dynamic array type. |
|---|
| 248 |
*/ |
|---|
| 249 |
template isDynamicArrayType( T ) |
|---|
| 250 |
{ |
|---|
| 251 |
const bool isDynamicArrayType = is( typeof(T.init[0])[] == T ); |
|---|
| 252 |
} |
|---|
| 253 |
|
|---|
| 254 |
/** |
|---|
| 255 |
* Evaluates to true if T is a static array type. |
|---|
| 256 |
*/ |
|---|
| 257 |
version( GNU ) |
|---|
| 258 |
{ |
|---|
| 259 |
// GDC should also be able to use the other version, but it probably |
|---|
| 260 |
// relies on a frontend fix in one of the latest DMD versions - will |
|---|
| 261 |
// remove this when GDC is ready. For now, this code pass the unittests. |
|---|
| 262 |
private template isStaticArrayTypeInst( T ) |
|---|
| 263 |
{ |
|---|
| 264 |
const T isStaticArrayTypeInst = void; |
|---|
| 265 |
} |
|---|
| 266 |
|
|---|
| 267 |
template isStaticArrayType( T ) |
|---|
| 268 |
{ |
|---|
| 269 |
static if( is( typeof(T.length) ) && !is( typeof(T) == typeof(T.init) ) ) |
|---|
| 270 |
{ |
|---|
| 271 |
const bool isStaticArrayType = is( T == typeof(T[0])[isStaticArrayTypeInst!(T).length] ); |
|---|
| 272 |
} |
|---|
| 273 |
else |
|---|
| 274 |
{ |
|---|
| 275 |
const bool isStaticArrayType = false; |
|---|
| 276 |
} |
|---|
| 277 |
} |
|---|
| 278 |
} |
|---|
| 279 |
else |
|---|
| 280 |
{ |
|---|
| 281 |
template isStaticArrayType( T : T[U], size_t U ) |
|---|
| 282 |
{ |
|---|
| 283 |
const bool isStaticArrayType = true; |
|---|
| 284 |
} |
|---|
| 285 |
|
|---|
| 286 |
template isStaticArrayType( T ) |
|---|
| 287 |
{ |
|---|
| 288 |
const bool isStaticArrayType = false; |
|---|
| 289 |
} |
|---|
| 290 |
} |
|---|
| 291 |
|
|---|
| 292 |
/// true for array types |
|---|
| 293 |
template isArrayType(T) |
|---|
| 294 |
{ |
|---|
| 295 |
static if (is( T U : U[] )) |
|---|
| 296 |
const bool isArrayType=true; |
|---|
| 297 |
else |
|---|
| 298 |
const bool isArrayType=false; |
|---|
| 299 |
} |
|---|
| 300 |
|
|---|
| 301 |
debug( UnitTest ) |
|---|
| 302 |
{ |
|---|
| 303 |
unittest |
|---|
| 304 |
{ |
|---|
| 305 |
static assert( isStaticArrayType!(char[5][2]) ); |
|---|
| 306 |
static assert( !isDynamicArrayType!(char[5][2]) ); |
|---|
| 307 |
static assert( isArrayType!(char[5][2]) ); |
|---|
| 308 |
|
|---|
| 309 |
static assert( isStaticArrayType!(char[15]) ); |
|---|
| 310 |
static assert( !isStaticArrayType!(char[]) ); |
|---|
| 311 |
|
|---|
| 312 |
static assert( isDynamicArrayType!(char[]) ); |
|---|
| 313 |
static assert( !isDynamicArrayType!(char[15]) ); |
|---|
| 314 |
|
|---|
| 315 |
static assert( isArrayType!(char[15]) ); |
|---|
| 316 |
static assert( isArrayType!(char[]) ); |
|---|
| 317 |
static assert( !isArrayType!(char) ); |
|---|
| 318 |
} |
|---|
| 319 |
} |
|---|
| 320 |
|
|---|
| 321 |
/** |
|---|
| 322 |
* Evaluates to true if T is an associative array type. |
|---|
| 323 |
*/ |
|---|
| 324 |
template isAssocArrayType( T ) |
|---|
| 325 |
{ |
|---|
| 326 |
const bool isAssocArrayType = is( typeof(T.init.values[0])[typeof(T.init.keys[0])] == T ); |
|---|
| 327 |
} |
|---|
| 328 |
|
|---|
| 329 |
|
|---|
| 330 |
/** |
|---|
| 331 |
* Evaluates to true if T is a function, function pointer, delegate, or |
|---|
| 332 |
* callable object. |
|---|
| 333 |
*/ |
|---|
| 334 |
template isCallableType( T ) |
|---|
| 335 |
{ |
|---|
| 336 |
const bool isCallableType = is( T == function ) || |
|---|
| 337 |
is( typeof(*T) == function ) || |
|---|
| 338 |
is( T == delegate ) || |
|---|
| 339 |
is( typeof(T.opCall) == function ); |
|---|
| 340 |
} |
|---|
| 341 |
|
|---|
| 342 |
|
|---|
| 343 |
/** |
|---|
| 344 |
* Evaluates to the return type of Fn. Fn is required to be a callable type. |
|---|
| 345 |
*/ |
|---|
| 346 |
template ReturnTypeOf( Fn ) |
|---|
| 347 |
{ |
|---|
| 348 |
static if( is( Fn Ret == return ) ) |
|---|
| 349 |
alias Ret ReturnTypeOf; |
|---|
| 350 |
else |
|---|
| 351 |
static assert( false, "Argument has no return type." ); |
|---|
| 352 |
} |
|---|
| 353 |
|
|---|
| 354 |
/** |
|---|
| 355 |
* Returns the type that a T would evaluate to in an expression. |
|---|
| 356 |
* Expr is not required to be a callable type |
|---|
| 357 |
*/ |
|---|
| 358 |
template ExprTypeOf( Expr ) |
|---|
| 359 |
{ |
|---|
| 360 |
static if(isCallableType!( Expr )) |
|---|
| 361 |
alias ReturnTypeOf!( Expr ) ExprTypeOf; |
|---|
| 362 |
else |
|---|
| 363 |
alias Expr ExprTypeOf; |
|---|
| 364 |
} |
|---|
| 365 |
|
|---|
| 366 |
|
|---|
| 367 |
/** |
|---|
| 368 |
* Evaluates to the return type of fn. fn is required to be callable. |
|---|
| 369 |
*/ |
|---|
| 370 |
template ReturnTypeOf( alias fn ) |
|---|
| 371 |
{ |
|---|
| 372 |
static if( is( typeof(fn) Base == typedef ) ) |
|---|
| 373 |
alias ReturnTypeOf!(Base) ReturnTypeOf; |
|---|
| 374 |
else |
|---|
| 375 |
alias ReturnTypeOf!(typeof(fn)) ReturnTypeOf; |
|---|
| 376 |
} |
|---|
| 377 |
|
|---|
| 378 |
|
|---|
| 379 |
/** |
|---|
| 380 |
* Evaluates to a tuple representing the parameters of Fn. Fn is required to |
|---|
| 381 |
* be a callable type. |
|---|
| 382 |
*/ |
|---|
| 383 |
template ParameterTupleOf( Fn ) |
|---|
| 384 |
{ |
|---|
| 385 |
static if( is( Fn Params == function ) ) |
|---|
| 386 |
alias Params ParameterTupleOf; |
|---|
| 387 |
else static if( is( Fn Params == delegate ) ) |
|---|
| 388 |
alias ParameterTupleOf!(Params) ParameterTupleOf; |
|---|
| 389 |
else static if( is( Fn Params == Params* ) ) |
|---|
| 390 |
alias ParameterTupleOf!(Params) ParameterTupleOf; |
|---|
| 391 |
else |
|---|
| 392 |
static assert( false, "Argument has no parameters." ); |
|---|
| 393 |
} |
|---|
| 394 |
|
|---|
| 395 |
|
|---|
| 396 |
/** |
|---|
| 397 |
* Evaluates to a tuple representing the parameters of fn. n is required to |
|---|
| 398 |
* be callable. |
|---|
| 399 |
*/ |
|---|
| 400 |
template ParameterTupleOf( alias fn ) |
|---|
| 401 |
{ |
|---|
| 402 |
static if( is( typeof(fn) Base == typedef ) ) |
|---|
| 403 |
alias ParameterTupleOf!(Base) ParameterTupleOf; |
|---|
| 404 |
else |
|---|
| 405 |
alias ParameterTupleOf!(typeof(fn)) ParameterTupleOf; |
|---|
| 406 |
} |
|---|
| 407 |
|
|---|
| 408 |
|
|---|
| 409 |
/** |
|---|
| 410 |
* Evaluates to a tuple representing the ancestors of T. T is required to be |
|---|
| 411 |
* a class or interface type. |
|---|
| 412 |
*/ |
|---|
| 413 |
template BaseTypeTupleOf( T ) |
|---|
| 414 |
{ |
|---|
| 415 |
static if( is( T Base == super ) ) |
|---|
| 416 |
alias Base BaseTypeTupleOf; |
|---|
| 417 |
else |
|---|
| 418 |
static assert( false, "Argument is not a class or interface." ); |
|---|
| 419 |
} |
|---|
| 420 |
|
|---|
| 421 |
/** |
|---|
| 422 |
* Strips the []'s off of a type. |
|---|
| 423 |
*/ |
|---|
| 424 |
template BaseTypeOfArrays(T) |
|---|
| 425 |
{ |
|---|
| 426 |
static if( is( T S : S[]) ) { |
|---|
| 427 |
alias BaseTypeOfArrays!(S) BaseTypeOfArrays; |
|---|
| 428 |
} |
|---|
| 429 |
else { |
|---|
| 430 |
alias T BaseTypeOfArrays; |
|---|
| 431 |
} |
|---|
| 432 |
} |
|---|
| 433 |
|
|---|
| 434 |
/** |
|---|
| 435 |
* strips one [] off a type |
|---|
| 436 |
*/ |
|---|
| 437 |
template ElementTypeOfArray(T:T[]) |
|---|
| 438 |
{ |
|---|
| 439 |
alias T ElementTypeOfArray; |
|---|
| 440 |
} |
|---|
| 441 |
|
|---|
| 442 |
/** |
|---|
| 443 |
* Count the []'s on an array type |
|---|
| 444 |
*/ |
|---|
| 445 |
template rankOfArray(T) { |
|---|
| 446 |
static if(is(T S : S[])) { |
|---|
| 447 |
const uint rankOfArray = 1 + rankOfArray!(S); |
|---|
| 448 |
} else { |
|---|
| 449 |
const uint rankOfArray = 0; |
|---|
| 450 |
} |
|---|
| 451 |
} |
|---|
| 452 |
|
|---|
| 453 |
/// type of the keys of an AA |
|---|
| 454 |
template KeyTypeOfAA(T){ |
|---|
| 455 |
alias typeof(T.init.keys[0]) KeyTypeOfAA; |
|---|
| 456 |
} |
|---|
| 457 |
|
|---|
| 458 |
/// type of the values of an AA |
|---|
| 459 |
template ValTypeOfAA(T){ |
|---|
| 460 |
alias typeof(T.init.values[0]) ValTypeOfAA; |
|---|
| 461 |
} |
|---|
| 462 |
|
|---|
| 463 |
/// returns the size of a static array |
|---|
| 464 |
template staticArraySize(T) |
|---|
| 465 |
{ |
|---|
| 466 |
static assert(isStaticArrayType!(T),"staticArraySize needs a static array as type"); |
|---|
| 467 |
static assert(rankOfArray!(T)==1,"implemented only for 1d arrays..."); |
|---|
| 468 |
const size_t staticArraySize=(T).sizeof / typeof(T.init).sizeof; |
|---|
| 469 |
} |
|---|
| 470 |
|
|---|
| 471 |
/// is T is static array returns a dynamic array, otherwise returns T |
|---|
| 472 |
template DynamicArrayType(T) |
|---|
| 473 |
{ |
|---|
| 474 |
static if( isStaticArrayType!(T) ) |
|---|
| 475 |
alias typeof(T.dup) DynamicArrayType; |
|---|
| 476 |
else |
|---|
| 477 |
alias T DynamicArrayType; |
|---|
| 478 |
} |
|---|
| 479 |
|
|---|
| 480 |
debug( UnitTest ) |
|---|
| 481 |
{ |
|---|
| 482 |
static assert( is(BaseTypeOfArrays!(real[][])==real) ); |
|---|
| 483 |
static assert( is(BaseTypeOfArrays!(real[2][3])==real) ); |
|---|
| 484 |
static assert( is(ElementTypeOfArray!(real[])==real) ); |
|---|
| 485 |
static assert( is(ElementTypeOfArray!(real[][])==real[]) ); |
|---|
| 486 |
static assert( is(ElementTypeOfArray!(real[2][])==real[2]) ); |
|---|
| 487 |
static assert( is(ElementTypeOfArray!(real[2][2])==real[2]) ); |
|---|
| 488 |
static assert( rankOfArray!(real[][])==2 ); |
|---|
| 489 |
static assert( rankOfArray!(real[2][])==2 ); |
|---|
| 490 |
static assert( is(ValTypeOfAA!(char[int])==char)); |
|---|
| 491 |
static assert( is(KeyTypeOfAA!(char[int])==int)); |
|---|
| 492 |
static assert( is(ValTypeOfAA!(char[][int])==char[])); |
|---|
| 493 |
static assert( is(KeyTypeOfAA!(char[][int[]])==int[])); |
|---|
| 494 |
static assert( isAssocArrayType!(char[][int[]])); |
|---|
| 495 |
static assert( !isAssocArrayType!(char[])); |
|---|
| 496 |
static assert( is(DynamicArrayType!(char[2])==DynamicArrayType!(char[]))); |
|---|
| 497 |
static assert( is(DynamicArrayType!(char[2])==char[])); |
|---|
| 498 |
static assert( staticArraySize!(char[2])==2); |
|---|
| 499 |
} |
|---|
| 500 |
|
|---|
| 501 |
// ------- CTFE ------- |
|---|
| 502 |
|
|---|
| 503 |
/// compile time integer to string |
|---|
| 504 |
char [] ctfe_i2a(int i){ |
|---|
| 505 |
char[] digit="0123456789"; |
|---|
| 506 |
char[] res=""; |
|---|
| 507 |
if (i==0){ |
|---|
| 508 |
return "0"; |
|---|
| 509 |
} |
|---|
| 510 |
bool neg=false; |
|---|
| 511 |
if (i<0){ |
|---|
| 512 |
neg=true; |
|---|
| 513 |
i=-i; |
|---|
| 514 |
} |
|---|
| 515 |
while (i>0) { |
|---|
| 516 |
res=digit[i%10]~res; |
|---|
| 517 |
i/=10; |
|---|
| 518 |
} |
|---|
| 519 |
if (neg) |
|---|
| 520 |
return '-'~res; |
|---|
| 521 |
else |
|---|
| 522 |
return res; |
|---|
| 523 |
} |
|---|
| 524 |
/// ditto |
|---|
| 525 |
char [] ctfe_i2a(long i){ |
|---|
| 526 |
char[] digit="0123456789"; |
|---|
| 527 |
char[] res=""; |
|---|
| 528 |
if (i==0){ |
|---|
| 529 |
return "0"; |
|---|
| 530 |
} |
|---|
| 531 |
bool neg=false; |
|---|
| 532 |
if (i<0){ |
|---|
| 533 |
neg=true; |
|---|
| 534 |
i=-i; |
|---|
| 535 |
} |
|---|
| 536 |
while (i>0) { |
|---|
| 537 |
res=digit[cast(size_t)(i%10)]~res; |
|---|
| 538 |
i/=10; |
|---|
| 539 |
} |
|---|
| 540 |
if (neg) |
|---|
| 541 |
return '-'~res; |
|---|
| 542 |
else |
|---|
| 543 |
return res; |
|---|
| 544 |
} |
|---|
| 545 |
/// ditto |
|---|
| 546 |
char [] ctfe_i2a(uint i){ |
|---|
| 547 |
char[] digit="0123456789"; |
|---|
| 548 |
char[] res=""; |
|---|
| 549 |
if (i==0){ |
|---|
| 550 |
return "0"; |
|---|
| 551 |
} |
|---|
| 552 |
bool neg=false; |
|---|
| 553 |
while (i>0) { |
|---|
| 554 |
res=digit[i%10]~res; |
|---|
| 555 |
i/=10; |
|---|
| 556 |
} |
|---|
| 557 |
return res; |
|---|
| 558 |
} |
|---|
| 559 |
/// ditto |
|---|
| 560 |
char [] ctfe_i2a(ulong i){ |
|---|
| 561 |
char[] digit="0123456789"; |
|---|
| 562 |
char[] res=""; |
|---|
| 563 |
if (i==0){ |
|---|
| 564 |
return "0"; |
|---|
| 565 |
} |
|---|
| 566 |
bool neg=false; |
|---|
| 567 |
while (i>0) { |
|---|
| 568 |
res=digit[cast(size_t)(i%10)]~res; |
|---|
| 569 |
i/=10; |
|---|
| 570 |
} |
|---|
| 571 |
return res; |
|---|
| 572 |
} |
|---|
| 573 |
|
|---|
| 574 |
debug( UnitTest ) |
|---|
| 575 |
{ |
|---|
| 576 |
unittest { |
|---|
| 577 |
static assert( ctfe_i2a(31)=="31" ); |
|---|
| 578 |
static assert( ctfe_i2a(-31)=="-31" ); |
|---|
| 579 |
static assert( ctfe_i2a(14u)=="14" ); |
|---|
| 580 |
static assert( ctfe_i2a(14L)=="14" ); |
|---|
| 581 |
static assert( ctfe_i2a(14UL)=="14" ); |
|---|
| 582 |
} |
|---|
| 583 |
} |
|---|