2010-12-09 3 views
7

Existe-t-il une méthode rapide/en ligne d'étrangeté synatx qui vous permet de vérifier si une énumération a une valeur de celles spécifiées?Méthode rapide de vérification d'une plage de valeurs enum

Exemple:

enum fruit_and_vegetables 
{ 
    apples, 
    pears, 
    tomatoes, 
    cucumbers 
} 

int main() 
{ 
    fruit_and_vegetables something = apples; 
    if(something = {apples, pears}) // <-- this here 
     cout << "something is fruit." << endl; 
    else 
     cout "something is a vegetable." << endl; 
    return 0; 
} 

Merci!

+2

Tomates et concombres * sont * fruits ;-P –

+0

non selon la SCOTUS: http://en.wikipedia.org/wiki/Tomato#Fruit_or_vegetable.3F –

+0

@Noah: '' tomates sont * et pas 'tomates est *' – ruslik

Répondre

4

Ah, cela peut être fait Assez facilement...

template <typename T> 
pair<T, fruit_and_vegetables> operator||(T t, fruit_and_vegetables v) { 
    return make_pair(t, v); 
} 

template <typename T> 
bool operator==(fruit_and vegetables lhs, pair<T, fruit_and_vegetables> rhs) { 
    return lhs == rhs.second || lhs == rhs.first; 
} 

Cela peut ensuite être utilisé comme ceci:

if (something == (apple || pear || orange)) eat_the_yummy_fruit(something); 
else feed_to_rabbit(something) 

mais ne fonctionnera pas si vous le faites (apple || (pear || orange)). Cela peut être corrigé facilement mais je voulais garder le code simple. Je crois que c'est la seule réponse à ce jour qui s'échelonne en réalité à de grandes enums ...

+0

Y aurait-il un moyen de faire fonctionner les grandes cuisinières? Ce serait purement par intérêt, votre solution me permet de faire ce que je veux parfaitement! Merci. – rubenvb

4

if (something < tomatoes)...

+1

Ah oui, '' Pourquoi n'ai-je pas pensé à ça '' (C) '... mais que se passe-t-il si l'énumération a des valeurs intermédiaires et que mon exemple devient plus compliqué/non trié? – rubenvb

5

Non pas que je suis au courant, mais ce que vous pouvez faire attribuer des valeurs 2^i aux membres de ENUM. Par exemple:

enum fruit_and_vegetables 
{ 
    apples = (1<<0), 
    pears  = (1<<1), 
    tomatoes = (1<<2), 
    cucumbers = (1<<3) 
    // ... 
} 

Ensuite, vous pouvez vérifier avec

if (something & (apples | pears | tomatoes)) 
    std::cout << "is tasty" << std::endl; 

Bien sûr, cela se limite à des énumérations avec une taille raisonnable (je pense que vous pouvez avoir jusqu'à 32 éléments).

EDIT

Si vous avez plus de 32 valeurs (64), vous devez être plus créatif que cela. En faisant plusieurs contrôles, vous pouvez toujours être assez rapide:

enum fruit_and_vegetables { 
    apples = 1, //! 
    pears, 
    tomatoes, 
    cucumbers, 
    // ... 
    grapes 
} 
#define FRUIT_AND_VEGETABLES 120 

if ( (1<<something)  & ((1<<apples) | (1<<pears) | (1<<tomatoes)) 
    || (1<<(something-32) & ((1<<(apples-32)) | (1<<(pears-32)) | (1<<(tomatoes-32)))) 
    || ...) { 
    std::cout << "my keyboard is broken, but tastes good" << std::endl; 
} 

Mais ce n'est pas vraiment une excellente solution. Si vous avez un grand nombre d'énumérations et qu'elles peuvent être partitionnées en plusieurs classes, alors je choisirais Noah Roberts' answer.

+1

-1 pour prétendre que les tomates sont savoureuses! j/k Bien que je dirai qu'au moment où vous commencez à vouloir ce genre de comportement de votre énumération, une énumération n'est pas vraiment une construction appropriée pour le comportement que vous voulez. –

+2

Vous plaisantez! Les tomates sont géniales! – bitmask

+2

@bitmask: que se passe-t-il si l'énumération contient 70 membres? cette approche leftshift ne fonctionnerait pas! – Nawaz

1

Il y a une autre façon, qui étend la réponse @bitmask:

Supposons qu'il y ait un nombre fixe de critères que vous pouvez vérifier. Ainsi, au lieu d'utiliser bitmask pour les valeurs de fruit_and_vegetables ENUM (qui vous limite à la taille du mot), vous pouvez utiliser LUT supplémentaire:

enum fruit_and_vegetables { 
    apples = 0, 
    pears, 
    tomatoes, 
    cucumbers 
} 

enum qualifs { 
    is_fruit = 1, 
    is_sweet = 1<<1, 
    is_round = 1<<2, 
    is_tasty = 1<<3 
} 

const qualifs qualifs_LUT[] = { // can be generated 
    is_fruit | is_sweet | is_round, // apple 
    ... 
}; 

afin que la vérification d'un testament de qualification spécifique est devenu

if (qualifs_LUT[tomato] & is_tasty) 

EDIT: et une autre méthode intéressante. Considérons (encore une fois) la méthode @bitmask: Il s'appuie sur les pouvoirs de 2. Mais qu'en est-il des nombres premiers? Ils se développent beaucoup plus lentement, en assignant des nombres premiers aux valeurs ENUM, vous pouvez squize plus de valeurs, en supposant que le produit ne débordera pas:

enum fruit_and_vegetables { 
    apples = 2, 
    pears = 3, 
    tomatoes = 5, 
    cucumbers = 7 
} 

if ((apples * pears * tomatoes) % tomatoes == 0) 
    printf("it's tasty!"); 

celui-ci limite le nombre d'éléments dans l'ensemble de commande.

+0

love it! (Mais vous devriez probablement faire le lut 'const') – bitmask

+0

@bitmask: bien, c'est juste un détail d'implémentation :) – ruslik

