7

I have an enum and I want to put them all in the set( and then remove some with set_intersection algorithm, but that is offtopic). All works great except Im stuck on step 1. :)

If I have(real class has enum with higher cardinality)

class MyClass
{
enum Color{red, green , blue}
};

How would I init a std::set<MyClass::Color> to contain all enums.
I can obviously manually insert them one by one, do a for loop with casting since they are consecutive and start from 0 (I think that is required if I dont use = in enum definition), but Im looking for a more elegant way.

EDIT: I prefer C++03 solution if possible because current instance of problem requires it, but if not C++11 is good to know too.

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 2
    if they are consecutive and starting from zero, you can add `total` as last enum's element, which value becomes equal to number of values =) – kassak Mar 14 '13 at 14:11
  • 1
    Good remark from @kassak `total` or `colors_count` as a last element of enum is very useful in many cases – borisbn Mar 14 '13 at 14:24
  • @kassak I know of that trick, but it depends on CAPS LOCK comments preventing ppl to go and define int value of each enum. :) – NoSenseEtAl Mar 14 '13 at 14:28

3 Answers3

8

This is an option:

#define COLORS {red, green , blue}
enum Color COLORS;
static std::set<Color> color_set() {
    return COLORS;
}
#undef COLORS
Pubby
  • 51,882
  • 13
  • 139
  • 180
  • @NoSenseEtAl Yes, initializer lists. – Pubby Mar 14 '13 at 14:14
  • I edited Q to say i prefer 03 if possible, but if this is the only nice way to do it Ill accept your A. Sorry for not mentioning it in initial Q. :) – NoSenseEtAl Mar 14 '13 at 14:15
  • 2
    If you don't have initializer lists, you can do something like `Color colors[] = COLORS; return std::set(colors, colors + sizeof(colors) / sizeof(*colors));` – Steve Jessop Mar 14 '13 at 14:16
  • 1
    @NoSenseEtAl in 03 you could define without braces, and then pass comma separated list to boost assign – kassak Mar 14 '13 at 14:18
  • @SteveJessop ah, good old array initialization of STL containers :) tnx – NoSenseEtAl Mar 14 '13 at 14:20
  • @SteveJessop I'd add `static` before `Color colors[] = COLORS;` – borisbn Mar 14 '13 at 14:23
  • @borisbn: if you like. I don't think it makes much difference: each call to this function constructs a `set`, so I don't really care whether or not it also initializes the array every time :-) – Steve Jessop Mar 14 '13 at 14:24
  • In my view any solution that uses `#define` is by definition inelegant. I would view this code has substantially less elegant than the loop option rejected by the OP. – Jack Aidley Mar 14 '13 at 18:28
  • 1
    @JackAidley: `#define` are oftentimes inelegant because they can be really hard to read. But in this case, I think it's actually really easy to read, and the resulting code is very short and concise. – Nicu Stiurca Mar 16 '13 at 17:22
4

Use a std::bitset< total_colors >. That is a more appropriate data structure for a set over a finite space. Each color maps to a Boolean value, representing whether or not it is part of the set. You can initialize it to all true's using my_bitset.set().

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
0

Personally I'd use a loop, and just cast the things as I go.

However, if you're dead set against casts you could define operators on the enum so you can iterate over them using ++. That way you can loop without casting.

Jack Aidley
  • 19,439
  • 7
  • 43
  • 70