c ++ plusieurs énumérations dans l'argument d'une fonction à l'aide ou au niveau du bit « | »

StackOverflow https://stackoverflow.com/questions/1874051

Question

Je suis tombé récemment sur certaines fonctions où vous pouvez passer plusieurs énumérations comme ceci:

myFunction(One | Two);

Depuis que je pense que cela est une façon vraiment élégante j'ai essayé de mettre en œuvre quelque chose comme moi-même:

void myFunction(int _a){
    switch(_a){
        case One:
            cout<<"!!!!"<<endl;
            break;
        case Two:
            cout<<"?????"<<endl;
            break;
    }
}

maintenant, si je tente d'appeler la fonction avec un | Deux, je veux que les deux cas de commutation s'appelle. Je ne suis pas vraiment bon avec les opérateurs binaires, donc je ne sais pas vraiment quoi faire. Toutes les idées serait génial!

Merci!

Était-ce utile?

La solution

Pour que vous devez faire énumérations comme:

enum STATE {
  STATE_A = 1,
  STATE_B = 2,
  STATE_C = 4
};

i.e.. valeur de l'élément ENUM doit être en puissance de 2 pour sélectionner le cas valide ou instruction if.

Alors, quand vous faites comme:

void foo( int state) {

  if ( state & STATE_A ) {
    //  do something 
  }

  if ( state & STATE_B ) {
    //  do something 
  }

  if ( state & STATE_C ) {
    //  do something 
  }   
}

int main() {
  foo( STATE_A | STATE_B | STATE_C);
}

Autres conseils

se comportent bien les opérateurs au niveau du bit uniquement avec des puissances de 2:

  0010
| 0100
------
  0110  // both bits are set


  0110
& 0100
------
  0100  // nonzero, i.e. true: the flag is set

Si vous essayez de faire la même chose avec un nombre arbitraire, vous obtiendrez des résultats inattendus:

  0101  // 5
| 1100  // 12
------
  1101  // 13

qui contient les éventuels nombres (arbitraires) en tant que drapeaux d'ensemble: 0001 (1), 0100 (4), 0101 (5), 1000 (8), 1001 (9), 1100 (12), 1101 (13)

Ainsi, au lieu de donner deux options, vous venez de donner six.

En général, les arguments qui sont combinés de cette façon sont des drapeaux (une valeur avec un seul jeu de bits) avec une valeur décimale de 1, 2, 4, 8, etc. En supposant que un et deux suivent cette règle, vous ne pouvez pas utiliser un commutateur pour vérifier les deux. Commutateurs qu'une seule ligne. Votre argumentation combinée ne correspond pas à un ou deux, mais une combinaison d'entre eux (1 | 2 == 3). Vous pouvez vérifier si un ou deux est défini comme ceci:

if (_a & One)
{

}
if (_a & Two)
{

}

Rappelez-vous qu'un ENUM standard sans valeurs explicites sera juste compter vers le haut, ne pas utiliser le bit suivant. Si votre prochaine valeur définie est trois, il sera égal probablement 3 qui n'est pas une valeur d'un seul bit, et ensuite agir comme si vous aviez passé les deux drapeaux (One | Deux) à la fonction. Vous aurez besoin de définir les valeurs de la même enum.

Vous devez diviser les possibles "jetons" (non-chevauchement bien sûr ... utiliser la puissance de 2):

if (_a & One) { ... }

Non élégant vous vraiment ce que vous voulez avec 1 instruction switch: split en utilisant des instructions de if

.

Vous êtes mieux le faire avec un ensemble de déclarations si ...

soit

if ( _a & ONE )
{
   // Do stuff.
}
if ( _a & TWO )
{
  // Do other stuff.
}

edit: Vous pouvez aussi le faire dans une instruction switch mais ce serait un cauchemar. Youd besoin de quelque chose comme ceci

switch( _a )
{
case ONE:
   // Handle ONE.
   break;

case TWO:
   // Handle TWO.
   break;

case ONE | TWO:
   // Handle ONE.
   // Handle TWO.
   break;
};

Son relativement sain d'esprit pour seulement deux options, mais une fois que vous obtenez plus qu'il commence à ballon hors de contrôle. Si vous avez 32-options que vous auriez une instruction switch qui serait probablement pas à sur toute machine. Dans la solution « si » est beaucoup plus propre et beaucoup plus sain d'esprit:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top