Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a good design to add an "all" option to an enum in C++?

I have an enum class as follows:

enum class Age
{
    Eleven,
    Twelve,
    Thirteen
};

Then I have a method called vector<Person> GetPeopleOfAge(Age age). What would be a good design so that a developer can call this and get the people with 11, 12 and 13? I can call it three times which is pretty bad but I did want to mention that I considered it. I can add an All enumeration and do a check in my method but I don't like the idea of polluting the enum with enumerations like All just to make my case work. I know it's a common method of solving this and some may disagree with me but to me it feels hacky and am looking for an alternative. Maybe I should use something other than an enum?

like image 854
Pittfall Avatar asked Jan 05 '18 14:01

Pittfall


3 Answers

Whether All is captured explicitly in the enum or implicitly by another mechanism, you have to deal with the abstraction. Given that, I find it better to deal with it explicitly.

You can use the established method of using values of enums such that they can be combined using bitwise OR operators.

enum Age : unsigned int
{
   Eleven   = 000001,
   Twelve   = 000010,
   Thirteen = 000100,
   All      = 000111
};

Then, you can use

// Get all the people of age 11
auto ret1 = GetPeopleOfAge(Age::Eleven);

// Get people of all ages
auto ret2 = GetPeopleOfAge(Age::All);

// Get all the people aged 11 or 13
auto ret3 = GetPeopleOfAge(Age::Eleven | Age::Thirteen);
like image 171
R Sahu Avatar answered Oct 21 '22 03:10

R Sahu


The obvious solution is to dump the enum: Age is a continuous concept, that may be quantized, but never fully enumerated (What is your highest supported age? 120? 130? 200? 1000? Your choice will be either insensibly large, or have the potential to exclude real persons!). Also, when you talk about age, you frequently need to select ranges of ages.

Consequently, age should be either an int or a float. And your GetPeopleOfAge() function should be declared as

vector<Person> GetPeopleOfAge(int minAge, int maxAge);

No need to complicate things with an enum.

like image 41
cmaster - reinstate monica Avatar answered Oct 21 '22 03:10

cmaster - reinstate monica


One option is to make the filter parameter optional:

vector<Person> GetPeopleOfAge(std::optional<Age> age = {})

Then, inside the function, use if (age) to check whether age-based filtering should be done or not.

The function should probably be renamed, though, because it does not always give people of a certain age; sometimes, it gives all people.

like image 34
Angew is no longer proud of SO Avatar answered Oct 21 '22 05:10

Angew is no longer proud of SO