Opérateurs de transtypage
Bonjour,
pour m'exercer j'essaie de créer une classe u64 (unsigned codés sur 64 bits), en surchargeant les opérations sur cette classe:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| struct u64
{
u32 faible;
u32 fort;
u64(u64 &right) {
faible = right.faible;
fort = right.fort;
}
// u32 -> u64
u64(u32 right) {
faible = right;
fort = 0;
}
u64& operator=(const u64 &right) {
faible = right.faible;
fort = right.fort;
return (*this);
}
inline static void multiplie(const u32 left, const u32 right, u64 &result) {
u32 a,b,c,d,i,j,k,l;
a = left & 0xffff;
b = ((u32)left) >> 16;
c = right & 0xffff;
d = ((u32)right) >> 16;
i = a * c;
j = a * d;
k = b * c;
l = b * d;
j += k;
if(j < k)
l++;
result.faible = i + (j << 16); // pas d'overFlow possible
result.fort = l + (((u32)j) >> 16); // idem
}
// u64 -> u32
operator unsigned int const (void) {
return faible;
}
};
u64 operator*(const u64 &left, const u64 &right) {
u64 result;
u64 i,j,k;
u64::multiplie(left.faible,right.faible,result);
if((left.fort) || (right.faible)) {
u64::multiplie(left.fort,right.faible,j);
u64::multiplie(left.faible,right.fort,k);
result.fort += j.faible + k.faible;
}
return result;
} |
mais si j'execute le code suivant:
Code:
1 2 3
| u64 a = 1 << 31;
u64 b = 1 << 31;
u64 c = a * b; |
c vaut 0 !
alors que ceci:
Code:
1 2 3 4
| u64 a = 1 << 31;
u64 b = 1 << 31;
u64 c;
c = a * b; |
me renvoie bien le bon résultat 1 << 62.
en step-by-step, on voit que dans le premier cas c'est l'opérateur de copie qui est utilisé, et pour une raison qui m'échappe, dans le second cas le compilo préfère caster le résultat de a * b en u32 puis lui appliquer le constructeur 32 bits u64(u32 right) plutôt que d'utiliser directement l'opérateur de copie 64 bits u64(u64 &right). 8O
A noter que si j'enlève le code permettant le cast de u64 à u32, ou le constructeur 32 bits u64(u32 right), alors il utilise bien l'opérateur de copie 64 bits u64(u64 &right) et la valeur de c devient juste dans les 2 morceaux de codes ci-dessus.
D'où ma question: 1) commet expliquer au compilo que c'est bien l'opérateur de copie 64 bit qu'il doit utiliser dans ce cas, et pas le constructeur 32 bits ?
et 2) (question subsidiaire): est-ce que c'est possible de désactiver le cast implicite dans le code:
Code:
1 2 3
| operator unsigned int const (void) {
return faible;
} |
un peu dans le genre du mot clé explicit qu'on peut ajouter devant:
Code:
1 2 3 4
| explicit u64(u32 right) {
faible = right;
fort = 0;
} |
puisque en principe on voudrait plutôt que l'utilisateur puisse faire librement des:
Code:
1 2 3
| u64 a;
u32 b = 10;
a = b; |
plutôt que des:
Code:
1 2 3
| u64 a = 1 << 50;
u32 b;
b = a; |
(qui eux devraient générer une erreur sauf si on cast b = (u32)a; )
merci d'avance !