+0

Je sais, mais j'ai dû remplir 15 caractères :) – bitmask

1

Vous pouvez écrire modèle d'aide qui vous aidera à atteindre la syntaxe que vous voulez:

enum fruit_and_vegetables 
{ 
    nothing, 
    apples, 
    pears, 
    tomatoes, 
    cucumbers 
}; 

// helper template 
typedef fruit_and_vegetables fav; 
template<fav v1 = nothing, fav v2 = nothing, fav v3 = nothing, fav v4 = nothing, 
    fav v5 = nothing, fav v6 = nothing, fav v7 = nothing, fav v8 = nothing> 
bool check_equal(fruit_and_vegetables value) 
{ 
    return (value == v1 || value == v2 || value == v3 || value == v4 || 
      value == v5 || value == v6 || value == v7 || value == v8); 
} 

// usage 
int main() 
{ 
    fruit_and_vegetables something = apples; 
    if(check_equal<apples, pears>(something)) 
     std::cout << "something is fruit." << std::endl; 
    else 
     std::cout << "something is a vegetable." << std::endl; 

    return 0; 
} 
+0

C'est la même chose que de vérifier chaque valeur à la main. OP a demandé une méthode plus rapide que l'évidence. – ruslik

+1

OP a posé une question sur la syntaxe simple: "la voie en ligne de l'étrangeté synatx". –

1

Pour gérer plus, ensembles non triés de produits:

enum fruit_and_vegetables 
{ 
    apples, 
    pears, 
    tomatoes, 
    cucumbers, 
    MAX_VALUE 
}; 

vector<bool> arguablyVegetables(MAX_VALUE, false); 
arguablyVegetables[tomatoes] = true; 
arguablyVegetables[cucumbers] = true; 

cout << arguablyVegetables[apples] << endl; 
1

pourquoi ne pas utiliser un set<fruit_and_vegetables> pour logique-ou-plusieurs plusieurs fruit_and_vegetables? si vous mettez constexpr avant que l'opérateur || et opérateur == surcharges, ainsi que devant les arguments et les types de résultats, le compilateur évaluera votre code à la compilation (pas de frais généraux d'exécution) si possible;) échelles bien plus grandes plages a || b || c || c enum et vous pouvez mettre les valeurs entre parenthèses comme vous s'il vous plaît.

#include <set> 
using std::set; 

enum fruit_and_vegetables 
{ 
    apples, 
    pears, 
    tomatoes, 
    cucumbers 
}; 

set<fruit_and_vegetables> operator||(fruit_and_vegetables left, fruit_and_vegetables right) { 
    set<fruit_and_vegetables> set; 
    set.insert(left); 
    set.insert(right); 
    return set; 
} 

set<fruit_and_vegetables> operator||(set<fruit_and_vegetables> left, fruit_and_vegetables right) { 
    left.insert(right); 
    return left; 
} 

set<fruit_and_vegetables> operator||(fruit_and_vegetables left, set<fruit_and_vegetables> right) { 
    right.insert(left); 
    return right; 
} 

bool operator!=(fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs) { 
    return (rhs.find(lhs) == rhs.end()); 
} 

bool operator==(fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs) { 
    return !(lhs != rhs); 
} 

int main() { 

fruit_and_vegetables fav = apples; 
if (fav == (apples || (pears || tomatoes))) cout << "match apples\n"; 
fav = cucumbers; 
if (fav == ((apples || pears) || tomatoes)) cout << "Error! matched ghost cucumbers\n"; 
if (fav != apples) cout << "correct no match apples\n"; 
if (fav == cucumbers) cout << "default operator==(FaV, FaV) match\n"; 
if (fav == (pears || apples)) cout << "yummi\n"; 

return 0; 
} 
Questions connexes