On Thursday, 18 May 2017 at 23:15:46 UTC, ag0aep6g wrote:
On 05/19/2017 12:31 AM, Stefan Koch wrote:
string enumToString(E)(E v)
{
static assert(is(E == enum), "emumToString is only meant for enums");
     mixin ({
     string result = "final switch(v) {\n";
     foreach(m;[__traits(allMembers, E)])
     {
         result ~= "\tcase E." ~ m ~ " :\n"
             ~ "\t\treturn \"" ~ m ~ "\";\n"
             ~ "\tbreak;\n";
     }
     return result ~ "}";
     } ());
}

I'm sure that can be de-uglified a fair bit without hurting performance.

1) "final switch(v) {" and the closing brace can be moved out of the string. This should be completely free.

2) No need for `break` after `return`. Also free.

3) With a static foreach over `__traits(allMembers, E)` you can get rid of the function literal. Doesn't seem to affect performance much if at all.

So far:

----
string enumToString(E)(E v)
{
    static assert(is(E == enum),
        "emumToString is only meant for enums");
    final switch (v)
    {
        foreach(m; __traits(allMembers, E))
        {
            mixin("case E." ~ m ~ ": return \"" ~ m ~ "\";");
        }
    }
}
----

4) If EnumMembers is an option, you can get rid of the string mixin altogether:

----
string enumToString(E)(E v)
{
    import std.meta: AliasSeq;
    import std.traits: EnumMembers;
    static assert(is(E == enum),
        "emumToString is only meant for enums");
    alias memberNames = AliasSeq!(__traits(allMembers, E));
    final switch(v)
    {
        foreach(i, m; EnumMembers!E)
        {
            case m: return memberNames[i];
        }
    }
}
----

That takes a bit longer. May just be the time it takes to parse the std.* modules. Object size stays the same.

Nice work beatifying the implementation.

Although AliasSeq and EnumMembers are unnecessary.
I incorporated your idea into the following version:

string enumToString(E)(E v)
{
    static assert(is(E == enum),
        "emumToString is only meant for enums");
    switch(v)
    {
        foreach(m; __traits(allMembers, E))
        {
            case mixin("E." ~ m) : return m;
        }

        default :
        {
            string result = "cast(" ~ E.stringof ~ ")";
            uint val = v;
            enum headLength = E.stringof.length + "cast()".length;
uint log10Val = (val < 10) ? 0 : (val < 100) ? 1 : (val < 1000) ? 2 : (val < 10000) ? 3 : (val < 100000) ? 4 : (val < 1000000) ? 5 : (val < 10000000) ? 6 : (val < 100000000) ? 7 : (val < 1000000000) ? 8 : 9;
            result.length += log10Val + 1;
            for(uint i;i != log10Val + 1;i++)
            {
cast(char)result[headLength + log10Val - i] = cast(char) ('0' + (val % 10));
                val /= 10;
            }

            return cast(string) result;
        }
    }
}

Reply via email to