Phobos' std.conv.to-conversion from enum to string doesn't scale beyond hundreds of enumerators

Steven Schveighoffer schveiguy at yahoo.com
Sun Jun 24 23:21:44 UTC 2018


On 6/24/18 7:13 PM, Per Nordlöw wrote:
> 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");
> }
> 
Great! That should cover quite a few cases.

Now, about this:

> Yes, I thought about that too, but the problem is that std.conv.to is 
> used in std.stdio and I don't want to remember to always to do
> 
>      writeln("Some text:", x.toString);
> 
> instead of
> 
>      writeln("Some text:", x);

You misunderstand -- I mean fix std.conv.to so it does what you want. I 
don't want your code to be the only one that benefits, I want all code 
to benefit ;)

It's shouldn't be that difficult of a PR. Just separate out the part 
that takes an AliasSeq and makes the switch, and try without and with 
NoDuplicates (whichever works first wins).

-Steve


More information about the Digitalmars-d mailing list