Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quick way to check a range of enum values

Tags:

c++

enums

Is there a quick/oneline way of synatx weirdness that allows you to check if an enum has a value of the ones specified?

Example:

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;
}

Thanks!

like image 440
rubenvb Avatar asked Dec 09 '10 19:12

rubenvb


People also ask

How do I get all the values in an enum list?

Use a list comprehension to get a list of all enum values, e.g. values = [member. value for member in Sizes] . On each iteration, access the value attribute on the enum member to get a list of all of the enum's values.

How do you find the value of an enum number?

Get the value of an Enum To get the value of enum we can simply typecast it to its type. In the first example, the default type is int so we have to typecast it to int. Also, we can get the string value of that enum by using the ToString() method as below.

How do you find the enum size?

In both C and C++, the size of an enumerator sizeof(enumStruc_2) is the size of any individual element in that enumeration. In C, the answer is sizeof(int) . So that's at least 2. In C++, the answer is sizeof(std::underlying_type<enumStruc_2>::type) .

Can you index enums?

Yes you can programmatically index an enum, text, or menu ring.


2 Answers

Not that I am aware of, but what you can do is assign values 2^i to the enum members. For instance:

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

Then you can check with

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

Of course, this is limited to enums with a reasonable size (I think you can have up to 32 elements).

EDIT

If you have more than 32 (64) values, you have to be more creative than this. By doing several checks, you can still be reasonably quick:

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;
}

But that is not really a great solution. If you have a large number of enums and they can be partitioned into several classes, then I would go with Noah Roberts' answer.

like image 66
bitmask Avatar answered Dec 10 '22 19:12

bitmask


Ah, this can be done fairly easily...

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;
}

This can then be used like so:

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

but won't work if you do (apple || (pear || orange)). This can be fixed easily but I wanted to keep the code simple. I believe that this is the only answer so far that actually scales to large enums...

like image 27
Chris Hopman Avatar answered Dec 10 '22 17:12

Chris Hopman