www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - using enums for flags

reply Trass3r <un known.com> writes:
So I was just reading  
http://stackoverflow.com/questions/1448396/how-to-use-enums-as-flags-in-c

And did a quick test:

enum STC
{
	A = 0x1,
	B = 0x2,
	C = 0x4
}
enum FOO
{
	F = 0x8,
	G = 0x10
}

void main()
{
	STC s = STC.A | STC.C;
	STC s2 = s & STC.A;
	auto s2_2 = s & STC.A;
	static assert(is(typeof(s2_2) == STC));

	static assert(!__traits(compiles, { if (s & FOO.F) {} }));       //  
fails. that one's hard to track down
	static assert(!__traits(compiles, { auto s3 = s & FOO.F; }));    //  
fails, cause implicitly converts to int
	static assert(!__traits(compiles, { STC s4 = s & FOO.F; }));
	static assert(!__traits(compiles, { FOO s5 = s & FOO.F; }));

	static assert(!__traits(compiles, { STC t = STC.A | FOO.F; }));
	static assert(!__traits(compiles, { auto t = STC.A | FOO.F; })); // fails

	static assert(!__traits(compiles, { if (s & STC.B == 0) {} }));  //  
works, but error not gagged
	static assert(!__traits(compiles, { if (s && STC.B) {} }));      // fails
}

Does it really make sense to allow bitwise operations on different enums?
There should at least be some way to get this straight without having to  
resort to a heap of code like in C++:  
http://www.artima.com/cppsource/safelabels.html
Jan 24 2012
next sibling parent reply =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
------------JSze7Hnt9chMB3HebjSp6t
Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes
Content-Transfer-Encoding: 7bit

On Wed, 25 Jan 2012 03:22:03 +0100, Trass3r <un known.com> wrote:

 Does it really make sense to allow bitwise operations on different enums?

Maybe. Certainly sometimes, but those could just as easily use casts.
 There should at least be some way to get this straight without having to  
 resort to a heap of code like in C++:  
 http://www.artima.com/cppsource/safelabels.html

