Thread overview
Why doesn't to!MyEnumType(42) work
Jul 16, 2012
Tommi
Jul 16, 2012
Era Scarecrow
Jul 16, 2012
cal
Jul 16, 2012
cal
Jul 16, 2012
Tommi
Jul 16, 2012
Era Scarecrow
Jul 17, 2012
Christophe Travert
July 16, 2012
According to the docs, std.conv.to uses cast operator under the hood, and since the following works:

enum MyEnumType {a}
auto val = cast(MyEnumType) 42;

...it seems natural that to!MyEnumType(42) should work as well. But currently it gives error:
template instance std.conv.to!(MyEnumType).to!(int) error instantiating
July 16, 2012
On Monday, 16 July 2012 at 17:35:33 UTC, Tommi wrote:
> According to the docs, std.conv.to uses cast operator under the hood, and since the following works:
>
> enum MyEnumType {a}
> auto val = cast(MyEnumType) 42;
>
> ...it seems natural that to!MyEnumType(42) should work as well. But currently it gives error:
> template instance std.conv.to!(MyEnumType).to!(int) error instantiating

 You can convert a enum to an int, but not the other way around. Enums are not a 'range', rather a bunch of const values with a tag stating it's type. Let's check against your example with a little modification.

 enum MyEnumType { none, a = 100 } //so far so good

 int i = MyEnumType.a; //success
 MyEnumType x = MyEnumType.a; //success, so far so good.
 MyEnumType y = cast(MyEnumType) 42; //Error: wtf is 42 anyways?
 MyEnumType z = cast(MyEnumType) 100; //Error: an int is not an enum! (Even if it's a valid match)

// although...
 assert(x == 100); //enum converts to int.
 assert(x == i);
 assert(x == MyenumType.a);

 These may seem like strict rules, and there may be cases where a combination of flags are valid, but setting an invalid state in a fixed range of 'const' values doesn't work. I suppose the same thing could be compared to an enum being a set of car keys, and every proper enum value is a car key, but when you give something that's not a car key (Say, a brick) then it isn't going to fit, not matter how hard you try to force it into the key hole.

 Enums with fixed values (and a number of them) are good for flags and limited ID types. It also allows you as TDPL gives an example where you can make a statement that handles ALL possible values.

with(MyEnumType) {
 final switch(x) { //of type MyEnumType. ALL possibilities MUST be present
  case none: //something
  case a: //something else
  //no possible 42 value here, no matter how hard you try;
  //and since we handle all cases, default should not be used
 }
}
July 16, 2012
On Monday, 16 July 2012 at 20:22:12 UTC, Era Scarecrow wrote:
>  You can convert a enum to an int, but not the other way around.
[...]
>  MyEnumType z = cast(MyEnumType) 100; //Error: an int is not an enum! (Even if it's a valid match)

I do this all the time....

enum E
{
 A = 100,
 B = 200
}

E e = cast(E) 100 ; // works fine...

Maybe I misunderstood?

The problem is that here int is not _implicitly_ convertible to the enum. For example, if you write your own template without any constraints:

T to(T, S)(S i)
{
    return cast(T)i;
}

then:
E e = to!E(100); // works, but is not safe


July 16, 2012
On Monday, 16 July 2012 at 21:00:00 UTC, cal wrote:
> On Monday, 16 July 2012 at 20:22:12 UTC, Era Scarecrow wrote:
>> You can convert a enum to an int, but not the other way around.
> [...]
>> MyEnumType z = cast(MyEnumType) 100; //Error: an int is not an enum! (Even if it's a valid match)
>
> I do this all the time....
>
> enum E
> {
>  A = 100,
>  B = 200
> }
>
> E e = cast(E) 100 ; // works fine...
>
> Maybe I misunderstood?
>
> The problem is that here int is not _implicitly_ convertible to the enum. For example, if you write your own template without any constraints:
>
> T to(T, S)(S i)
> {
>     return cast(T)i;
> }
>
> then:
> E e = to!E(100); // works, but is not safe

actually ignore that bit about implicit conversion, that's probably not "the problem"


July 16, 2012
On Monday, 16 July 2012 at 20:22:12 UTC, Era Scarecrow wrote:
>  MyEnumType y = cast(MyEnumType) 42; //Error: wtf is 42 anyways?

Like the previous fellow said, it's not an error.

To me that line of code says: "let's assign to MyEnumType variable y some value that's not valid (as type MyEnumType defines the word valid)". I think it's very useful to be able to assign values which are unambiguously invalid, like NaN to float, 0xFF to char or some undefined value to enum. Sadly, with integral types there's no such value that could be seen as invalid.

And to reiterate my point:
If the call:

to!MyEnum(42)

...is supposed to be (and this I gather from the docs) under the hood the same as:

cast(MyEnum) 42

...which works, then, logically, to!MyEnum(42) should also work.
July 16, 2012
On Monday, 16 July 2012 at 21:59:17 UTC, Tommi wrote:
> On Monday, 16 July 2012 at 20:22:12 UTC, Era Scarecrow wrote:
>> MyEnumType y = cast(MyEnumType) 42; //Error: wtf is 42 anyways?
>
> Like the previous fellow said, it's not an error.

 I had the impression it was illegal by the compiler; Logically forcing an enum to an invalid state is probably undefined and unstable (but casting with compile-time constant that's provably correct would be different). Also I've never tried force casting the enums, so.. Hmmm...

 I suppose 'use at your own risk' applies here.
July 17, 2012
"Era Scarecrow" , dans le message (digitalmars.D:172568), a écrit :
> On Monday, 16 July 2012 at 21:59:17 UTC, Tommi wrote:
>> On Monday, 16 July 2012 at 20:22:12 UTC, Era Scarecrow wrote:
>>> MyEnumType y = cast(MyEnumType) 42; //Error: wtf is 42 anyways?
>>
>> Like the previous fellow said, it's not an error.
> 
>   I had the impression it was illegal by the compiler; Logically
> forcing an enum to an invalid state is probably undefined and
> unstable (but casting with compile-time constant that's provably
> correct would be different). Also I've never tried force casting
> the enums, so.. Hmmm...
> 
>   I suppose 'use at your own risk' applies here.

For what it's worth, I think cast should be at your own risk, and to!MyEnumType should assert the enum is valid.