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(" | "));
}
------------------------------------

Reply via email to