Well, it may be a heap of code, but it's a lot less than what you linked. Example attached. It's WTFPL or freer, so feel free to use it as you wish. ------------JSze7Hnt9chMB3HebjSp6t Content-Disposition: attachment; filename=flags.d Content-Type: application/octet-stream; name="flags.d" Content-Transfer-Encoding: Base64 77u/bW9kdWxlIGZsYWdzOwoKaW1wb3J0IHN0ZC50eXBldHVwbGU7CmltcG9ydCBz dGQuYXJyYXk7CgpwdXJlOgpub3Rocm93OgpAc2FmZToKcHJpdmF0ZToKCnRlbXBs YXRlIGlzVmFsaWRGbGFnRW51bUJvZHkoIHN0cmluZyBzICkgewoJZW51bSBpc1Zh bGlkRmxhZ0VudW1Cb2R5ID0gX190cmFpdHMoIGNvbXBpbGVzLCB7IG1peGluKCAi ZW51bSBmb28geyAiIH4gcyB+ICIgfSIgKTsgfSApOwp9Cgp1bml0dGVzdCB7Cglh c3NlcnQoIGlzVmFsaWRGbGFnRW51bUJvZHkhcXthfSApOwoJYXNzZXJ0KCBpc1Zh bGlkRmxhZ0VudW1Cb2R5IXF7YSxifSApOwoJYXNzZXJ0KCAhaXNWYWxpZEZsYWdF bnVtQm9keSFxe2EufSApOwp9Cgp0ZW1wbGF0ZSBNYWtlRW51bSggc3RyaW5nIHMg KSB7CgltaXhpbiggImVudW0gTWFrZUVudW0geyAiIH4gcyB+ICIgfSIgKTsKfQoK dGVtcGxhdGUgcGFyc2VkU3RyaW5nKCBzdHJpbmcgcyApIHsKCWFsaWFzIFR5cGVU dXBsZSEoIF9fdHJhaXRzKCBhbGxNZW1iZXJzLCBNYWtlRW51bSFzICkgKSBwYXJz ZWRTdHJpbmc7Cn0KCnVuaXR0ZXN0IHsKCWFzc2VydCggcGFyc2VkU3RyaW5nISJh IlswXSA9PSAiYSIgKTsKCWFzc2VydCggcGFyc2VkU3RyaW5nISJhIi5sZW5ndGgg PT0gMSApOwoJYXNzZXJ0KCBwYXJzZWRTdHJpbmchImEsYiJbMF0gPT0gImEiICk7 Cglhc3NlcnQoIHBhcnNlZFN0cmluZyEiYSxiIlsxXSA9PSAiYiIgKTsKCWFzc2Vy dCggcGFyc2VkU3RyaW5nISJhLGIiLmxlbmd0aCA9PSAyICk7Cn0KCi8qKgpSZXBy ZXNlbnRzIGEgc2V0IG9mIGZsYWdzLgoKVGhlc2UgY2FuIGJlIG1hbmlwdWxhdGVk IHZpYSByZWd1bGFyIGJpdHdpc2Ugb3BlcmF0b3JzIC0gfCwgJiwgYW5kIF4uCgpF eGFtcGxlOgotLS0tCmFsaWFzIEZsYWdzIXF7CiAgICBBLAoJQgp9IG15RmxhZ3M7 Cm15RmxhZ3MgYSA9IG15RmxhZ3MuQSB8IG15RmxhZ3MuQjsKYXNzZXJ0KCBhICYg bXlGbGFncy5BICk7CmFzc2VydCggYSAmIG15RmxhZ3MuQiApOwotLS0tCioqLwpw dWJsaWMKc3RydWN0IEZsYWdzKCBzdHJpbmcgcyApIGlmICggaXNWYWxpZEZsYWdF bnVtQm9keSFzICYmIHBhcnNlZFN0cmluZyFzLmxlbmd0aCA8PSA2NCApIHsKCXBy aXZhdGUgYWxpYXMgcGFyc2VkU3RyaW5nIXMgbWVtYmVyTmFtZXM7CglzdGF0aWMg aWYgKCBtZW1iZXJOYW1lcy5sZW5ndGggPD0gOCApIHsKCQlwcml2YXRlIGFsaWFz IHVieXRlIFJlcHJlc2VudGF0aW9uOwoJfSBlbHNlIHN0YXRpYyBpZiAoIG1lbWJl ck5hbWVzLmxlbmd0aCA8PSAxNiApIHsKCQlwcml2YXRlIGFsaWFzIHVzaG9ydCBS ZXByZXNlbnRhdGlvbjsKCX0gZWxzZSBzdGF0aWMgaWYgKCBtZW1iZXJOYW1lcy5s ZW5ndGggPD0gMzIgKSB7CgkJcHJpdmF0ZSBhbGlhcyB1aW50IFJlcHJlc2VudGF0 aW9uOwoJfSBlbHNlIHN0YXRpYyBpZiAoIG1lbWJlck5hbWVzLmxlbmd0aCA8PSA2 NCApIHsKCQlwcml2YXRlIGFsaWFzIHVsb25nIFJlcHJlc2VudGF0aW9uOwoJfQoJ cHJpdmF0ZSBSZXByZXNlbnRhdGlvbiB2YWx1ZTsKCgltaXhpbiB0ZW1wbGF0ZSBm bGFnc01lbWJlcnMoIGludCBOICkgewoJfQoKCW1peGluIHRlbXBsYXRlIGZsYWdz TWVtYmVycyggaW50IE4sIHN0cmluZyBULCBVLi4uICkgewoJCW1peGluKCAiZW51 bSAiIH4gVCB+ICIgPSBGbGFncyggMUwgPDwgTiApOyIgKTsKCQltaXhpbiBmbGFn c01lbWJlcnMhKCBOICsgMSwgVSApOwoJfQoJCgltaXhpbiBmbGFnc01lbWJlcnMh KCAwLCBtZW1iZXJOYW1lcyApOwoJCglwcml2YXRlIHRoaXMoIFJlcHJlc2VudGF0 aW9uIHZhbHVlICkgewoJCXRoaXMudmFsdWUgPSB2YWx1ZTsKCX0KCQoJRmxhZ3Mg b3BCaW5hcnkoIHN0cmluZyBvcCApKCBGbGFncyBvdGhlciApIGNvbnN0IGlmICgg b3AgPT0gInwiIHx8IG9wID09ICJeIiB8fCBvcCA9PSAiJiIgKSB7CgkJbWl4aW4o ICJyZXR1cm4gRmxhZ3MoIHZhbHVlICIgfiBvcCB+ICIgb3RoZXIudmFsdWUgKTsi ICk7Cgl9CgkKCXJlZiBGbGFncyBvcE9wQXNzaWduKCBzdHJpbmcgb3AgKSggRmxh Z3Mgb3RoZXIgKSBpZiAoIG9wID09ICJ8IiB8fCBvcCA9PSAiXiIgfHwgb3AgPT0g IiYiICkgewoJCW1peGluKCAidmFsdWUgIiB+IG9wIH4gIj0gb3RoZXIudmFsdWU7 IiApOwoJCXJldHVybiB0aGlzOwoJfQoJCglSZXByZXNlbnRhdGlvbiBvcENhc3Qo IFQgKSggKSBjb25zdCBpZiAoIGlzKCBSZXByZXNlbnRhdGlvbiA6IFQgKSApIHsK CQlyZXR1cm4gdmFsdWU7Cgl9CgkKCWJvb2wgb3BDYXN0KCBUIDogYm9vbCApKCAp IGNvbnN0IHsKCQlyZXR1cm4gdmFsdWUgIT0gMDsKCX0KCQoJQHRydXN0ZWQKCXN0 cmluZyB0b1N0cmluZyggKSBjb25zdCB7CgkJc3RyaW5nW10gcmVzdWx0OwoJCQoJ CWZvcmVhY2ggKGksIGU7IG1lbWJlck5hbWVzKSB7CgkJCWlmICh2YWx1ZSAmICgg MUwgPDwgaSApICkgewoJCQkJcmVzdWx0IH49IGU7CgkJCX0KCQl9CgkJCgkJcmV0 dXJuICI8IiB+IHJlc3VsdC5qb2luKCIsICIpIH4gIj4iOwoJfQp9Cgp1bml0dGVz dCB7CgkvLyBUZXN0IHNpemVzIG9mIGNyZWF0ZWQgdHlwZXMuCglhbGlhcyBGbGFn cyEiYSIgbXlGbGFnczE7CglhbGlhcyBGbGFncyEiYSxiLGMsZCxlLGYsZyxoLGks aixrLGwsbSxuLG8scCIgbXlGbGFnczI7CglhbGlhcyBGbGFncyEiYTEsYjEsYzEs ZDEsZTEsZjEsZzEsaDEsaTEsajEsazEsbDEsbTEsbjEsbzEscDEsczEsYTIsYjIs YzIsZDIsZTIsZjIsZzIsaDIsaTIsajIsazIsbDIsbTIsbjIsbzIiIG15RmxhZ3Mz OwoJYWxpYXMgRmxhZ3MhImExLGIxLGMxLGQxLGUxLGYxLGcxLGgxLGkxLGoxLGsx LGwxLG0xLG4xLG8xLHAxLHMxLGEyLGIyLGMyLGQyLGUyLGYyLGcyLGgyLGkyLGoy LGsyLGwyLG0yLG4yLG8yLHAyLHMyLGEzLGIzLGMzLGQzLGUzLGYzLGczLGgzLGkz LGozLGszLGwzLG0zLG4zLG8zLHAzLHMzLGE0LGI0LGM0LGQ0LGU0LGY0LGc0LGg0 LGk0LGo0LGs0LGw0LG00IiBteUZsYWdzNDsKCWFzc2VydCggbXlGbGFnczEuc2l6 ZW9mID09IDEgKTsKCWFzc2VydCggbXlGbGFnczIuc2l6ZW9mID09IDIgKTsKCWFz c2VydCggbXlGbGFnczMuc2l6ZW9mID09IDQgKTsKCWFzc2VydCggbXlGbGFnczQu c2l6ZW9mID09IDggKTsKCQoJLy8gVGVzdCB0aGF0IHZhbGlkIHR5cGVzIGRvIGNv bXBpbGUsIGFuZCBpbnZhbGlkIHR5cGVzIG5vdC4KCWFzc2VydCggX190cmFpdHMo IGNvbXBpbGVzLCBGbGFncyEiYSIgKSApOwoJYXNzZXJ0KCBfX3RyYWl0cyggY29t cGlsZXMsIEZsYWdzISJhLCBiIiApICk7Cglhc3NlcnQoICFfX3RyYWl0cyggY29t cGlsZXMsIEZsYWdzISIiICkgKTsKCWFzc2VydCggIV9fdHJhaXRzKCBjb21waWxl cywgRmxhZ3MhImEuIiApICk7Cglhc3NlcnQoICFfX3RyYWl0cyggY29tcGlsZXMs IEZsYWdzISJhMSxiMSxjMSxkMSxlMSxmMSxnMSxoMSxpMSxqMSxrMSxsMSxtMSxu MSxvMSxwMSxzMSxhMixiMixjMixkMixlMixmMixnMixoMixpMixqMixrMixsMixt MixuMixvMixwMixzMixhMyxiMyxjMyxkMyxlMyxmMyxnMyxoMyxpMyxqMyxrMyxs MyxtMyxuMyxvMyxwMyxzMyxhNCxiNCxjNCxkNCxlNCxmNCxnNCxoNCxpNCxqNCxr NCxsNCxtNCxuNCIgKSApOwoJCglhbGlhcyBGbGFncyFxeyBhLCBiIH0gdGVzdEZs YWdzOwoJCgkvLyBUZXN0IHRoYXQgb3BlcmF0b3JzIHdvcmsuCglhdXRvIG8gPSB0 ZXN0RmxhZ3MuYSB8IHRlc3RGbGFncy5iOwoJYXNzZXJ0KCBvICE9IHRlc3RGbGFn cy5hICk7Cglhc3NlcnQoIG8gIT0gdGVzdEZsYWdzLmIgKTsKCWFzc2VydCggby52 YWx1ZSAhPSAwICk7CgkKCWF1dG8gcCA9IG8gXiB0ZXN0RmxhZ3MuYTsKCWFzc2Vy dCggcCA9PSB0ZXN0RmxhZ3MuYiApOwoJYXNzZXJ0KCBwICE9IHRlc3RGbGFncy5h ICk7CgkKCWF1dG8gcSA9IG8gJiB0ZXN0RmxhZ3MuYTsKCWFzc2VydCggcSA9PSB0 ZXN0RmxhZ3MuYSApOwoJYXNzZXJ0KCBvICE9IHRlc3RGbGFncy5iICk7CgkKCW8g Jj0gdGVzdEZsYWdzLmE7Cglhc3NlcnQoIG8gPT0gdGVzdEZsYWdzLmEgKTsKCQoJ cCB8PSB0ZXN0RmxhZ3MuYTsKCWFzc2VydCggcCA9PSAoIHRlc3RGbGFncy5hIHwg dGVzdEZsYWdzLmIgKSApOwoJCglxIF49IHRlc3RGbGFncy5hOwoJYXNzZXJ0KCBx LnZhbHVlID09IDAgKTsKCQoJCgkvLyBUZXN0IHRvU3RyaW5nLgoJYXNzZXJ0KCB0 ZXN0RmxhZ3MuYS50b1N0cmluZygpID09ICI8YT4iICk7Cglhc3NlcnQoIHRlc3RG bGFncy5iLnRvU3RyaW5nKCkgPT0gIjxiPiIgKTsKCWFzc2VydCggKCB0ZXN0Rmxh Z3MuYSB8IHRlc3RGbGFncy5iICkudG9TdHJpbmcoKSA9PSAiPGEsIGI+IiApOwoJ YXNzZXJ0KCB0ZXN0RmxhZ3MoKS50b1N0cmluZygpID09ICI8PiIgKTsKCQoJLy8g VGVzdCBjYXN0aW5nLgoJYXNzZXJ0KCAhdGVzdEZsYWdzKCkgKTsKCWFzc2VydCgg dGVzdEZsYWdzLmEgKTsKCWFzc2VydCggdGVzdEZsYWdzLmIgKTsKCWFzc2VydCgg dGVzdEZsYWdzLmEgfCB0ZXN0RmxhZ3MuYiApOwoJYXNzZXJ0KCBjYXN0KGJvb2wp dGVzdEZsYWdzKCkgPT0gZmFsc2UgKTsKCWFzc2VydCggY2FzdChib29sKXRlc3RG bGFncy5hID09IHRydWUgKTsKCWFzc2VydCggY2FzdChpbnQpdGVzdEZsYWdzKCkg PT0gMCApOwoJYXNzZXJ0KCBjYXN0KGludCl0ZXN0RmxhZ3MuYSAhPSAwICk7CgkK CS8vIFRlc3QgaW52YWxpZCBjb21wYXJpc29ucy4KCWFzc2VydCggIV9fdHJhaXRz KCBjb21waWxlcywgeyB0ZXN0RmxhZ3MuYSA9PSAxOyB9ICkgKTsKCWFzc2VydCgg IV9fdHJhaXRzKCBjb21waWxlcywgeyB0ZXN0RmxhZ3MuYSA9PSB0cnVlOyB9ICkg KTsKCQoJLy8gVGVzdCBpbnZhbGlkIGNvbnZlcnNpb25zLgoJYXNzZXJ0KCAhX190 cmFpdHMoIGNvbXBpbGVzLCB7IGludCBpID0gdGVzdEZsYWdzLmE7IH0gKSApOwoJ YXNzZXJ0KCAhX190cmFpdHMoIGNvbXBpbGVzLCB7IGJvb2wgYiA9IHRlc3RGbGFn cy5hOyB9ICkgKTsKCQoJLy8gVGVzdCBvcGVyYXRvcnMgd2l0aCBpbnZhbGlkIHR5 cGVzLgoJYXNzZXJ0KCAhX190cmFpdHMoIGNvbXBpbGVzLCB7IGF1dG8gdG1wID0g dGVzdEZsYWdzLmIgfCBteUZsYWdzMS5hOyB9ICkgKTsKCWFzc2VydCggIV9fdHJh aXRzKCBjb21waWxlcywgeyBhdXRvIHRtcCA9IHRlc3RGbGFncy5iIHwgMTsgfSAp ICk7Cn0KCnZvaWQgbWFpbiggKSB7fQ== ------------JSze7Hnt9chMB3HebjSp6t--
Jan 25 2012
next sibling parent Trass3r <un known.com> writes:
 Does it really make sense to allow bitwise operations on different  
 enums?


 but those could just as easily use casts.

