digitalmars.D.learn - Nothrow std.conv.to with explicit default value
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (19/19) Jun 18 2018 I have a nothrow variant of std.conv.to defined as follows:
- Adam D. Ruppe (9/15) Jun 18 2018 why not just make it
- Steven Schveighoffer (7/9) Jun 18 2018 Yes, have an internal implementation which doesn't throw, but rather
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (4/6) Jun 20 2018 Ok. Where in std.conv do the string-to-enum conversions take
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (3/9) Jun 20 2018 AFAICT, string-to-enum-conversion must include a switch
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (24/26) Jun 20 2018 My suggestion for nothrow @nogc string-to-enum conversion with
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (3/16) Jun 20 2018 Oops, this doesn't work for enums with "holes". How do I most
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (19/32) Jun 20 2018 This is my solution:
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (20/22) Jun 21 2018 Using __traits(getMember, ...) should compile faster, right?
- Jonathan M Davis (5/16) Jun 20 2018 If you want to know where std.conv deals with converting enums, look for
I have a nothrow variant of std.conv.to defined as follows: T toDefaulted(T, S, U)(S value, /*lazy*/ U defaultValue) if (is(typeof(() { T r = defaultValue; }))) // TODO use std.traits.isAssignable!(T, U) ? { try { import std.conv : to; return value.to!T; } catch (Exception e) // assume `ConvException`. TODO can we capture `ConvException` instead make it inferred `nothrow` { return defaultValue; } } The problem with this code is that throwing exceptions for the default case is costly at least with dmd. Is there another way to do this?
Jun 18 2018
On Monday, 18 June 2018 at 20:48:55 UTC, Per Nordlöw wrote:T toDefaulted(T, S, U)(S value, /*lazy*/ U defaultValue) if (is(typeof(() { T r = defaultValue; }))) // TODO use std.traits.isAssignable!(T, U) ?why not just make it T toDefaulted(T, S)(S value, T defaultValue) and forget U entirely?The problem with this code is that throwing exceptions for the default case is costly at least with dmd. Is there another way to do this?It depends on what the types are. If it is like string to int, you can simply scan the string for the appropriate format. For other conversions though, I don't think you can tell in general. User-defined types might not even tell you except by exception.
Jun 18 2018
On 6/18/18 4:48 PM, Per Nordlöw wrote:The problem with this code is that throwing exceptions for the default case is costly at least with dmd. Is there another way to do this?Yes, have an internal implementation which doesn't throw, but rather returns an error code. Then you can call that and throw or use default value based on the return value. It just means re-doing std.conv.to, which is pretty hairy, but also pretty well-organized. -Steve
Jun 18 2018
On Monday, 18 June 2018 at 21:10:03 UTC, Steven Schveighoffer wrote:It just means re-doing std.conv.to, which is pretty hairy, but also pretty well-organized.Ok. Where in std.conv do the string-to-enum conversions take place?
Jun 20 2018
On Wednesday, 20 June 2018 at 09:27:14 UTC, Per Nordlöw wrote:On Monday, 18 June 2018 at 21:10:03 UTC, Steven Schveighoffer wrote:AFAICT, string-to-enum-conversion must include a switch containing a static foreach over all the enumerators, right?It just means re-doing std.conv.to, which is pretty hairy, but also pretty well-organized.Ok. Where in std.conv do the string-to-enum conversions take place?
Jun 20 2018
On Wednesday, 20 June 2018 at 09:37:00 UTC, Per Nordlöw wrote:AFAICT, string-to-enum-conversion must include a switch containing a static foreach over all the enumerators, right?My suggestion for nothrow nogc string-to-enum conversion with default value T toDefaulted(T)(scope const(char)[] value, T defaultValue) safe pure nothrow nogc if (is(T == enum)) { switch (value) { static foreach (index, member; __traits(allMembers, T)) { case member: return cast(T)(index); } default: return defaultValue; } } safe pure nothrow /*TODO nogc*/ unittest { enum E { unknown, x, y, z } assert("x".toDefaulted!(E)(E.init) == E.x); assert("_".toDefaulted!(E)(E.init) == E.unknown); }
Jun 20 2018
On Wednesday, 20 June 2018 at 09:52:04 UTC, Per Nordlöw wrote:My suggestion for nothrow nogc string-to-enum conversion with default value T toDefaulted(T)(scope const(char)[] value, T defaultValue) safe pure nothrow nogc if (is(T == enum)) { switch (value) { static foreach (index, member; __traits(allMembers, T)) { case member: return cast(T)(index); }Oops, this doesn't work for enums with "holes". How do I most easily fix that?
Jun 20 2018
On Wednesday, 20 June 2018 at 09:54:29 UTC, Per Nordlöw wrote:This is my solution: T toDefaulted(T)(scope const(char)[] value, T defaultValue) safe pure nothrow nogc if (is(T == enum)) { switch (value) { static foreach (member; __traits(allMembers, T)) { case member: mixin(`return T.` ~ member ~ `;`); } default: return defaultValue; } } Is there a way to avoid compile-time-string-concat plus mixin here?T toDefaulted(T)(scope const(char)[] value, T defaultValue) safe pure nothrow nogc if (is(T == enum)) { switch (value) { static foreach (index, member; __traits(allMembers, T)) { case member: return cast(T)(index); }Oops, this doesn't work for enums with "holes". How do I most easily fix that?
Jun 20 2018
On Wednesday, 20 June 2018 at 14:39:48 UTC, Per Nordlöw wrote:Is there a way to avoid compile-time-string-concat plus mixin here?Using __traits(getMember, ...) should compile faster, right? T toDefaulted(T)(scope const(char)[] value, T defaultValue) safe pure nothrow nogc if (is(T == enum)) { // doesn't need `std.conv.to` switch (value) { static foreach (member; __traits(allMembers, T)) // prevents call to slower `EnumMembers` { case member: return __traits(getMember, T, member); // NOTE this is slower: mixin(`return T.` ~ member ~ `;`); } default: return defaultValue; } }
Jun 21 2018
On Wednesday, June 20, 2018 09:37:00 Per Nordlöw via Digitalmars-d-learn wrote:On Wednesday, 20 June 2018 at 09:27:14 UTC, Per Nordlöw wrote:If you want to know where std.conv deals with converting enums, look for EnumMembers, since that's the trait to get all of the members of an enum. - Jonathan M DavisOn Monday, 18 June 2018 at 21:10:03 UTC, Steven Schveighoffer wrote:AFAICT, string-to-enum-conversion must include a switch containing a static foreach over all the enumerators, right?It just means re-doing std.conv.to, which is pretty hairy, but also pretty well-organized.Ok. Where in std.conv do the string-to-enum conversions take place?
Jun 20 2018