Am 27.01.2012, 20:01 Uhr, schrieb Era Scarecrow <rtcv...@yahoo.com>:
>> El 26/01/2012 14:59, Trass3r escribi?:
>>> I thought it'd be good to outsource this
question from the other thread
>>> about enums as flags.
>>>
>>> Is there any merit in having implicit
conversion to the basetype?
>>> Imo it only introduces a severe bug source and
brings no advantages.
>>
> Sometimes, bitwise operations make sense, other times
not. Enums play two
> roles in D - that of an enumeration and that of a set
of flags. Only for
> 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 returning
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" in
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 IMO.
This means that enum values cannot be larger than 63 of course (so they
fit inside a ulong).
What else… hmm… I'm wondering if the documentation for flipFlag 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 <=> +=,
clearFlag <=> -=, flipFlag <=> ^=, check <=> in. (setFlag could be |= as
well, but += is more consistent with clearFlag as -=)