www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Char enum conversion

reply Rekel <paultjeadriaanse gmail.com> writes:
I'm surprised char to enum conversion is currently not possible.
This, as char[] & string conversion to enum is supported.

 enum E{A, B}
 void main()
 char[] a = ['A'];
 a.to!E.writeln;
 "A".to!E.writeln;
 'A'.to!E.writeln; // Crash
 }
The last line crashes with:
 std.conv.ConvException C:\D\dmd2\windows\bin\..\..\src\phob
s\std\conv.d(2058): Value (A) does not match any member value of enum 'Enum'
Jan 01 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/1/21 12:17 PM, Rekel wrote:
 I'm surprised char to enum conversion is currently not possible.
 This, as char[] & string conversion to enum is supported.
 
 enum E{A, B}
 void main()
 char[] a = ['A'];
 a.to!E.writeln;
 "A".to!E.writeln;
 'A'.to!E.writeln; // Crash
 }
The last line crashes with:
 std.conv.ConvException C:\D\dmd2\windows\bin\..\..\src\phob
s\std\conv.d(2058): 
 Value (A) does not match any member value of enum 'Enum'
So what's happening here is that std.conv.to is treating your 'A' as an integer. What you are doing is really: 65.to!E.writeln; // 'A' is really a octet of 65 That char/wchar/dchar are treated as a standard implicit-convertible integer type is one of the failings of D I think. Another gotcha to watch out for, if your enum is string-based, there is NO WAY to use std.conv to convert from the base string to the enum type, it only goes by enum names. -Steve
Jan 01 2021
parent reply Rekel <paultjeadriaanse gmail.com> writes:
On Friday, 1 January 2021 at 17:59:30 UTC, Steven Schveighoffer 
wrote:
 So what's happening here is that std.conv.to is treating your 
 'A' as an integer. What you are doing is really:

 65.to!E.writeln; // 'A' is really a octet of 65

 That char/wchar/dchar are treated as a standard 
 implicit-convertible integer type is one of the failings of D I 
 think.
I see why that makes sense ascii wise, however, does that ruin templating for chars? That would seem very problematic.
 Another gotcha to watch out for, if your enum is string-based, 
 there is NO WAY to use std.conv to convert from the base string 
 to the enum type, it only goes by enum names.
Im unsure about what you mean here. Do you mean that an enum with strings as assigned values cannot be converted to using any of the assigned strings? If so, how come it does work using integers?
Jan 01 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/1/21 1:11 PM, Rekel wrote:
 On Friday, 1 January 2021 at 17:59:30 UTC, Steven Schveighoffer wrote:
 So what's happening here is that std.conv.to is treating your 'A' as 
 an integer. What you are doing is really:

 65.to!E.writeln; // 'A' is really a octet of 65

 That char/wchar/dchar are treated as a standard implicit-convertible 
 integer type is one of the failings of D I think.
I see why that makes sense ascii wise, however, does that ruin templating for chars?
It's not. It's templating based on the base type. when passed a variable that's an enum, `to` looks at 2 possibilities: 1. The type is a string -- match against the names of the enum values 2. The type is implicitly convertible to the enum base type, look up based on the base type. Since char is not a string, but it's implicitly convertible to int (which is the default base type for enums), it uses the second overload.
 That would seem very problematic.
I'd have to see a more compelling example in order to agree. Using 'A' instead of "A" isn't that convincing. Note, that if 'A' is in a variable, you can generate a "string" based on it: auto nameToLookup = (&var)[0 .. 1]; nameToLookup.to!E.writeln;
 
 Another gotcha to watch out for, if your enum is string-based, there 
 is NO WAY to use std.conv to convert from the base string to the enum 
 type, it only goes by enum names.
Im unsure about what you mean here. Do you mean that an enum with strings as assigned values cannot be converted to using any of the assigned strings? If so, how come it does work using integers?
So for example: enum X : string { Foo = "FOO", Bar = "BAR" } // std.conv.ConvException /dlang/dmd/linux/bin64/../../src/phob s/std/conv.d(2819): X does not have a member named 'FOO' auto val = "FOO".to!X; // ok auto val2 = "Foo".to!X; How come it works for integers? Because integers are not strings, so it can distinguish what you want. When both case 1 and case 2 above are the same type, it has to pick one. -Steve
Jan 01 2021
parent reply Rekel <paultjeadriaanse gmail.com> writes:
On Friday, 1 January 2021 at 18:27:05 UTC, Steven Schveighoffer 
wrote:
 That would seem very problematic.
I'd have to see a more compelling example in order to agree. Using 'A' instead of "A" isn't that convincing.
I meant that in case this was an issue with char when templating in general, as I'm quite new to it I wasnt sure if that was what you meant. I guess making your char into a 1 long string is an ok workaround, and the scenario's in which you have a char with names 1 character long are, I guess, limited. Ended up using [0..1]. Thanks for the explanation.
Jan 01 2021
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/1/21 3:27 PM, Rekel wrote:
 On Friday, 1 January 2021 at 18:27:05 UTC, Steven Schveighoffer wrote:
 That would seem very problematic.
I'd have to see a more compelling example in order to agree. Using 'A' instead of "A" isn't that convincing.
I meant that in case this was an issue with char when templating in general, as I'm quite new to it I wasnt sure if that was what you meant.
There may be some misunderstanding here. A string is an *array* and is not implicitly convertible from values like char. However, an int is implicitly convertible from char. If you have an overload set like: void foo(string s) { writeln("string: ", s); } void foo(int i) { writeln("int: ", i); } foo("A"); // prints string: A foo('A'); // prints int: 65 This is all that is happening, the overload set for `to` is either string or the base type of the enum (in this case int). So 'A' matches the int, not the string. It's not an issue with templating at all, you can template on a char no problem. It's just the way `to` is implemented. My comment about not being convincing was basically a solicitation to see if you have a compelling case of why you would want to use a char to represent an enum name instead of a string. The small example you give is not that. -Steve
Jan 01 2021