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