C ++ Le moyen le plus efficace de comparer une variable à plusieurs valeurs?

Quelques fois dans mon programme, j’ai dû vérifier si une variable était l’une des nombreuses options. Par exemple

if (num = ()) { DO STUFF } 

Je me suis amusé avec les «OU», mais rien ne semble être correct. J’ai essayé

 if (num == (1 || 2 || 3)) 

mais ça ne fait rien. S’il vous plaît aider! Merci d’avance.

PS je dois faire la distinction entre plusieurs groupes. Par exemple…

 if (num = (1,2,3)) else if (num = (4,5,6)) else if (num = (7,8,9)) 

Si les valeurs que vous souhaitez vérifier sont suffisamment petites, vous pouvez créer un masque de bits des valeurs que vous recherchez, puis vérifier que ce bit est défini.

Supposons que vous vous souciez de deux groupes.

 static const unsigned values_group_1 = (1 << 1) | (1 << 2) | (1 << 3); static const unsigned values_group_2 = (1 << 4) | (1 << 5) | (1 << 6); static const unsigned values_group_3 = (1 << 7) | (1 << 8) | (1 << 9); if ((1 << value_to_check) & values_group_1) { // You found a match for group 1 } if ((1 << value_to_check) & values_group_2) { // You found a match for group 2 } if ((1 << value_to_check) & values_group_3) { // You found a match for group 3 } 

Cette approche fonctionne mieux pour les valeurs ne dépassant pas la taille naturelle avec laquelle votre CPU aime travailler. Ce serait généralement 64 dans les temps modernes, mais peut varier en fonction des spécificités de votre environnement.

Voici une manière de faire en C ++ 11, en utilisant std::initializer_list :

 #include  #include  template  bool is_in(const T& v, std::initializer_list lst) { return std::find(std::begin(lst), std::end(lst), v) != std::end(lst); } 

avec ça, tu peux faire:

 if (is_in(num, {1, 2, 3})) { DO STUFF } 

Il n’est cependant pas très efficace s’il n’est pas utilisé avec des types intégrés. int fonctionnera correctement, mais si vous comparez std::ssortingng variables std::ssortingng par exemple, le code produit est simplement horrible.

Cependant, en C ++ 17, vous pouvez utiliser une solution beaucoup plus efficace qui fonctionne bien avec n’importe quel type:

 template bool is_in(First &&first, T && ... t) { return ((first == t) || ...); } // ... // s1, s2, s3, s4 are ssortingngs. if (is_in(s1, s2, s3, s4)) // ... 

La version C ++ 11 serait très inefficace ici, alors que cette version devrait produire le même code que les comparaisons manuscrites.

Vous devez faire la comparaison avec chaque valeur. Par exemple

 if (num == 1 || num == 2 || num == 3) { stuff } 

Vous voudrez peut-être aussi envisager un changement d’attention et un échec intentionnel (bien que je ne pense pas que ce soit la meilleure solution pour ce que vous dites).

 switch (num) { case 1: case 2: case 3: {DO STUFF} break; default: //do nothing. } 

Je viens d’avoir un problème similaire et je suis venu à ces solutions C ++ 11:

 template  struct Is { T d_; bool in(T a) { return a == d_; } template  bool in(Arg a, Args... args) { return in(a) || in(args...); } }; template  Is is(T d) { return Is{d}; } 

Ou comme alternative sans la méthode de terminaison de récursivité. Sachez qu’ici l’ordre des comparaisons n’est pas défini et qu’il ne se termine pas tôt si la première correspondance est trouvée. Mais le code est plus compact.

 template  struct Is { const T d_; template  bool in(Args... args) { bool r{ false }; [&r](...){}(( (r = r || d_ == args), 1)...); return r; } }; template  Is is(T d) { return Is{d}; } 

Donc, pour les deux solutions, le code ressemblerait à ceci:

 if (is(num).in(1,2,3)) { // do whatever needs to be done } 

Vous pouvez définir un ensemble d’entiers, y append les valeurs souhaitées, puis utiliser la méthode find pour voir si la valeur en question est dans l’ensemble.

 std::set values; // add the desired values to your set... if (values.find(target) != values.end()) ... 

Je devais faire quelque chose de similaire pour les enums. J’ai une variable et souhaite la tester par rapport à une plage de valeurs.

Ici, j’ai utilisé une fonction de modèle variadique. Notez la spécialisation pour le type const char* , de sorte que is_in( my_str, "a", "b", "c") ait le résultat attendu pour le moment où my_str "a" .

 #include  template constexpr bool is_in(T t, T v) { return t == v; } template<> constexpr bool is_in(const char* t, const char* v) { return std::strcmp(t,v); } template constexpr bool is_in(T t, T v, Args... args) { return t==v || is_in(t,args...); } 

Exemple d’utilisation:

 enum class day { mon, tues, wed, thur, fri, sat, sun }; bool is_weekend(day d) { return is_in(d, day::sat, day::sun); }