Thread overview
Constructing an enum using the members of an AliasSeq as enumerator names
Apr 27, 2016
Nordlöw
Apr 27, 2016
Nordlöw
Apr 27, 2016
ag0aep6g
Apr 28, 2016
Nordlöw
April 27, 2016
What's the easiest way to create an `enum` using the symbol names of an `AliasSeq` as enumerator names?

That is, given

    alias Types = AliasSeq!(byte, short, int);

we need some compile-time type-constructor `makeEnum` called as

    alias E = makeEnum!Types;

that should be equivalent to

    enum E { _byte, _short, _int }

I guess a `mixin` is the way to go here, right?
April 27, 2016
On Wednesday, 27 April 2016 at 10:49:54 UTC, Nordlöw wrote:
> What's the easiest way to create an `enum` using the symbol names of an `AliasSeq` as enumerator names?

/** 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?

Destroy!
April 27, 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.
April 28, 2016
On Wednesday, 27 April 2016 at 15:30:55 UTC, ag0aep6g wrote:
> That takes longer to compile, though. Probably needs more memory as well.

Thanks!

Added here

https://github.com/nordlow/phobos-next/blob/master/src/typecons_ex.d#L425