Seconded. I generally don't see any merit in letting enums *implicitly* convert to their base type.
Jan 25 2012
prev sibling next sibling parent =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Wed, 25 Jan 2012 22:47:49 +0100, Trass3r <un known.com> wrote:

 Does it really make sense to allow bitwise operations on different  
 enums?



In the codebase I have to work with, having the same enum specified in different places is rather common. Yeah, I hate it. This means I might have a filter defined using one enum, and the value to filter being a different type with the same values.
 but those could just as easily use casts.

Seconded. I generally don't see any merit in letting enums *implicitly* convert to their base type.

Jan 25 2012
prev sibling next sibling parent Trass3r <un known.com> writes:
 In the codebase I have to work with, having the same enum specified in
 different places is rather common. Yeah, I hate it. This means I might
 have a filter defined using one enum, and the value to filter being a
 different type with the same values.

Why don't you fix it then?
Jan 25 2012
prev sibling parent =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Thu, 26 Jan 2012 00:49:58 +0100, Trass3r <un known.com> wrote:

 In the codebase I have to work with, having the same enum specified in
 different places is rather common. Yeah, I hate it. This means I might
 have a filter defined using one enum, and the value to filter being a
 different type with the same values.

Why don't you fix it then?

I'm not allowed to. The project I'm on has its tasks, and fixing things in other projects is not one of them, especially when such an easy workaround exists.
Jan 26 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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:
 
 enum STC
 {
 	A = 0x1,
 	B = 0x2,
 	C = 0x4
 }
 enum FOO
 {
 	F = 0x8,
 	G = 0x10
 }
 
 void main()
 {
 	STC s = STC.A | STC.C;
 	STC s2 = s & STC.A;
 	auto s2_2 = s & STC.A;
 	static assert(is(typeof(s2_2) == STC));
 
 	static assert(!__traits(compiles, { if (s & FOO.F) {} }));       //
 fails. that one's hard to track down
 	static assert(!__traits(compiles, { auto s3 = s & FOO.F; }));    //
 fails, cause implicitly converts to int
 	static assert(!__traits(compiles, { STC s4 = s & FOO.F; }));
 	static assert(!__traits(compiles, { FOO s5 = s & FOO.F; }));
 
 	static assert(!__traits(compiles, { STC t = STC.A | FOO.F; }));
 	static assert(!__traits(compiles, { auto t = STC.A | FOO.F; })); // fails
 
 	static assert(!__traits(compiles, { if (s & STC.B == 0) {} }));  //
 works, but error not gagged
 	static assert(!__traits(compiles, { if (s && STC.B) {} }));      // fails
 }
 
 Does it really make sense to allow bitwise operations on different enums?
 There should at least be some way to get this straight without having to
 resort to a heap of code like in C++:
 http://www.artima.com/cppsource/safelabels.html

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. - Jonathan M Davis
Jan 25 2012
prev sibling next sibling parent Trass3r <un known.com> writes:
 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;

