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.