www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: strong enums: why implicit conversion to basetype?

reply Era Scarecrow <rtcvb32 yahoo.com> writes:
 El 26/01/2012 14:59, Trass3r escribi?:
 I thought it'd be good to outsource this



 about enums as flags.

 Is there any merit in having implicit



 Imo it only introduces a severe bug source and





 roles in D - that of an enumeration and that of a set

 the latter do bitwise operations make sense.

You'd think that with some use of a templated struct and some "alias=20 this" we'd be able to have a strongly-typed type for storing sets of=20 flags.=A0 It could even offer convenience functions like "getFlag" and=20 "setFlag" to make the code read a bit nicer.

I have a personal class i am using, may submit it later to Walter to add t= o Phobos. Comments? (I have working unittests... :) ) ///T of type ENUM, and S of an integral. struct HandleFlags(T, S) { =09S state;=09///Holds state. =09alias T T_Enum; =09 this(T[] setFlags...); =09///Returns true/false if a specific ENUM flag has been set. =09bool check(T[] flag...); =09///Returns true/false if a specific ENUM flag has been set. =09bool checkAll(T[] flag...); =09 =09/** =09Checks if a flag has been set, returning that ENUM, otherwise returning = the Else flag. =09*/ =09T checkElse(T Else, T[] flag...); =09///Sets specific flag(s) on =09void setFlag(T[] flag...); =09///turns listed flags off. =09void clearFlag(T[] flag...); =09///reverses the state of a specific flag. =09void flipFlag(T[] flag...); }
Jan 27 2012
parent reply "Marco Leise" <Marco.Leise gmx.de> writes:
Am 27.01.2012, 20:01 Uhr, schrieb Era Scarecrow <rtcvb32 yahoo.com>:

 El 26/01/2012 14:59, Trass3r escribi?:
 I thought it'd be good to outsource this



 about enums as flags.

 Is there any merit in having implicit



 Imo it only introduces a severe bug source and





 roles in D - that of an enumeration and that of a set

 the latter do bitwise operations make sense.

You'd think that with some use of a templated struct and some "alias this" we'd be able to have a strongly-typed type for storing sets of flags. It could even offer convenience functions like "getFlag" and "setFlag" to make the code read a bit nicer.

I have a personal class i am using, may submit it later to Walter to =

 add to Phobos. Comments? (I have working unittests... :) )


 ///T of type ENUM, and S of an integral.
 struct HandleFlags(T, S)
  {
 	S state;	///Holds state.
 	alias T T_Enum;

 	 this(T[] setFlags...);

 	///Returns true/false if a specific ENUM flag has been set.
 	bool check(T[] flag...);

 	///Returns true/false if a specific ENUM flag has been set.
 	bool checkAll(T[] flag...);
 	=

 	/**
 	Checks if a flag has been set, returning that ENUM, otherwise returni=

 the Else flag.
 	*/
 	T checkElse(T Else, T[] flag...);

 	///Sets specific flag(s) on
 	void setFlag(T[] flag...);

 	///turns listed flags off.
 	void clearFlag(T[] flag...);

 	///reverses the state of a specific flag.
 	void flipFlag(T[] flag...);
 }

Is it possible to 'auto-detect' the integral type? I makes little sense = to = use a signed type or a type too small for the enum for example. And in the same fashion: Do you map an enum value to "1 << enum_value" i= n = the bit field? I know that in Delphi 'sets' worked great for me and so I= = am biased for everything that works the same way. It is also the most = natural way to work with enums that can be represented as a bit field IM= O. = This means that enum values cannot be larger than 63 of course (so they = = fit inside a ulong). What else=E2=80=A6 hmm=E2=80=A6 I'm wondering if the documentation for f= lipFlag should be = "reverses the state of all given flags". How is checkElse supposed to work. I could imagine the function of a = method with the signature "T (T flag, T else)". What is the use case for= = it? Even check seems to accept multiple flags, where I would expect only= = one. We could also introduce some operator overloading: setFlag <=3D> +=3D, = clearFlag <=3D> -=3D, flipFlag <=3D> ^=3D, check <=3D> in. (setFlag coul= d be |=3D as = well, but +=3D is more consistent with clearFlag as -=3D)
Jan 29 2012
parent bearophile <bearophileHUGS lycos.com> writes:
This is an important topic.

I have an enhancement requests on enums:
http://d.puremagic.com/issues/show_bug.cgi?id=3999
As usual language design is a matter of finding the right balance between
strictness, that helps catch real bugs, and type "sloppiness" that makes code
more handy, and avoids some casts that sometimes are themselves a source of
bugs. C++11 has introduced enums with a stronger static typing compared to D
enums. But it keeps the less strongly typed enum too. This increases C++11
language complexity, but allows the programmer to choose between strictness and
flexibility at will.

Regarding flags management, I think D2 is not good enough about them. They are
a common need for a system language and I think normal enums are not good
enough for this specialized purpose. Normal enums are both not handy enough and
not safe enough for this purpose.
So an idea is to introduce something like a " flags enum". But I think a
library solution is enough here, just like bitfields. I have written this:
http://d.puremagic.com/issues/show_bug.cgi?id=6946
A problem with this implementation is that needs operator overload (with
preconditions) to catch some wrong usages. Another problem is that is doesn't
allow to add flag combinations inside the flag list itself. Maybe if you try to
solve this second problem you increase too much the complexity of this
implementation, so I have left them out.

In this thread I have seen various library solutions to implement flags. I
think Andrei will be glad to add to Phobos a flags library solution that
combines the best ideas of the various implementations.

Bye,
bearophile
Jan 29 2012