We could easily introduce flags enum or whatever to make it more clear like in C#.
 just makes it worse. It should be something like

 uint var = STC.A & FOO.F;

To me it doesn't make any sense at all to allow bitwise operations on different *named* enums. I also don't see why you would really need implicit conversion to the base type.
 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.

You really think int is any better?? No type safety at all.
Jan 25 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, January 26, 2012 01:17:51 Trass3r wrote:
 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;

We could easily introduce flags enum or whatever to make it more clear like in C#.
 just makes it worse. It should be something like
 
 uint var = STC.A & FOO.F;

To me it doesn't make any sense at all to allow bitwise operations on different *named* enums. I also don't see why you would really need implicit conversion to the base type.
 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.

You really think int is any better?? No type safety at all.

What type safety? You're dealing with a uint (or ushort or ulong) with a bunch of specific bits set which represent flags. What other type would you want? You could typedef it I suppose (well, use the TypeDef library type when it's merged in anyway), but you're dealing with a fixed number of bits, which is exactly what an unsigned integer is. It's just a question of which are on and which are off. That's certainly not what _enum_ is for. It's a fixed set of values. And that's my beef with using it as the result of &ing flags. The result isn't one of those flags, so it has no business being an enum. - Jonathan M Davis
Jan 25 2012
prev sibling next sibling parent "Marco Leise" <Marco.Leise gmx.de> writes:
Delphi: http://delphi.about.com/od/beginners/a/delphi_set_type.htm |  
Scroll to: "Sets with Enumerations"
Sets use the smallest integer type that can hold enough bits for the  
number of elements in an enum. So up to 8 enum flags use a byte for  
example. TDaySet in the example code would also be 1 byte in size. As the  
syntax suggests they don't implicitly convert forth or back to integers.
Jan 25 2012
prev sibling next sibling parent Mantis <mail.mantis.88 gmail.com> writes:
26.01.2012 2:40, Jonathan M Davis пишет:
 What type safety? You're dealing with a uint (or ushort or ulong) with a bunch
 of specific bits set which represent flags. What other type would you want? You
 could typedef it I suppose (well, use the TypeDef library type when it's
 merged in anyway), but you're dealing with a fixed number of bits, which is
 exactly what an unsigned integer is. It's just a question of which are on and
 which are off. That's certainly not what _enum_ is for. It's a fixed set of
 values.

 And that's my beef with using it as the result of&ing flags. The result isn't
 one of those flags, so it has no business being an enum.

 -  Jonathan M Davis

