How does to!string(enum.member) works?

d, dmd

Solution

What it does is use compile time reflection on the enum type to get a list of members (the names as strings) and their values. It constructs a switch statement out of this information for a fast lookup to get the name from a value. `to!SomeEnum("a_string")` uses the same principle, just in the other direction.

The compile time reflection info is accessed with `__traits(allMembers, TheEnumType)`, which returns a list of strings that can be looped over to build the switch statement. Then `__traits(getMember, TheEnumType, memberName)` is used to fetch the body.

Traits can be seen more of here: http://dlang.org/traits.html#allMembers

That `allMembers` one works on many types, not just classes as seen in the example, but also structs, enums, and more, even modules.

The phobos source code has some examples like `EnumMembers` in `std.traits`: https://github.com/D-Programming-Language/phobos/blob/master/std/traits.d#L3360

though the phobos source is kinda hard to read, but on line 3399, at the bottom of that function, you can see it using `__traits(allMembers)` as its data source. `std.conv.to` is implemented in terms of many `std.traits` functions.

You can also check out the sample chapter tab to get the Reflection chapter out of my D cookbook which discusses this stuff too:

http://www.packtpub.com/discover-advantages-of-programming-in-d-cookbook/book

The final example in that chapter shows how to use several of the reflection capabilities to build a little function dispatcher based on strings. The following chapter (not available for free though) shows how to build a switch out of it for better efficiency too. It's actually pretty easy: just put the `case` statements inside a `foreach` over the compile time data and the D compiler will unroll then optimize the lookup table for you!

Problem

How does `std.conv.to!string(enum.member)` work? How is it possible that a function takes an enum member and returns its name? Does it use a compiler extension or something similar? It's a bit usual to me since I came from C/C++ world.

Original source