On 6/24/18 7:13 PM, Per Nordlöw wrote:
On Sunday, 24 June 2018 at 21:47:14 UTC, Per Nordlöw wrote:
Further, it just struck me that we can generalize my fast solution to
include enumerations with enumerator aliases that are defined directly
after its original enumerator by checking with a `static if` if the
current enumerator value equals the previous then we skip it. I'm
gonna post the solution here after some hacking.
Solution:
@safe:
/** Enumeration wrapper that uses optimized conversion to string (via
`toString`
* member).
*/
struct Enum(E)
if (is(E == enum))
{
@property string toString() @safe pure nothrow @nogc
{
final switch (_enum)
{
static foreach (index, member; __traits(allMembers, E))
{
static if (index == 0 ||
(__traits(getMember, E, __traits(allMembers,
E)[index - 1]) !=
__traits(getMember, E, member)))
{
case __traits(getMember, E, member):
return member;
}
}
}
}
E _enum; // the wrapped enum
alias _enum this;
}
@safe pure unittest
{
import std.conv : to;
enum X { a,
b,
_b = b // enumerator alias
}
alias EnumX = Enum!X;
assert(EnumX(X.a).to!string == "a");
assert(EnumX(X.b).to!string == "b");
assert(EnumX(X._b).to!string == "b");
}
Great! That should cover quite a few cases.
Now, about this:
Yes, I thought about that too, but the problem is that std.conv.to is
used in std.stdio and I don't want to remember to always to do
writeln("Some text:", x.toString);
instead of
writeln("Some text:", x);
You misunderstand -- I mean fix std.conv.to so it does what you want. I
don't want your code to be the only one that benefits, I want all code
to benefit ;)
It's shouldn't be that difficult of a PR. Just separate out the part
that takes an AliasSeq and makes the switch, and try without and with
NoDuplicates (whichever works first wins).
-Steve