On Sunday, 24 June 2018 at 21:47:14 UTC, Per Nordlöw wrote:
Further, it just struck me that we can generalize my fast solution to include enumerations with enumerator aliases that are defined directly after its original enumerator by checking with a `static if` if the current enumerator value equals the previous then we skip it. I'm gonna post the solution here after some hacking.

Solution:

@safe:

/** Enumeration wrapper that uses optimized conversion to string (via `toString`
 * member).
 */
struct Enum(E)
if (is(E == enum))
{
    @property string toString() @safe pure nothrow @nogc
    {
        final switch (_enum)
        {
static foreach (index, member; __traits(allMembers, E))
            {
                static if (index == 0 ||
(__traits(getMember, E, __traits(allMembers, E)[index - 1]) !=
                            __traits(getMember, E, member)))
                {
                case __traits(getMember, E, member):
                    return member;
                }
            }
        }
    }
    E _enum;                    // the wrapped enum
    alias _enum this;
}

@safe pure unittest
{
    import std.conv : to;
    enum X { a,
             b,
             _b = b             // enumerator alias
    }
    alias EnumX = Enum!X;
    assert(EnumX(X.a).to!string == "a");
    assert(EnumX(X.b).to!string == "b");
    assert(EnumX(X._b).to!string == "b");
}

Reply via email to