digitalmars.D.learn - Make enum auto castable
- Mike B Johnson (9/9) Jun 04 2017 I am dealing with some COM stuff and some functions use VARIANT,
- Laeeth Isharc (5/14) Jun 04 2017 Not sure if this breaks your requirement but you could generate
- Jonathan M Davis via Digitalmars-d-learn (46/55) Jun 04 2017 Aside from whatever implicit conversions are built into the language, th...
- Mike B Johnson (5/14) Jun 04 2017 I might be able to change the enum, I assume you mean something
- Jonathan M Davis via Digitalmars-d-learn (17/34) Jun 04 2017 Yes.
- Mike B Johnson (8/46) Jun 04 2017 Well, I do need to to treat it as an int at times and opCast only
- Jonathan M Davis via Digitalmars-d-learn (11/18) Jun 04 2017 I don't know when we're getting multiple alias thises. TDPL talks about ...
- Mike B Johnson (21/48) Jun 04 2017 enum X : EnumX
- Jonathan M Davis via Digitalmars-d-learn (9/29) Jun 04 2017 It's not a bug. The alias this conversion only goes one way. It provides...
- Mike B Johnson (2/14) Jun 04 2017 That's pretty crappy! Defeats the whole point!
- Jonathan M Davis via Digitalmars-d-learn (21/38) Jun 04 2017 Well, implicit conversions tend to cause a lot of bugs in C++ code, so
- Mike B Johnson (12/55) Jun 04 2017 The problem is bugs are only a possibility. If you remove a
- via Digitalmars-d-learn (3/5) Jun 04 2017 So D has plenty of implicit conversion. It is implicit *construction* th...
I am dealing with some COM stuff and some functions use VARIANT, which can hold an enum. Instead of having to manually convert the enum(and for that matter, other things) to VARIANT, is it possible to have them automatically converted? This is because an enum is always convertible to a VARIANT but not the other way around. So, when a enum is passed to a function accepting a VARIANT, it should just work. Overloading is not an option.
Jun 04 2017
On Sunday, 4 June 2017 at 22:52:55 UTC, Mike B Johnson wrote:I am dealing with some COM stuff and some functions use VARIANT, which can hold an enum. Instead of having to manually convert the enum(and for that matter, other things) to VARIANT, is it possible to have them automatically converted? This is because an enum is always convertible to a VARIANT but not the other way around. So, when a enum is passed to a function accepting a VARIANT, it should just work. Overloading is not an option.Not sure if this breaks your requirement but you could generate overloads or rather templated version of your variant accepting function with a mixin that introspects on functions with a certain uda in the module. See excel-d for an example.
Jun 04 2017
On Sunday, June 04, 2017 22:52:55 Mike B Johnson via Digitalmars-d-learn wrote:I am dealing with some COM stuff and some functions use VARIANT, which can hold an enum. Instead of having to manually convert the enum(and for that matter, other things) to VARIANT, is it possible to have them automatically converted? This is because an enum is always convertible to a VARIANT but not the other way around. So, when a enum is passed to a function accepting a VARIANT, it should just work. Overloading is not an option.Aside from whatever implicit conversions are built into the language, the only way to define an implicit conversion in D is via alias this on a user-defined type, which then tells that type that it can convert to whatever type the result of the alias this is. e.g. if you have struct S { int x; alias x this; } then S can implicitly convert to int, and when it does, the value of x is used (alternatively, a member function could be used, in which case, the result of the member function would be used as the result of the conversion). So, that allows you to tell how to convert a type _to_ another type, but it does not allow you to convert _from_ another type. So, if you're implicitly converting from type A to type B, it will work if type A has been told how to convert to B, but there is no way for B to say that an A can be converted to a B. Only A can define the conversion. So, if you have control of the definition of the base type of the enum, then you can define an alias this on it to convert to a VARIANT, but if you don't have control over the definition of the base type of the enum (e.g. if it's int, as is the default), then you're out of luck. And if you're dealing with COM, then I'm guessing that your enum has a base type of int, and you obviously don't control the definition of int, so you can't add an alias this to it. So, if you can't change the enum, and you can't change the function that you're calling, then you'll have to insert something in between - be it a conversion function, an explicit construction of VARIANT with the enum, or some kind of wrapper function around the one that you're calling. But unless the enum itself knows how to implicitly convert to a VARIANT thanks to alias this, there is no implicit conversion. std.typecons.Nullable has this sort of problem, which has historically forced folks to do stuff like Nullable!int(42) when passing the actual type to a function that accepts a Nullable wrapper around the type, which is pretty annoying. Recently, a nullable function was added to std.typecons which uses IFTI to infer the type of the Nullable auto nullable(T)(T t) { return Nullable!T(t); } and then you could pass nullable(42) instead of Nullable!int(42), so it's more user-friendly, but it still requires an explicit conversion unless you overload the function. It's a downside to D's stricter approach to implicit conversions. - Jonathan M Davis
Jun 04 2017
On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote:On Sunday, June 04, 2017 22:52:55 Mike B Johnson via Digitalmars-d-learn wrote:I might be able to change the enum, I assume you mean something like enum myenum : S { } where S is the struct that implicitly converts?[...]Aside from whatever implicit conversions are built into the language, the only way to define an implicit conversion in D is via alias this on a user-defined type, which then tells that type that it can convert to whatever type the result of the alias this is. e.g. if you have [...]
Jun 04 2017
On Monday, June 05, 2017 00:16:15 Mike B Johnson via Digitalmars-d-learn wrote:On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote:Yes. However, be aware that you can currently only define one alias this per type. So, the rest of the code will then need to be able to deal with the fact that the enum is a struct that implicitly converts to VARIANT and does not implicitly convert to int. So, if you're just passing the enums around and comparing them, you're fine, but if you need to treat them as ints somewhere, then you'll need to provide an explicit conversion (via overloading opCast or by creating a specific function for it or just exposing a member with the int value or whatever), and that could get annoying in the same way that you're annoyed about the VARIANT issue right now. But if you don't actually need to treat the enum as an int, and you can make it a struct that implicitly converts to VARIANT instead, then that will fix your VARIANT conversion problem. - Jonathan M DavisOn Sunday, June 04, 2017 22:52:55 Mike B Johnson via Digitalmars-d-learn wrote:I might be able to change the enum, I assume you mean something like enum myenum : S { } where S is the struct that implicitly converts?[...]Aside from whatever implicit conversions are built into the language, the only way to define an implicit conversion in D is via alias this on a user-defined type, which then tells that type that it can convert to whatever type the result of the alias this is. e.g. if you have [...]
Jun 04 2017
On Monday, 5 June 2017 at 00:51:15 UTC, Jonathan M Davis wrote:On Monday, June 05, 2017 00:16:15 Mike B Johnson via Digitalmars-d-learn wrote:Well, I do need to to treat it as an int at times and opCast only works with cast. While I could set it up to do a cast(VARIANT), which is better than nothing, I'd get same result as to!VARIANT, which is shorter and effectively the same. When will we get multiple alias this? all I need is two? Hell, why not make alias this an "overloadable" function similar to opCast and such?On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote:Yes. However, be aware that you can currently only define one alias this per type. So, the rest of the code will then need to be able to deal with the fact that the enum is a struct that implicitly converts to VARIANT and does not implicitly convert to int. So, if you're just passing the enums around and comparing them, you're fine, but if you need to treat them as ints somewhere, then you'll need to provide an explicit conversion (via overloading opCast or by creating a specific function for it or just exposing a member with the int value or whatever), and that could get annoying in the same way that you're annoyed about the VARIANT issue right now. But if you don't actually need to treat the enum as an int, and you can make it a struct that implicitly converts to VARIANT instead, then that will fix your VARIANT conversion problem. - Jonathan M DavisOn Sunday, June 04, 2017 22:52:55 Mike B Johnson via Digitalmars-d-learn wrote:I might be able to change the enum, I assume you mean something like enum myenum : S { } where S is the struct that implicitly converts?[...]Aside from whatever implicit conversions are built into the language, the only way to define an implicit conversion in D is via alias this on a user-defined type, which then tells that type that it can convert to whatever type the result of the alias this is. e.g. if you have [...]
Jun 04 2017
On Monday, June 05, 2017 01:12:20 Mike B Johnson via Digitalmars-d-learn wrote:Well, I do need to to treat it as an int at times and opCast only works with cast. While I could set it up to do a cast(VARIANT), which is better than nothing, I'd get same result as to!VARIANT, which is shorter and effectively the same. When will we get multiple alias this? all I need is two? Hell, why not make alias this an "overloadable" function similar to opCast and such?I don't know when we're getting multiple alias thises. TDPL talks about it being a thing, and the spec claims that it's a thing, but until someone implements it, we won't have it, and it hasn't been a priority for Walter. IIRC, someone tried to implement it at one point, but I don't know where that went. There was a thread in the main newsgroup a couple of months ago about how to simulate multiple alias thises, so you might want to check that out: https://forum.dlang.org/post/uniyvmvjopeyyxmphfso forum.dlang.org - Jonathan M Davis
Jun 04 2017
On Monday, 5 June 2017 at 00:51:15 UTC, Jonathan M Davis wrote:On Monday, June 05, 2017 00:16:15 Mike B Johnson via Digitalmars-d-learn wrote:enum X : EnumX { a = 1, } struct EnumX { int x; alias x this; void opAssign(int y) { x = y; } double opCall() { return x; } } doesn't work because "1" is not castable to EnumX, even though EnumX is aliased to an int, and hence it should work fine. Seems like a bug to me.On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote:Yes. However, be aware that you can currently only define one alias this per type. So, the rest of the code will then need to be able to deal with the fact that the enum is a struct that implicitly converts to VARIANT and does not implicitly convert to int. So, if you're just passing the enums around and comparing them, you're fine, but if you need to treat them as ints somewhere, then you'll need to provide an explicit conversion (via overloading opCast or by creating a specific function for it or just exposing a member with the int value or whatever), and that could get annoying in the same way that you're annoyed about the VARIANT issue right now. But if you don't actually need to treat the enum as an int, and you can make it a struct that implicitly converts to VARIANT instead, then that will fix your VARIANT conversion problem. - Jonathan M Davis[...]I might be able to change the enum, I assume you mean something like enum myenum : S { } where S is the struct that implicitly converts?
Jun 04 2017
On Monday, June 05, 2017 01:30:47 Mike B Johnson via Digitalmars-d-learn wrote:enum X : EnumX { a = 1, } struct EnumX { int x; alias x this; void opAssign(int y) { x = y; } double opCall() { return x; } } doesn't work because "1" is not castable to EnumX, even though EnumX is aliased to an int, and hence it should work fine. Seems like a bug to me.It's not a bug. The alias this conversion only goes one way. It provides a way to convert _from_ the type that it's declared on to another type, not from the other type to the type that it's declared on. There is no way in D to declare an implicit conversion in the direction you're trying. So, if you have a struct that wraps an int like this, and you want to assign it an int, you're going to need to explicitly construct the struct - e.g. EnumX(1). - Jonathan M Davis
Jun 04 2017
On Monday, 5 June 2017 at 01:42:55 UTC, Jonathan M Davis wrote:On Monday, June 05, 2017 01:30:47 Mike B Johnson via Digitalmars-d-learn wrote:That's pretty crappy! Defeats the whole point![...]It's not a bug. The alias this conversion only goes one way. It provides a way to convert _from_ the type that it's declared on to another type, not from the other type to the type that it's declared on. There is no way in D to declare an implicit conversion in the direction you're trying. So, if you have a struct that wraps an int like this, and you want to assign it an int, you're going to need to explicitly construct the struct - e.g. EnumX(1). - Jonathan M Davis
Jun 04 2017
On Monday, June 05, 2017 02:14:14 Mike B Johnson via Digitalmars-d-learn wrote:On Monday, 5 June 2017 at 01:42:55 UTC, Jonathan M Davis wrote:Well, implicit conversions tend to cause a lot of bugs in C++ code, so Walter decided to restrict them quite a bit more in D than they are in C++. This therefore prevents a number of bugs in D, but it also prevents implicit conversions from being used in a number of situations where they're useful. Whether the end result is better or worse, I don't know and certainly YMMV. As it is, some of the implicit conversions that we still allow have a tendency to cause bugs (e.g. conversions between integral values and character types tend to be error-prone - especially when arrays are involved - and using implicit conversions with templated code is almost always a bad idea). So, at times, I tend to think that all implicit conversions should be banned. But at other times, it would be really nice to be able to have more than we do (e.g. it would be a lot more user-friendly if you could pass a T to a function that takes a Nullable!T). In any case, I think that the reality of the matter with D is that you tend to have to use explicit conversions rather than implicit ones, and if you're looking to do much with implicit conversions, you're usually going to be frustrated, and obviously, that sucks, but at least you're less likely to have bugs related to implicit conversions. - Jonathan M DavisOn Monday, June 05, 2017 01:30:47 Mike B Johnson via Digitalmars-d-learn wrote:That's pretty crappy! Defeats the whole point![...]It's not a bug. The alias this conversion only goes one way. It provides a way to convert _from_ the type that it's declared on to another type, not from the other type to the type that it's declared on. There is no way in D to declare an implicit conversion in the direction you're trying. So, if you have a struct that wraps an int like this, and you want to assign it an int, you're going to need to explicitly construct the struct - e.g. EnumX(1). - Jonathan M Davis
Jun 04 2017
On Monday, 5 June 2017 at 03:15:46 UTC, Jonathan M Davis wrote:On Monday, June 05, 2017 02:14:14 Mike B Johnson via Digitalmars-d-learn wrote:The problem is bugs are only a possibility. If you remove a feature from a language the feature does not exist, period. So, throwing the baby out with the bath water because he pooped in it is not a solution. Instead, if there is a problem with implicit autonomous conversion or construction, then the solution is not to remove all implicit conversions or constructions but to remove the autonomous part. e.g., make the user specify the implicit conversion explicitly. This way, if bugs do creep in, it is due to the user. It is much easier to diagnose and fix then.On Monday, 5 June 2017 at 01:42:55 UTC, Jonathan M Davis wrote:Well, implicit conversions tend to cause a lot of bugs in C++ code, so Walter decided to restrict them quite a bit more in D than they are in C++. This therefore prevents a number of bugs in D, but it also prevents implicit conversions from being used in a number of situations where they're useful. Whether the end result is better or worse, I don't know and certainly YMMV. As it is, some of the implicit conversions that we still allow have a tendency to cause bugs (e.g. conversions between integral values and character types tend to be error-prone - especially when arrays are involved - and using implicit conversions with templated code is almost always a bad idea). So, at times, I tend to think that all implicit conversions should be banned. But at other times, it would be really nice to be able to have more than we do (e.g. it would be a lot more user-friendly if you could pass a T to a function that takes a Nullable!T). In any case, I think that the reality of the matter with D is that you tend to have to use explicit conversions rather than implicit ones, and if you're looking to do much with implicit conversions, you're usually going to be frustrated, and obviously, that sucks, but at least you're less likely to have bugs related to implicit conversions. - Jonathan M DavisOn Monday, June 05, 2017 01:30:47 Mike B Johnson via Digitalmars-d-learn wrote:That's pretty crappy! Defeats the whole point![...]It's not a bug. The alias this conversion only goes one way. It provides a way to convert _from_ the type that it's declared on to another type, not from the other type to the type that it's declared on. There is no way in D to declare an implicit conversion in the direction you're trying. So, if you have a struct that wraps an int like this, and you want to assign it an int, you're going to need to explicitly construct the struct - e.g. EnumX(1). - Jonathan M Davis
Jun 04 2017
On Sun, Jun 04, 2017 at 08:15:46PM -0700, Jonathan M Davis via Digitalmars-d-learn wrote:Well, implicit conversions tend to cause a lot of bugs in C++ code, so Walter decided to restrict them quite a bit more in D than they are in C++.So D has plenty of implicit conversion. It is implicit *construction* that it lacks. And alas, C++'s mistake is implicit is default, so it gets used in places it wasn't intended. We should have just had explicit default with implicit as an option.
Jun 04 2017