Constructing an enum using the members of an AliasSeq as enumerator names

ag0aep6g via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Apr 27 08:30:55 PDT 2016


On 27.04.2016 13:06, Nordlöw wrote:
> /** Returns: a `string` containing the definition of an `enum` named
> `name` and
>      with enumerator names given by `Es`, optionally prepended with
> `prefix` and
>      appended with `suffix`.
>
>      TODO Move to Phobos std.typecons
> */
> string makeEnumDefinitionString(string name,
>                                  string prefix = `_`,
>                                  string suffix = ``,
>                                  Es...)()
>      if (Es.length >= 1)
> {
>      typeof(return) s = `enum ` ~ name ~ ` { `;
>      foreach (E; Es)
>      {
>          s ~= prefix ~ E.stringof ~ suffix ~ `, `;
>      }
>      s ~= `}`;
>      return s;
> }
>
> @safe pure nothrow @nogc unittest
> {
>      import std.meta : AliasSeq;
>      alias Types = AliasSeq!(byte, short);
>      mixin(makeEnumDefinitionString!("Type", `_`, `_`, Types));
>      static assert(is(Type == enum));
>      static assert(Type._byte_.stringof == "_byte_");
>      static assert(Type._short_.stringof == "_short_");
> }
>
> Can it be made more elegant?

I'd hide the string mixin in the template:

----
template makeEnumFromSymbolNames(string prefix = `_`,
                                  string suffix = ``,
                                  Es...)
     if (Es.length >= 1)
{
     enum members = {
         string s = "";
         foreach (E; Es)
         {
             s ~= prefix ~ E.stringof ~ suffix ~ `, `;
         }
         return s;
     }();
     mixin("enum makeEnumFromSymbolNames {" ~ members ~ "}");
}

@safe pure nothrow @nogc unittest
{
     import std.meta : AliasSeq;
     alias Types = AliasSeq!(byte, short);
     alias Type = makeEnumFromSymbolNames!(`_`, `_`, Types);
     static assert(is(Type == enum));
     static assert(Type._byte_.stringof == "_byte_");
     static assert(Type._short_.stringof == "_short_");
}
----

The `foreach` could be replaced with `map` and `joiner`, but I'm not 
sure if that would be an improvement.

`format` might be interesting:

----
     import std.format;
     import std.meta: staticMap;
     enum stringOf(t...) = t[0].stringof;
     mixin(format(
         "enum makeEnumFromSymbolNames {%-(" ~ prefix ~ "%s" ~ suffix 
~"%|, %)}",
         [staticMap!(stringOf, Es)]
     ));
----

That takes longer to compile, though. Probably needs more memory as well.


More information about the Digitalmars-d-learn mailing list