2010-04-27 5 views
4

J'essaye d'écrire une classe qui implémente des nombres de 64 bits pour un compilateur qui ne supporte pas long long, pour être utilisé dans le code existant. Fondamentalement, je devrais pouvoir avoir un typedef quelque part qui choisit si je veux utiliser long long ou ma classe, et tout le reste devrait compiler et fonctionner. Donc, j'ai évidemment besoin de constructeurs de conversion de int, long, etc., et les opérateurs de conversion respectifs (moulages) pour ces types. Cela semble provoquer des erreurs avec les opérateurs arithmétiques. Avec les types natifs, le compilateur "sait" que lorsque operator*(int, char) est appelé, il doit promouvoir les char à int et appeler le operator*(int, int) (plutôt que de transtyper int en char, par exemple). Dans mon cas, il devient confus entre les différents opérateurs intégrés et ceux que j'ai créés. Il me semble que si je pouvais signaler les opérateurs de conversion comme étant explicites, cela résoudrait le problème, mais pour autant que je puisse dire le mot-clé explicit est seulement pour les constructeurs (et je ne peux pas faire de constructeurs pour types intégrés).Rendre la conversion à un type natif explicite en C++

Y a-t-il donc un moyen de marquer les moulages de façon explicite? Ou suis-je aboyant le mauvais arbre ici et il y a une autre façon de résoudre ce problème? Ou peut-être que je vais juste faire quelque chose d'autre mal ...

EDIT:

Une petite précision sur ce que je veux faire: j'ai un projet qui utilise des opérations 64 bits («long long`) dans beaucoup d'endroits, et j'essaye de le porter à une plate-forme que n'a pas ont le support intégré pour des variables/opérations de 64 bits. Même si j'ai la source pour le projet, je préférerais vraiment ne pas avoir à passer par-dessus les milliers d'endroits où les opérateurs intégrés et les moulages de style C sont et les changer autour.

En ce qui concerne le code lui-même, le projet a les définitions et les types de code:

typedef long long i64; // I would like to only have to change this to use my class instead of "long long" 

int a; 
unsigned b; 
int c = ((i64)a*b)>>32; 

En ce qui concerne la mise en œuvre de la classe, je les suivantes:

class Long64 { 
public: 

Long64(); 
Long64(const Long64&); 
Long64(int); 
Long64(long); 
Long64(unsigned int); 
Long64(unsigned long); 

operator int() const; 
operator long() const; 
operator unsigned int() const; 
operator unsigned long() const; 

friend Long64 operator*(int l, const Long64& r); 
friend Long64 operator*(const Long64& l, int r); 
friend Long64 operator*(long l, const Long64& r); 
friend Long64 operator*(const Long64& l, long r); 
} 
+2

Vous serez autorisé à utiliser 'explicit' avec les opérateurs de conversion dans la prochaine version de C++, mais pas. Pouvez-vous poster du code? Le conseil habituel est d'éviter trop de conversions implicites mais de fournir (par exemple) des fonctions de style to_int() mais vous devez vraiment afficher du code démontrant le problème que vous rencontrez. –

+0

Pour vous aider, j'ai besoin de montrer les signatures de l'opérateur que vous avez définies dans votre classe. –

Répondre

3

Pour éviter que le compilateur ne soit confondu, vous l'aidez en définissant la combinaison de votre classe et des types intégrés pour tout l'opérateur arithmétique. Par exemple, pour l'opérateur +, vous devrez définir + les non signés

MyClass operator+(char, MyClass const&); 
MyClass operator+(MyClass const&, char); 
MyClass operator+(short, MyClass const&); 
MyClass operator+(MyClass const&,short); 
MyClass operator+(MyClass const&,int); 

le compilateur qui ne préfèrent pas les surcharges ont besoin d'utiliser les opérateurs de conversion.

Bien sûr, toutes ces méthodes utiliseront la surcharge opérateur MyClass + (MyClass const &, MyClass const &);

en convertissant explicitement l'un des paramètres à votre classe MyClass

MyClass operator+(char c, MyClass const& m) { return MyClass(c)+m;} 

Ceci est un peu lourd, je sais, mais il devrait éviter les conflits.

+0

est ce que je l'ai fait, mais je raté les unsigneds ... pour les surcharges/doh Merci. –

2

Vous devez créer des méthodes avec des noms significatifs au lieu des opérateurs de conversion - comme toLongLong() au lieu de operator long long() - de cette façon, vous serez capable d'écrire du code que les gens et le compilateur comprendront facilement. C'est la seule solution raisonnable quand vous avez tellement d'opérateurs de conversion que même le compilateur ne peut pas obtenir ce que vous voulez.

+0

Mais alors il ne sera pas un remplacement pour un type natif, et nécessitera des changements dans le code qui l'utilise, ce que j'essaie d'éviter. Je vais clarifier la question avec ce que j'essaie exactement de faire. –

+1

@Tal Pressman: Je vois votre problème, mais il n'y a pas grand-chose que vous pouvez faire ici - soit vous aurez un code propre à la recherche, mais nécessitant beaucoup de penser à comprendre ou à vous changer juste la classe et le code d'appel pour un avenir meilleur. Ce – sharptooth