Thread overview | ||||||
---|---|---|---|---|---|---|
|
June 24, 2015 Casting from an enum type to another enum type | ||||
---|---|---|---|---|
| ||||
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); } |
June 24, 2015 Re: Casting from an enum type to another enum type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland Hadinger | 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;
}
|
June 24, 2015 Re: Casting from an enum type to another enum type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | Note that this is a very simple example. You need to check in the function that a valid StyleColor will actually be produced. Otherwise, it'll happily produce a StyleColor that's invalid. |
June 24, 2015 Re: Casting from an enum type to another enum type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On Wednesday, 24 June 2015 at 18:16:42 UTC, Meta wrote:
> 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;
> }
Thanks, that works!
I'll add this to my project's 'helpers' module, with the "return" line replaced by:
foreach (m; EnumMembers!To) {
if (m == f)
return m;
}
throw new ConvException("Value not in enum");
|
Copyright © 1999-2021 by the D Language Foundation