Here's an example how current way may lead to unexpected result: enum Foo { A = 1, B } void bar( Foo foo ) { final switch( foo ) { case Foo.A: writeln( "A" ); return; case Foo.B: writeln( "B" ); return; } writeln( "Unreachable branch" ); } int main() { bar( Foo.A | Foo.B ); return 0; } It is intuitive to assume that the final switch will always hit one of it's branches, yet this doesn't work here.
Jan 25 2012
prev sibling next sibling parent reply "Trass3r" <un known.com> writes:
 I agree, enum variable should only contain one of the 
 enumerated values. Here's an example how current way may lead 
 to unexpected result:

 enum Foo { A = 1, B }

 void bar( Foo foo ) {
    final switch( foo ) {
        case Foo.A:
            writeln( "A" );
            return;
        case Foo.B:
            writeln( "B" );
            return;
    }
    writeln( "Unreachable branch" );
 }

 int main() {
    bar( Foo.A | Foo.B );
    return 0;
 }

 It is intuitive to assume that the final switch will always hit 
 one of it's branches, yet this doesn't work here.

Valid example. As I said one could introduce something like flags but I guess a library solution is preferred. I still wonder though if implicit conversion to the basetype has any merit.
Jan 26 2012
parent bearophile <bearophileHUGS lycos.com> writes:
Trass3r:

 As I said one could introduce something like  flags but I guess a 
 library solution is preferred.
 I still wonder though if implicit conversion to the basetype has 
 any merit.

Those are important topics. D must offer a solution that is both safer and more handy than the current one. Bye, bearophile
Jan 26 2012
prev sibling parent "foobar" <foo bar.com> writes:
On Thursday, 26 January 2012 at 01:44:23 UTC, Marco Leise wrote:
 Delphi: 
 http://delphi.about.com/od/beginners/a/delphi_set_type.htm | 
 Scroll to: "Sets with Enumerations"
 Sets use the smallest integer type that can hold enough bits 
 for the number of elements in an enum. So up to 8 enum flags 
 use a byte for example. TDaySet in the example code would also 
 be 1 byte in size. As the syntax suggests they don't implicitly 
 convert forth or back to integers.

vote += MAX_INT for the above suggestion which btw is also the solution in Java 5.0 which provides an EnumSet type. At the moment eums are completely broken in D and IMO they are even worse that the unsafe C counterparts. C# is a lousy example here since its design is only very slightly better than the original C semantics. I suggest looking into the Java implementation of Enum and EnumSet types which provides both type safety and convenience.
Jan 26 2012