2008-10-14 13 views
3

C++ est principalement un surensemble de C, mais pas toujours. En particulier, alors que les valeurs d'énumération dans C et C++ se convertissent implicitement en int, l'inverse n'est pas vrai: uniquement dans C do ints se reconvertit en valeurs d'énumération. Ainsi, les bitflags définis via les déclarations d'énumération ne fonctionnent pas correctement. Par conséquent, c'est OK en C, mais pas en C++:Comment les énumérations C bitflag doivent-elles être traduites en C++?

typedef enum Foo 
{ 
    Foo_First = 1<<0, 
    Foo_Second = 1<<1, 
} Foo; 

int main(void) 
{ 
    Foo x = Foo_First | Foo_Second; // error in C++ 
    return 0; 
} 

Comment ce problème soit traité correctement et efficacement, idéalement sans nuire à la nature du débogueur convivial d'utiliser Foo comme type de variable (il se décompose dans la bitflags de composant dans les montres etc.)? Considérons également qu'il peut y avoir des centaines d'énumérations de drapeaux de ce type, et plusieurs milliers de points d'utilisation. Idéalement, une sorte de surcharge de l'opérateur efficace ferait l'affaire, mais elle devrait vraiment être efficace; l'application que j'ai à l'esprit est liée au calcul et a la réputation d'être rapide. Clarification: Je traduis un grand programme C (> 300K) en C++, donc je recherche une traduction efficace à la fois en temps d'exécution et en temps de développement. Simplement insérer des moulages dans tous les endroits appropriés pourrait prendre des semaines. Pourquoi ne pas simplement renvoyer le résultat à un Foo?

Répondre

8

Foo x = Foo(Foo_First | Foo_Second); 

EDIT: Je n'ai pas compris l'étendue de votre problème lorsque j'ai répondu à cette question pour la première fois. Ce qui précède fonctionnera pour faire quelques corrections ponctuelles. Pour ce que vous voulez faire, vous devrez définir un | opérateur qui prend 2 arguments Foo et retourne un Foo:

Foo operator|(Foo a, Foo b) 
{ 
    return Foo(int(a) | int(b)); 
} 

Les int int sont là pour éviter une récursion indésirable.

+0

Passer par des centaines de milliers de lignes de code source pour insérer des moulages n'est pas mon idée d'une traduction efficace. –

+0

@Ferruccio, la syntaxe ne serait-elle pas "Foo x = (Foo) (Foo_First | Foo_Second);" –

+0

Vous pouvez le faire aussi. J'ai utilisé un casting de style C++. Les moulages en style C fonctionnent toujours. – Ferruccio

0

Soit laisser le résultat comme un int ou static_cast:

Foo x = static_cast<Foo>(Foo_First | Foo_Second); // not an error in C++ 
2

Cela ressemble à une application idéale pour un casting - il est à vous de dire au compilateur que oui, vous ne veux instancier un Foo avec un entier aléatoire.

Bien sûr, techniquement parlant, Foo_First | Foo_Second n'est pas une valeur valide pour un Foo.

+0

dans ce cas, il est - 1 | 0 est toujours 1 – warren

+0

L'idiome est valide en C, et j'essaie de traduire un grand programme C (> 300K) en C++, donc je suis à la recherche d'une traduction efficace à la fois temps d'exécution et temps de développement. –

+1

@warren - 1 << 0 == 1, 1 << 1 == 2; ce n'est pas 1 | 0, mais 1 | 2 == 3. –

Questions connexes