Thread overview
Get enum value name as string at compile time?
Sep 14, 2020
Simen Kjærås
September 13, 2020
Consider the enum:

enum Foo { a, b }

Foo.a.stringof => "a"
enum x = Foo.a;
x.stringof => "cast(Foo)0"

Is there another way I can take an enum value that's known at compile time (but not the actual identifier), and get the name of it? I know I can use a switch, or to!string. But I was hoping this was easy for the compiler to figure out some way without involving CTFE.

-Steve
September 14, 2020
On Monday, 14 September 2020 at 03:48:51 UTC, Steven Schveighoffer wrote:
> Consider the enum:
>
> enum Foo { a, b }
>
> Foo.a.stringof => "a"
> enum x = Foo.a;
> x.stringof => "cast(Foo)0"
>
> Is there another way I can take an enum value that's known at compile time (but not the actual identifier), and get the name of it? I know I can use a switch, or to!string. But I was hoping this was easy for the compiler to figure out some way without involving CTFE.

It is a bit weird that x.stringof doesn't simply return the name like Foo.a.stringof does. Anyways, this works:

template enumName(alias a) {
    import std.meta : staticIndexOf, staticMap;

    alias T = typeof(a);
    enum getValue(string name) = __traits(getMember, T, name);
    alias enumValues = staticMap!(getValue, __traits(allMembers, T));

    enum enumName = __traits(allMembers, T)[staticIndexOf!(a, enumValues)];
}

enum Foo { a = 2, b = 19 }

enum x = Foo.a;
pragma(msg, enumName!x); // "a"

--
  Simen
September 14, 2020
On 9/14/20 2:25 AM, Simen Kjærås wrote:
> On Monday, 14 September 2020 at 03:48:51 UTC, Steven Schveighoffer wrote:
>> Consider the enum:
>>
>> enum Foo { a, b }
>>
>> Foo.a.stringof => "a"
>> enum x = Foo.a;
>> x.stringof => "cast(Foo)0"
>>
>> Is there another way I can take an enum value that's known at compile time (but not the actual identifier), and get the name of it? I know I can use a switch, or to!string. But I was hoping this was easy for the compiler to figure out some way without involving CTFE.
> 
> It is a bit weird that x.stringof doesn't simply return the name like Foo.a.stringof does. Anyways, this works:
> 
> template enumName(alias a) {
>      import std.meta : staticIndexOf, staticMap;
> 
>      alias T = typeof(a);
>      enum getValue(string name) = __traits(getMember, T, name);
>      alias enumValues = staticMap!(getValue, __traits(allMembers, T));
> 
>      enum enumName = __traits(allMembers, T)[staticIndexOf!(a, enumValues)];
> }
> 
> enum Foo { a = 2, b = 19 }
> 
> enum x = Foo.a;
> pragma(msg, enumName!x); // "a"
> 

Thanks.

I never considered doing something like that. Not sure I like that better than the CTFE version. I just punted and used to!string in my code anyway.

A CTFE linear search in a compile-time array probably wouldn't be too bad, especially when the list of elements is not long.

Again, we could use that ... DIP to make things a lot less complex.

-Steve