Thread overview
Converting function pointers to delegates
Apr 14, 2014
Ryan Voots
Apr 14, 2014
Adam D. Ruppe
Apr 14, 2014
Andrej Mitrovic
Apr 15, 2014
Artur Skawina
Apr 15, 2014
Andrej Mitrovic
Apr 15, 2014
Artur Skawina
Apr 15, 2014
Adam D. Ruppe
Apr 15, 2014
Andrej Mitrovic
Apr 14, 2014
Andrej Mitrovic
April 14, 2014
I'm porting some code from D1 to D2 and this is the final error i'm getting from DMD and GDC.  I have no idea what is going on with it though.

/**
 * Convert any function pointer to a delegate.
 * _ From: http://www.digitalmars.com/d/archives/digitalmars/D/easily_convert_any_method_function_to_a_delegate_55827.html */
R delegate(P) toDelegate(R, P...)(R function(P) fp)
{	struct S
	{	R Go(P p) // P is the function args.
		{	return (cast(R function(P))(cast(void*)this))(p);
		}
	}
	return &(cast(S*)(cast(void*)fp)).Go;
}

DMD tells me:
src/yage/core/misc.d(164): Error: e2ir: cannot cast this of type S to type void*


The code itself you can see at: https://bitbucket.org/simcop2387/yage/src/0542cea5eefabf4c90b822cf26ec1062ed0fcb64/src/yage/core/misc.d?at=default#cl-161

and where it gets called: https://bitbucket.org/simcop2387/yage/src/0542cea5eefabf4c90b822cf26ec1062ed0fcb64/src/yage/core/repeater.d?at=default#cl-47

To be perfectly honest I'm not sure what it's doing to figure out how to fix it.
April 14, 2014
On Monday, 14 April 2014 at 17:45:52 UTC, Ryan Voots wrote:
> src/yage/core/misc.d(164): Error: e2ir: cannot cast this of type S to type void*


Try taking the address of this before casting it. So more like

cast(void*)&this


IIRC in D1 this was a pointer, whereas in D2 this is a reference. You can't cast a reference to pointer directly (at least not without overloading the cast operator) but you can take its address to fetch a pointer out of it and then work with that.

BTW see also: http://dlang.org/phobos/std_functional.html#toDelegate
April 14, 2014
On Monday, 14 April 2014 at 17:45:52 UTC, Ryan Voots wrote:
> /**
>  * Convert any function pointer to a delegate.
>  * _ From: http://www.digitalmars.com/d/archives/digitalmars

You can replaced it with std.functional.toDelegate.

As for its use-case, if some API or function supports only delegates but you want to pass in a function, you would wrap the function with toDelegate and then pass the delegate to the API/function.
April 14, 2014
On Monday, 14 April 2014 at 17:48:31 UTC, Adam D. Ruppe wrote:
> On Monday, 14 April 2014 at 17:45:52 UTC, Ryan Voots wrote:
>> src/yage/core/misc.d(164): Error: e2ir: cannot cast this of type S to type void*
>
>
> Try taking the address of this before casting it. So more like
>
> cast(void*)&this
>
>
> IIRC in D1 this was a pointer, whereas in D2 this is a reference. You can't cast a reference to pointer directly.

That's not true.

And I think the issue in his diagnostic is that he used it with a struct. You can't cast 'this' of a struct to a pointer (you'd have to use &this), but you can cast a class reference to a pointer.
April 15, 2014
On 04/14/14 19:51, Andrej Mitrovic wrote:
> On Monday, 14 April 2014 at 17:48:31 UTC, Adam D. Ruppe wrote:
>> On Monday, 14 April 2014 at 17:45:52 UTC, Ryan Voots wrote:
>>> src/yage/core/misc.d(164): Error: e2ir: cannot cast this of type S to type void*
>>
>>
>> Try taking the address of this before casting it. So more like
>>
>> cast(void*)&this
>>
>>
>> IIRC in D1 this was a pointer, whereas in D2 this is a reference. You can't cast a reference to pointer directly.
> 
> That's not true.
> 
> And I think the issue in his diagnostic is that he used it with a struct. You can't cast 'this' of a struct to a pointer (you'd have to use &this), but you can cast a class reference to a pointer.

It *is* true. Classes are /reference types/, not references to classes.
[There's no such thing as a "class payload" in D. Also, you can have a
 D-ref to a D-class.]

D doesn't have "true" references, just a storage-class based hack, that only supports a small subset of ref functionality. But these pseudo-refs still act as the objects they point to.

artur
April 15, 2014
On 4/15/14, Artur Skawina <art.08.09@gmail.com> wrote:
> It *is* true. Classes are /reference types/, not references to classes.

I meant the part where he said you can't cast a reference to a pointer. You can.
April 15, 2014
On 04/15/14 13:30, Andrej Mitrovic wrote:
> On 4/15/14, Artur Skawina <art.08.09@gmail.com> wrote:
>> It *is* true. Classes are /reference types/, not references to classes.
> 
> I meant the part where he said you can't cast a reference to a pointer. You can.

He obviously meant that you can't get a pointer to the object, that the reference points to, just by casting and w/o address-of.

   int* f(ref int r) { return cast(int*)r; }

   void main() {
      int a = 42;

      import std.stdio;
      writeln(&a);
      writeln(f(a));
   }

Yes, this will compile, and, yes, you can "cast a reference to a pointer", but this does not mean that you will get a pointer to 'a'.

The D situation wrt to refs and classes is bad enough; saying that you "can cast a reference to a pointer" will only confuse people.

artur
April 15, 2014
On Tuesday, 15 April 2014 at 12:05:09 UTC, Artur Skawina wrote:
> He obviously meant that you can't get a pointer to the object, that the> reference points to, just by casting and w/o address-of.

Yea, you can cast a class reference to void* (which does include
this inside a class), but not a ref storage class thingy which
includes this inside a struct. Since the topic at hand was a
struct I got a bit sloppy in my wording.

So I'd say we're all partially right, just in different contexts
:)
April 15, 2014
On 4/15/14, Artur Skawina <art.08.09@gmail.com> wrote:
> He obviously meant that you can't get a pointer to the object, that the reference points to, just by casting and w/o address-of.

Ah right. I don't do this often so I forgot. The proper code would be:

int* f(ref int r) { return &r; }