www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: using enums for flags

 On Wednesday, January 25, 2012 03:22:03 Trass3r wrote:
 So I was just reading
 http://stackoverflow.com/questions/1448396/how-to-use-enums-as-flags-in-c
 
 And did a quick test:

I think that it makes sense to use enums as flags, but I do _not_ think that it makes sense to use an enum as the type of the variable _holding_ the flags. STC var = STC.A & STC.B; is an abimination IMHO. adding another enum to the list and doing something like STC var = STC.A & FOO.F; just makes it worse. It should be something like uint var = STC.A & FOO.F; instead. Now anding two different enums like that is still a bit weird, but I don't know that it should really be illegal. It's assigning anded enums to an enum that I want to see die. I'd _love_ it if that were illegal. For instance, std.socket uses flag enums, which is fine, but in some places it uses them as the type of function parameters, which is _not_ a good idea IMHO. Whenever I think about it, I keep meaning to go and fix it, but I never get around to it.

Indeed. enum should be only a single value, be it a number like 42, or a binary bit 1<<42. The type checking enforces it to be a valid value. You can easily turn a enum into an int, but the other direction as said before, is not so easy. I started on C++ recently and came across that problem, and came across this solution (ported shortly after to D). Here's my unittests. (they pass) unittest{ enum ETEST { none = 0, one = 1, two = 2, four = 4 } alias ETEST.none none; alias ETEST.one one; alias ETEST.two two; alias ETEST.four four; HandleFlags!(ETEST, int) ftest; //test all flags off. Uses int checks. assert(ftest.state == 0); //start empty. //set 2 flag ftest.setFlag(two, true); assert(ftest.state == 2); //set 4, should now be 6 ftest.setFlag(four, true); assert(ftest.state == 6); //turn off 2 bit ftest.setFlag(two, false); assert(ftest.state == 4); //flip 1 ftest.flipFlag(one); //4+1 assert(ftest.state == 5); //flip 1 again. ftest.flipFlag(one); //4+0 assert(ftest.state == 4); //check truth/else ETEST x = ftest.checkElse(four, none); assert(x == four); x = ftest.checkElse(one, none); assert(x == none); assert(ftest.check(four) == true); assert(ftest.check(two) == false); }
Jan 25 2012