using enums for flags
Era Scarecrow
rtcvb32 at yahoo.com
Wed Jan 25 16:26:00 PST 2012
> 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);
}
More information about the Digitalmars-d
mailing list