Bitfield-style enum to strings?
Nick Sabalausky via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu May 7 13:55:42 PDT 2015
On 05/07/2015 01:41 PM, Nick Sabalausky wrote:
> Assuming a plain old bitfield-style enum like:
>
> enum Foo {
> optionA = 1<<0;
> optionB = 1<<1;
> optionC = 1<<2;
> optionD = 1<<3;
> optionE = 1<<4;
> }
>
> Does a function already exist somewhere to take an instance of Foo and
> get a list of the switch names as strings?
>
> Something kinda like:
>
> Foo fooVar = Foo.optionB | Foo.optionD;
> assert(
> DOES_THIS_FUNC_EXIST(fooVar)
> .equals(["optionB", "optionD"])
> );
>
> Seems entirely feasible, although my traits-fu is a bit rusty.
>
Wow, D's seriously awesome, that was actually way easier than I expected:
------------------------------------
import std.traits : isIntegral;
auto bitFieldValues(T)(T value) if(is(T==enum) && isIntegral!T)
{
import std.algorithm : filter, map;
import std.conv : to;
import std.traits : EnumMembers;
// There's gotta be a better way to convert EnumMembers!T
// to a range, right? But std.range.only() didn't work,
// due to a template instantiation error.
T[] members;
foreach(m; EnumMembers!(T))
members ~= m;
return members
.filter!(member => (value & member) == member)
.map!(member => to!string(member));
}
------------------------------------
Sample code to use it:
------------------------------------
enum Foo
{
optionA = 1<<0,
optionB = 1<<1,
optionC = 1<<2,
optionD = 1<<3,
optionE = 1<<4,
}
void main()
{
import std.range : join;
import std.stdio : writeln;
Foo fooVar = Foo.optionB | Foo.optionD;
// Output: optionB | optionD
writeln(bitFieldValues(fooVar).join(" | "));
}
------------------------------------
More information about the Digitalmars-d-learn
mailing list