Jump to page: 1 2
Thread overview
Make enum auto castable
Jun 04, 2017
Mike B Johnson
Jun 04, 2017
Laeeth Isharc
Jun 04, 2017
Jonathan M Davis
Jun 05, 2017
Mike B Johnson
Jun 05, 2017
Jonathan M Davis
Jun 05, 2017
Mike B Johnson
Jun 05, 2017
Jonathan M Davis
Jun 05, 2017
Mike B Johnson
Jun 05, 2017
Jonathan M Davis
Jun 05, 2017
Mike B Johnson
Jun 05, 2017
Jonathan M Davis
Jun 05, 2017
Mike B Johnson
June 04, 2017
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.
June 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.

June 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

June 05, 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:
>> [...]
>
> 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
>
> [...]

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?
June 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:
> > On Sunday, June 04, 2017 22:52:55 Mike B Johnson via
> >
> > Digitalmars-d-learn wrote:
> >> [...]
> >
> > 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
> >
> > [...]
>
> 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?

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

June 05, 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:
>> 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:
>> >> [...]
>> >
>> > 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
>> >
>> > [...]
>>
>> 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?
>
> 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

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?

June 05, 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:
>> On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis 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?
>
> 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



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.

June 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

June 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

June 05, 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:
>> [...]
>
> 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

That's pretty crappy! Defeats the whole point!
« First   ‹ Prev
1 2