On Wednesday, 24 June 2015 at 15:29:03 UTC, Roland Hadinger wrote:
Hi!
What is the straightest way to safely cast from one enum type A
to another enum type B, when B, in terms of values as well as
identifiers, is a strict subset of A?
Ideally, that should be as simple as "to!B(a)". So far I've
tried a couple of things, and one way I found was to first cast
A to int, then cast that to B, but that is not really
straightforward.
Example:
import std.stdio;
import std.conv;
enum Color { r, o, y, g, b, i, v }
enum StyleColor : int { o = Color.o, b = Color.b }
void main()
{
auto c = Color.g;
// Problem: the result is not guaranteed to be a StyleColor.
// Does not throw, needs extra checks.
auto d1 = cast(StyleColor) c;
// Typesafe, but is not exactly straightforward.
auto d2 = to!StyleColor(cast(int) c);
// Error: template std.conv.toImpl cannot deduce
// function from argument types !(StyleColor)(Color)
//
// Changing "enum StyleColor : Color" to "enum StyleColor :
int"
// in the definition above does not help either.
auto d3 = to!StyleColor(c);
}
std.conv.to really should be able to do this, but I guess not
many people have needed to do this. You can write an "extension"
to `to` which does it for you:
import std.traits;
auto to(To, From)(From f)
if (is(From == enum) && is(To == enum) && is(OriginalType!From :
OriginalType!To))
{
return cast(To)f;
}
enum Color { r, o, y, g, b, i, v }
enum StyleColor : int { o = Color.o, b = Color.b }
void main()
{
auto c = Color.g;
auto s = c.to!StyleColor;
}