@@ -57,6 +57,18 @@ private enum isFinalClassWithAddressBasedHash(T) = __traits(isFinalClass, T)
57
57
static assert (! isFinalClassWithAddressBasedHash! C3 );
58
58
}
59
59
60
+ private template isCppClassWithoutHash (T)
61
+ {
62
+ static if (! is (T == class ) && ! is (T == interface ))
63
+ enum isCppClassWithoutHash = false ;
64
+ else
65
+ {
66
+ import core.internal.traits : Unqual;
67
+ enum bool isCppClassWithoutHash = __traits(getLinkage, T) == " C++"
68
+ && ! is (Unqual! T : Object ) && ! hasCallableToHash! T;
69
+ }
70
+ }
71
+
60
72
/+
61
73
Is it valid to calculate a hash code for T based on the bits of its
62
74
representation? Always false for interfaces, dynamic arrays, and
@@ -80,11 +92,11 @@ private template canBitwiseHash(T)
80
92
enum canBitwiseHash = true ;
81
93
else static if (is (T == class ))
82
94
{
83
- enum canBitwiseHash = isFinalClassWithAddressBasedHash! T;
95
+ enum canBitwiseHash = isFinalClassWithAddressBasedHash! T || isCppClassWithoutHash ! T ;
84
96
}
85
97
else static if (is (T == interface ))
86
98
{
87
- enum canBitwiseHash = false ;
99
+ enum canBitwiseHash = isCppClassWithoutHash ! T ;
88
100
}
89
101
else static if (is (T == struct ))
90
102
{
@@ -553,7 +565,7 @@ size_t hashOf(T)(scope const T val, size_t seed = 0) if (!is(T == enum) && is(T
553
565
@nogc nothrow pure @trusted
554
566
size_t hashOf (T)(scope const T val)
555
567
if (! is (T == enum ) && (is (T == interface ) || is (T == class ))
556
- && isFinalClassWithAddressBasedHash ! T)
568
+ && canBitwiseHash ! T)
557
569
{
558
570
if (__ctfe) if (val is null ) return 0 ;
559
571
return hashOf (cast (const void * ) val);
@@ -563,7 +575,7 @@ if (!is(T == enum) && (is(T == interface) || is(T == class))
563
575
@nogc nothrow pure @trusted
564
576
size_t hashOf (T)(scope const T val, size_t seed)
565
577
if (! is (T == enum ) && (is (T == interface ) || is (T == class ))
566
- && isFinalClassWithAddressBasedHash ! T)
578
+ && canBitwiseHash ! T)
567
579
{
568
580
if (__ctfe) if (val is null ) return hashOf(size_t (0 ), seed);
569
581
return hashOf (cast (const void * ) val, seed);
@@ -572,7 +584,7 @@ if (!is(T == enum) && (is(T == interface) || is(T == class))
572
584
// class or interface hash. CTFE depends on toHash
573
585
size_t hashOf (T)(T val)
574
586
if (! is (T == enum ) && (is (T == interface ) || is (T == class ))
575
- && ! isFinalClassWithAddressBasedHash ! T)
587
+ && ! canBitwiseHash ! T)
576
588
{
577
589
static if (__traits(compiles, {size_t h = val.toHash();}))
578
590
return val ? val.toHash() : 0 ;
@@ -583,7 +595,7 @@ if (!is(T == enum) && (is(T == interface) || is(T == class))
583
595
// class or interface hash. CTFE depends on toHash
584
596
size_t hashOf (T)(T val, size_t seed)
585
597
if (! is (T == enum ) && (is (T == interface ) || is (T == class ))
586
- && ! isFinalClassWithAddressBasedHash ! T)
598
+ && ! canBitwiseHash ! T)
587
599
{
588
600
static if (__traits(compiles, {size_t h = val.toHash();}))
589
601
return hashOf (val ? cast (size_t ) val.toHash() : size_t (0 ), seed);
0 commit comments