@@ -267,21 +267,24 @@ unittest
267
267
}();
268
268
}
269
269
270
+ /*
271
+ Reduces to `T` if `cond` is `true` or `U` otherwise.
272
+ */
270
273
private template Select (bool cond, T, U)
271
274
{
272
275
static if (cond) alias Select = T;
273
276
else alias Select = U;
274
277
}
275
278
276
- /**
279
+ /*
277
280
TypeInfo information for built-in types.
278
281
279
- Type `T` has the same layout and alignment as type `Base`, but slightly different behavior.
280
- Example: `float` and `ifloat` or `char` and `ubyte`.
281
- We assume the two types hash the same, swap the same, have the same ABI flags, and compare the same for
282
- equality. For ordering comparisons, we detect during compilation whether they have different min and max
283
- values (e.g. signed vs. unsigned) and override appropriately. For initializer, we detect if we need to
284
- override. The overriding initializer should be nonzero.
282
+ A `Base` type may be specified, which must be a type with the same layout, alignment, hashing, and
283
+ equality comparison as type `T`. This saves on code size because parts of `Base` will be reused. Example:
284
+ `float` and `ifloat` or `char` and `ubyte`. The implementation assumes `Base` and `T` hash the same, swap
285
+ the same, have the same ABI flags, and compare the same for equality. For ordering comparisons, we detect
286
+ during compilation whether they have different signedness and override appropriately. For initializer, we
287
+ detect if we need to override. The overriding initializer should be nonzero.
285
288
*/
286
289
private class TypeInfoGeneric (T, Base = T) : Select !(is(T == Base), TypeInfo, TypeInfoGeneric!Base)
287
290
if (T.sizeof == Base.sizeof && T.alignof == Base.alignof)
@@ -408,66 +411,72 @@ unittest
408
411
}
409
412
}
410
413
411
- private class TypeInfoArrayGeneric (T) : TypeInfo_Array
412
- {
413
- static if (__traits(isFloating, T))
414
- {
415
- static if (is (T == ifloat )) private alias Real = float ;
416
- else static if (is (T == idouble )) private alias Real = double ;
417
- else static if (is (T == ireal )) private alias Real = real ;
418
- else private alias Real = T;
419
- }
414
+ /*
415
+ TypeInfo information for arrays of built-in types.
420
416
421
- override bool opEquals (Object o) { return TypeInfo .opEquals (o); }
417
+ A `Base` type may be specified, which must be a type with the same layout, alignment, hashing, and
418
+ equality comparison as type `T`. This saves on code size because parts of `Base` will be reused. Example:
419
+ `float` and `ifloat` or `char` and `ubyte`. The implementation assumes `Base` and `T` hash the same, swap
420
+ the same, have the same ABI flags, and compare the same for equality. For ordering comparisons, we detect
421
+ during compilation whether they have different signedness and override appropriately. For initializer, we
422
+ detect if we need to override. The overriding initializer should be nonzero.
423
+ */
424
+ private class TypeInfoArrayGeneric (T, Base = T) : Select !(is(T == Base), TypeInfo_Array, TypeInfoArrayGeneric!Base)
425
+ {
426
+ static if (is (T == Base))
427
+ override bool opEquals (Object o) { return TypeInfo .opEquals (o); }
422
428
423
429
override string toString () const { return (T[]).stringof; }
424
430
425
- override size_t getHash (scope const void * p) @trusted const
426
- {
427
- static if (__traits(isFloating, T))
428
- return Array! Real.hashOf(* cast (Real[]* )p);
429
- else
430
- return hashOf (* cast (const T[]* ) p);
431
- }
432
-
433
- override bool equals (in void * p1, in void * p2) const
434
- {
435
- static if (__traits(isFloating, T))
436
- {
437
- return Array! Real.equals(* cast (Real[]* )p1, * cast (Real[]* )p2);
438
- }
439
- else
431
+ static if (is (T == Base))
432
+ override size_t getHash (scope const void * p) @trusted const
440
433
{
441
- import core.stdc.string ;
442
- auto s1 = * cast (T[]* )p1;
443
- auto s2 = * cast (T[]* )p2;
444
- return s1.length == s2.length &&
445
- memcmp(s1.ptr, s2.ptr, s1.length) == 0 ;
434
+ static if (__traits(isFloating, T))
435
+ return Array! T.hashOf(* cast (T[]* )p);
436
+ else
437
+ return hashOf (* cast (const T[]* ) p);
446
438
}
447
- }
448
439
449
- override int compare (in void * p1, in void * p2) const
450
- {
451
- static if (__traits(isFloating, T))
440
+ static if (is (T == Base))
441
+ override bool equals (in void * p1, in void * p2) const
452
442
{
453
- return Array! Real.compare(* cast (Real[]* )p1, * cast (Real[]* )p2);
443
+ static if (__traits(isFloating, T))
444
+ {
445
+ return Array! T.equals(* cast (T[]* )p1, * cast (T[]* )p2);
446
+ }
447
+ else
448
+ {
449
+ import core.stdc.string ;
450
+ auto s1 = * cast (T[]* )p1;
451
+ auto s2 = * cast (T[]* )p2;
452
+ return s1.length == s2.length &&
453
+ memcmp(s1.ptr, s2.ptr, s1.length) == 0 ;
454
+ }
454
455
}
455
- else
456
- {
457
- auto s1 = * cast (T[]* )p1;
458
- auto s2 = * cast (T[]* )p2;
459
- auto len = s1.length;
460
456
461
- if (s2.length < len)
462
- len = s2.length;
463
- for (size_t u = 0 ; u < len; u++ )
457
+ static if (is (T == Base) || (__traits(isIntegral, T) && T.max != Base.max))
458
+ override int compare (in void * p1, in void * p2) const
459
+ {
460
+ static if (__traits(isFloating, T))
464
461
{
465
- if (int result = (s1[u] > s2[u]) - (s1[u] < s2[u]))
466
- return result;
462
+ return Array! T.compare(* cast (T[]* )p1, * cast (T[]* )p2);
463
+ }
464
+ else
465
+ {
466
+ auto s1 = * cast (T[]* )p1;
467
+ auto s2 = * cast (T[]* )p2;
468
+ auto len = s1.length;
469
+
470
+ if (s2.length < len)
471
+ len = s2.length;
472
+ for (size_t u = 0 ; u < len; u++ )
473
+ {
474
+ if (int result = (s1[u] > s2[u]) - (s1[u] < s2[u]))
475
+ return result;
476
+ }
477
+ return (s1.length > s2.length) - (s1.length < s2.length);
467
478
}
468
- return (s1.length > s2.length) - (s1.length < s2.length);
469
479
}
470
- }
471
480
472
481
override @property inout (TypeInfo ) next() inout
473
482
{
@@ -521,18 +530,18 @@ class TypeInfo_v : TypeInfoGeneric!ubyte
521
530
}
522
531
523
532
// All integrals.
533
+ class TypeInfo_h : TypeInfoGeneric !ubyte {}
524
534
class TypeInfo_b : TypeInfoGeneric !(bool, ubyte) {}
525
- class TypeInfo_g : TypeInfoGeneric !byte {}
526
- class TypeInfo_h : TypeInfoGeneric !(ubyte, byte) {}
535
+ class TypeInfo_g : TypeInfoGeneric !(byte, ubyte) {}
527
536
class TypeInfo_a : TypeInfoGeneric !(char, ubyte) {}
537
+ class TypeInfo_t : TypeInfoGeneric !ushort {}
538
+ class TypeInfo_s : TypeInfoGeneric !(short, ushort) {}
528
539
class TypeInfo_u : TypeInfoGeneric !(wchar, ushort) {}
529
540
class TypeInfo_w : TypeInfoGeneric !(dchar, uint) {}
530
- class TypeInfo_s : TypeInfoGeneric !short {}
531
- class TypeInfo_t : TypeInfoGeneric !(ushort, short) {}
532
- class TypeInfo_i : TypeInfoGeneric !int {}
533
- class TypeInfo_k : TypeInfoGeneric !(uint, int) {}
534
- class TypeInfo_l : TypeInfoGeneric !long {}
535
- class TypeInfo_m : TypeInfoGeneric !(ulong, long) {}
541
+ class TypeInfo_k : TypeInfoGeneric !uint {}
542
+ class TypeInfo_i : TypeInfoGeneric !(int, uint) {}
543
+ class TypeInfo_m : TypeInfoGeneric !ulong {}
544
+ class TypeInfo_l : TypeInfoGeneric !(long, ulong) {}
536
545
static if (is (cent )) class TypeInfo_zi : TypeInfoGeneric! cent {}
537
546
static if (is (ucent )) class TypeInfo_zk : TypeInfoGeneric! ucent {}
538
547
@@ -597,24 +606,24 @@ static if (__traits(hasMember, TypeInfo, "argTypes"))
597
606
}
598
607
599
608
// Arrays of all integrals.
600
- class TypeInfo_Ab : TypeInfoArrayGeneric !bool {}
601
- class TypeInfo_Ag : TypeInfoArrayGeneric !byte {}
602
609
class TypeInfo_Ah : TypeInfoArrayGeneric !ubyte {}
603
- class TypeInfo_Aa : TypeInfoArrayGeneric !char {}
610
+ class TypeInfo_Ab : TypeInfoArrayGeneric !(bool, ubyte) {}
611
+ class TypeInfo_Ag : TypeInfoArrayGeneric !(byte, ubyte) {}
612
+ class TypeInfo_Aa : TypeInfoArrayGeneric !(char, ubyte) {}
604
613
class TypeInfo_Axa : TypeInfoArrayGeneric !(const char) {}
605
614
class TypeInfo_Aya : TypeInfoArrayGeneric !(immutable char)
606
615
{
607
616
// Must override this, otherwise "string" is returned.
608
617
override string toString () const { return " immutable(char)[]" ; }
609
618
}
610
- class TypeInfo_As : TypeInfoArrayGeneric !short {}
611
619
class TypeInfo_At : TypeInfoArrayGeneric !ushort {}
612
- class TypeInfo_Au : TypeInfoArrayGeneric !wchar {}
613
- class TypeInfo_Ai : TypeInfoArrayGeneric !int {}
620
+ class TypeInfo_As : TypeInfoArrayGeneric !(short, ushort) {}
621
+ class TypeInfo_Au : TypeInfoArrayGeneric !(wchar, ushort) {}
614
622
class TypeInfo_Ak : TypeInfoArrayGeneric !uint {}
615
- class TypeInfo_Aw : TypeInfoArrayGeneric !dchar {}
616
- class TypeInfo_Al : TypeInfoArrayGeneric !long {}
623
+ class TypeInfo_Ai : TypeInfoArrayGeneric !(int, uint) {}
624
+ class TypeInfo_Aw : TypeInfoArrayGeneric !(dchar, uint) {}
617
625
class TypeInfo_Am : TypeInfoArrayGeneric !ulong {}
626
+ class TypeInfo_Al : TypeInfoArrayGeneric !(long, ulong) {}
618
627
619
628
private extern (C) void [] _adSort(void [] a, TypeInfo ti);
620
629
@@ -656,11 +665,11 @@ unittest
656
665
657
666
// Arrays of all floating point types.
658
667
class TypeInfo_Af : TypeInfoArrayGeneric !float {}
659
- class TypeInfo_Ao : TypeInfoArrayGeneric !ifloat {}
668
+ class TypeInfo_Ao : TypeInfoArrayGeneric !( ifloat, float) {}
660
669
class TypeInfo_Ad : TypeInfoArrayGeneric !double {}
661
- class TypeInfo_Ap : TypeInfoArrayGeneric !idouble {}
670
+ class TypeInfo_Ap : TypeInfoArrayGeneric !( idouble, double) {}
662
671
class TypeInfo_Ae : TypeInfoArrayGeneric !real {}
663
- class TypeInfo_Aj : TypeInfoArrayGeneric !ireal {}
672
+ class TypeInfo_Aj : TypeInfoArrayGeneric !( ireal, real) {}
664
673
class TypeInfo_Aq : TypeInfoArrayGeneric !cfloat {}
665
674
class TypeInfo_Ar : TypeInfoArrayGeneric !cdouble {}
666
675
class TypeInfo_Ac : TypeInfoArrayGeneric !creal {}
0 commit comments