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