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

Stefan Koch uplink.coder at googlemail.com
Fri Jun 22 17:41:26 UTC 2018


On Friday, 22 June 2018 at 00:50:05 UTC, Steven Schveighoffer 
wrote:
> On 6/21/18 6:46 PM, Per Nordlöw wrote:
>> I've discovered the annoying fact that std.conv.to doesn't 
>> scale for enum to string conversion when the enum has hundreds 
>> of members. This because of a call to `NoDuplicates` which has 
>> (at least) O(n*log(n) time and space complexity.
>> 
>> So I've come up with
>> 
>> 
>> /** Faster implementation of `std.conv.to`.
>>   */
>> string toString(T)(T value) @safe pure nothrow @nogc
>> if (is(T == enum))
>> {
>>      final switch (value)
>>      {
>>          static foreach (member; __traits(allMembers, T))
>>          {
>>          case __traits(getMember, T, member):
>>              return member;
>>          }
>>      }
>> }
>> 
>> ///
>> @safe pure nothrow @nogc unittest
>> {
>>      enum E { unknown, x, y, z, }
>>      assert(E.x.toString == "x");
>>      assert(E.y.toString == "y");
>>      assert(E.z.toString == "z");
>> }
>> 
>> 
>> The question know is: How do I make this support enums with 
>> enumerator aliases without needing to call `NoDuplicates`?
>
> You can't. That's why it's in there. And I can't think of a 
> better algorithm than O(nlgn). That's what it would cost to 
> sort anyway.
>
> The sucky thing is, the compiler is *already* doing a sort on 
> the items in the switch, and *already* doing the duplicate 
> check. It would be cool to be able to leverage this mechanism 
> to avoid the library solution, but I don't know how we can do 
> that, as the semantics for switch are well defined, and there's 
> no other way to hook this builtin functionality.
>
> One thing that may be worthwhile is checking to see if a CTFE 
> solution is better than a template solution. In other words:
>
> string[] dedup(string[] identifiers) { ... }
>
> enum items = dedup(__traits(allMembers, T));
>
> static foreach(member; items) ...
>
> Just avoiding all the template symbol generation may make it 
> worth it, even if the dedup function is O(n^2) complexity.
>
> -Steve


I do have my own ctfe utils for this
{https://forum.dlang.org/post/bfnwstkafhfgihavtzsz@forum.dlang.org}, however without dedup (because I'd rather be alerted when it happens) what you have to do is to sort the enum values.
(I'd suggest a non-recursive mergesort.)
However if there are no duplicates there's no need to 
deduplicate, the reason it is deduplicated it because the 
switch_statement forbids duplicates.

I may add that this performs very well with newCTFE I don't know 
about the old engine, but I'd assume even there it's faster.


More information about the Digitalmars-d mailing list