Re: Member function pointers

2015-09-11 Thread Vladimir Panteleev via Digitalmars-d

On Friday, 11 September 2015 at 00:37:35 UTC, data man wrote:
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir 
Panteleev wrote:

...

Heh. My fault. Fixed (though it'll stick for that post in some 
views).


Correct a "D-Runtime" topic, please. It is not updated.


Not sure what you mean, please clarify.

If it's not related to this thread, please file bugs on 
https://github.com/CyberShadow/DFeed/issues to avoid off-topic 
discussion.


Re: Member function pointers

2015-09-10 Thread John Colvin via Digitalmars-d
On Thursday, 10 September 2015 at 01:52:17 UTC, digitalmars.D 
wrote:
On 10 September 2015 at 04:55, Walter Bright via Digitalmars-d 
 wrote:

On 6/10/2013 7:33 AM, Manu wrote:


[...]



Sorry to say, your n.g. poster is back to its old tricks :-)


We've resolved this issue since 6/10/2013 no? ;)


In the web forum, this post shows up as having author 
"digitalmars.D", not even "Manu via Digitalmars-d" like your 
posts normally do and definitely not "Manu" like it should.


CyberShadow?


Re: Member function pointers

2015-09-10 Thread Vladimir Panteleev via Digitalmars-d

On Thursday, 10 September 2015 at 16:18:13 UTC, John Colvin wrote:
On Thursday, 10 September 2015 at 01:52:17 UTC, digitalmars.D 
wrote:
On 10 September 2015 at 04:55, Walter Bright via Digitalmars-d 
 wrote:

On 6/10/2013 7:33 AM, Manu wrote:


[...]



Sorry to say, your n.g. poster is back to its old tricks :-)


We've resolved this issue since 6/10/2013 no? ;)


In the web forum, this post shows up as having author 
"digitalmars.D", not even "Manu via Digitalmars-d" like your 
posts normally do and definitely not "Manu" like it should.


CyberShadow?


Heh. My fault. Fixed (though it'll stick for that post in some 
views).


Re: Member function pointers

2015-09-10 Thread via Digitalmars-d
On Thursday, 10 September 2015 at 21:29:15 UTC, Vladimir 
Panteleev wrote:
Doesn't happen here, so that's something local to you, almost 
surely unrelated to the above. Try clearing your cookies.


Yes, it was caused by cookies, but it wasn't local since it 
returned a HTTP status 500. It happend on the web server.




Re: Member function pointers

2015-09-10 Thread Vladimir Panteleev via Digitalmars-d
On Thursday, 10 September 2015 at 21:24:17 UTC, Ola Fosheim 
Grøstad wrote:
On Thursday, 10 September 2015 at 20:15:15 UTC, Vladimir 
Panteleev wrote:
On Thursday, 10 September 2015 at 19:40:02 UTC, Ola Fosheim 
Grøstad wrote:
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir 
Panteleev wrote:
Heh. My fault. Fixed (though it'll stick for that post in 
some views).


Now the main index says: "Unexpected end of input when 
converting from type string to type long".


Doesn't happen here, so that's something local to you, almost 
surely unrelated to the above. Try clearing your cookies.


Request URL:http://forum.dlang.org/
Request Method:GET
Status Code:500 Internal Server Error


Doesn't happen here, so that's something local to you, almost 
surely unrelated to the above. Try clearing your cookies.


Re: Member function pointers

2015-09-10 Thread data man via Digitalmars-d
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir 
Panteleev wrote:

...

Heh. My fault. Fixed (though it'll stick for that post in some 
views).


Correct a "D-Runtime" topic, please. It is not updated.


Re: Member function pointers

2015-09-10 Thread via Digitalmars-d
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir 
Panteleev wrote:
Heh. My fault. Fixed (though it'll stick for that post in some 
views).


Now the main index says: "Unexpected end of input when converting 
from type string to type long".





Re: Member function pointers

2015-09-10 Thread Vladimir Panteleev via Digitalmars-d
On Thursday, 10 September 2015 at 19:40:02 UTC, Ola Fosheim 
Grøstad wrote:
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir 
Panteleev wrote:
Heh. My fault. Fixed (though it'll stick for that post in some 
views).


Now the main index says: "Unexpected end of input when 
converting from type string to type long".


Doesn't happen here, so that's something local to you, almost 
surely unrelated to the above. Try clearing your cookies.


Re: Member function pointers

2015-09-10 Thread via Digitalmars-d
On Thursday, 10 September 2015 at 20:15:15 UTC, Vladimir 
Panteleev wrote:
On Thursday, 10 September 2015 at 19:40:02 UTC, Ola Fosheim 
Grøstad wrote:
On Thursday, 10 September 2015 at 16:24:52 UTC, Vladimir 
Panteleev wrote:
Heh. My fault. Fixed (though it'll stick for that post in 
some views).


Now the main index says: "Unexpected end of input when 
converting from type string to type long".


Doesn't happen here, so that's something local to you, almost 
surely unrelated to the above. Try clearing your cookies.


Request URL:http://forum.dlang.org/
Request Method:GET
Status Code:500 Internal Server Error




Re: Member function pointers

2015-09-09 Thread bitwise via Digitalmars-d

On Wednesday, 9 September 2015 at 18:33:41 UTC, Prudence wrote:

On Tuesday, 27 May 2014 at 12:21:40 UTC, d coder wrote:

[...]


What's the current state of this? I'm in need of such behavior 
for win32 interop.


I'm thinking that one can make the above code more general by 
using it in a mixin and automatically generating the funcptr 
signature:



import std.stdio;
import std.concurrency;

extern (C) int getch();
import std.string;


template FancyDelegate(O, D)
{
	const char[] FancyDelegate = "union "~O.stringof~"Delegate { 
"~D.stringof~" dg; struct { "~O.stringof~"* ptr; 
"~D.stringof.replace("delegate(", 
"function("~O.stringof~",").replace(",)", ")")~" funcptr; } }";	
	//const char[] FancyDelegate = "union "~O.stringof~"Delegate { 
"~D.stringof~" dg; struct { "~O.stringof~"* ptr; 
"~D.stringof.replace("delegate(", "function(")~" funcptr; } }";	

}

class X
{
public int z = 2;
public void foo(int x)
{
//writeln(this.z*x);
writeln(x);
}
}

void delegate(int) dg;

mixin(FancyDelegate!(X, typeof(dg)));


void main()
{

auto xX = new X();
XDelegate x;
x.dg = 

//x.dg(3);
x.ptr = 
x.funcptr(xX, 5);
//x.funcptr(5);


getch();
}

Unfortunately this fails when entering the function. I've tried 
various things(passing , etc..., passing nothing(the 
comments, etc.)


I thought a delegate, when called, was called like a member 
function? It seems that a delegate is some magic black box that 
we can't emulate in any way shape or form due to the calling 
conventions used?


struct S {
void fun() { writeln("fun" ); }
}

class C {
void fun() { writeln("fun" ); }
}

void main(string[] args) {
S s;
void delegate() fn1 = 
fn1();

C c = new C();
void delegate() fn2 = 
fn2();

void delegate() fn3;
fn3.ptr = cast(void*)
fn3.funcptr = 
fn3();

void delegate() fn4;
fn4.ptr = cast(void*)c;
fn4.funcptr = 
fn4();
}


Re: Member function pointers

2015-09-09 Thread Manu via Digitalmars-d
On 10 September 2015 at 04:55, Walter Bright via Digitalmars-d
 wrote:
> On 6/10/2013 7:33 AM, Manu wrote:
>>
>> [...]
>
>
> Sorry to say, your n.g. poster is back to its old tricks :-)

We've resolved this issue since 6/10/2013 no? ;)


Re: Member function pointers

2015-09-09 Thread Walter Bright via Digitalmars-d

On 9/9/2015 6:52 PM, Manu via Digitalmars-d wrote:

We've resolved this issue since 6/10/2013 no? ;)



:-)


Re: Member function pointers

2015-09-09 Thread Walter Bright via Digitalmars-d

On 6/7/2013 4:21 PM, Manu wrote:

So from my dconf talk, I detailed a nasty hack to handle member function
pointers in D.


https://www.digitalmars.com/articles/b68.html


Re: Member function pointers

2015-09-09 Thread Walter Bright via Digitalmars-d

On 6/10/2013 7:33 AM, Manu wrote:

[...]


Sorry to say, your n.g. poster is back to its old tricks :-)


Re: Member function pointers

2015-09-09 Thread Prudence via Digitalmars-d

On Tuesday, 27 May 2014 at 12:21:40 UTC, d coder wrote:

https://github.com/D-Programming-Language/dmd/pull/3181

Daniel asked me to use this. And it works.

Use something like:

union U
{
  void delegate(int) dg;
  struct
  {
void* ptr;
void function(int) funcptr;
  }
}
U u;
u.dg = dg;
u.funcptr = ...;
u.ptr = ...;

Regards
- Puneet


What's the current state of this? I'm in need of such behavior 
for win32 interop.


I'm thinking that one can make the above code more general by 
using it in a mixin and automatically generating the funcptr 
signature:



import std.stdio;
import std.concurrency;

extern (C) int getch();
import std.string;


template FancyDelegate(O, D)
{
	const char[] FancyDelegate = "union "~O.stringof~"Delegate { 
"~D.stringof~" dg; struct { "~O.stringof~"* ptr; 
"~D.stringof.replace("delegate(", 
"function("~O.stringof~",").replace(",)", ")")~" funcptr; } }";	
	//const char[] FancyDelegate = "union "~O.stringof~"Delegate { 
"~D.stringof~" dg; struct { "~O.stringof~"* ptr; 
"~D.stringof.replace("delegate(", "function(")~" funcptr; } }";	

}

class X
{
public int z = 2;
public void foo(int x)
{
//writeln(this.z*x);
writeln(x);
}
}

void delegate(int) dg;

mixin(FancyDelegate!(X, typeof(dg)));


void main()
{

auto xX = new X();
XDelegate x;
x.dg = 

//x.dg(3);
x.ptr = 
x.funcptr(xX, 5);
//x.funcptr(5);


getch();
}

Unfortunately this fails when entering the function. I've tried 
various things(passing , etc..., passing nothing(the comments, 
etc.)


I thought a delegate, when called, was called like a member 
function? It seems that a delegate is some magic black box that 
we can't emulate in any way shape or form due to the calling 
conventions used?


Re: Member function pointers

2015-09-09 Thread Freddy via Digitalmars-d

On Wednesday, 9 September 2015 at 20:18:06 UTC, Freddy wrote:
enum MemberFunc(alias Type, string member) = (ref Type self, 
Parameters!(__traits(getMember, Type, member)) args) => 
mixin(q{self.} ~ member ~ q{(args)});


Whoops the alias wasn't needed

enum MemberFunc(Type, string member) = (ref Type self, 
Parameters!(__traits(getMember, Type, member)) args) => 
mixin(q{self.} ~ member ~ q{(args)});




Re: Member function pointers

2015-09-09 Thread Freddy via Digitalmars-d
On Wednesday, 9 September 2015 at 18:55:18 UTC, Walter Bright 
wrote:

On 6/10/2013 7:33 AM, Manu wrote:

[...]


Sorry to say, your n.g. poster is back to its old tricks :-)


On 6/10/2013
That was 2 years ago.


Re: Member function pointers

2015-09-09 Thread Freddy via Digitalmars-d
On Wednesday, 9 September 2015 at 18:50:45 UTC, Walter Bright 
wrote:

On 6/7/2013 4:21 PM, Manu wrote:
So from my dconf talk, I detailed a nasty hack to handle 
member function

pointers in D.


https://www.digitalmars.com/articles/b68.html


Here's on automatic version

import std.traits : Parameters;

enum MemberFunc(alias Type, string member) = (ref Type self, 
Parameters!(__traits(getMember, Type, member)) args) => 
mixin(q{self.} ~ member ~ q{(args)});


unittest
{
static struct A
{
bool test;
void b(int arg)
{
test = arg == 4;
}
}

A a;
auto func = MemberFunc!(A, "b");
func(a,4);
assert(a.test);
}



Re: Member function pointers

2015-09-09 Thread Walter Bright via Digitalmars-d

On 9/9/2015 1:17 PM, Freddy wrote:

On Wednesday, 9 September 2015 at 18:55:18 UTC, Walter Bright wrote:

On 6/10/2013 7:33 AM, Manu wrote:

[...]


Sorry to say, your n.g. poster is back to its old tricks :-)


On 6/10/2013
That was 2 years ago.


Woops! I didn't notice. My reader sorts things based on the date of the last 
post.


Re: Member function pointers

2014-05-27 Thread d coder via Digitalmars-d
On Mon, Jun 10, 2013 at 10:13 PM, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 18:34, Manu wrote:

 On 11 June 2013 02:26, Jacob Carlborg d...@me.com mailto:d...@me.com

 wrote:

 On 2013-06-10 17:40, David Nadlinger wrote:

 Let me try to summarize it in code:

 ---
 class A { void foo(); }
 auto memberFun = (A.foo).funcptr;

 auto a = new A;
 memberFun(a);
 ---


 Why is this better than a delegate?


 It's not 'better', it's different.


 class A { void foo(); }
 auto memberFun = (A.foo).funcptr;

 auto a = new A;
 void delegate () dg;
 dg.funcptr = memberFun;
 dg.ptr = cast(void*) a;
 dg();

 The details can be hidden in a function call. Sure, a delegate could be
 type safe but still don't see the point.

 --
 /Jacob Carlborg


Greetings

Apologies for bringing up this year old thread.

With https://github.com/D-Programming-Language/dmd/pull/3181 getting
merged, it is no longer feasible to directly assign dg.funcptr (which is
not an lvalue now). The problem is that the code suggested by David also
does not work.

Is there an alternative?

Regards
- Puneet


Re: Member function pointers

2014-05-27 Thread d coder via Digitalmars-d
https://github.com/D-Programming-Language/dmd/pull/3181

Daniel asked me to use this. And it works.

Use something like:

union U
{
  void delegate(int) dg;
  struct
  {
void* ptr;
void function(int) funcptr;
  }
}
U u;
u.dg = dg;
u.funcptr = ...;
u.ptr = ...;

Regards
- Puneet


Re: Member function pointers

2013-06-11 Thread Daniel Murphy
Michel Fortin michel.for...@michelf.ca wrote in message 
news:kp4nr0$q71$1...@digitalmars.com...

 I just find it sad that we have to use a different calling convention for 
 member functions. I mean, it'd be much more elegant be if a member 
 function could simply be called from a void function(Object) by 
 supplying this as the first argument? Wouldn't it be better to adapt the 
 ABI to fit the language rather than adapt the language to fit the ABI?


For D, yes, and it would be awesome.  For everything else, never ever ever. 




Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-08 01:21, Manu wrote:

So from my dconf talk, I detailed a nasty hack to handle member function
pointers in D.
My approach is not portable, so I'd like to see an expression formalised
in D, so this sort of interaction with C++ is possible, and also it may
be useful in D code directly.

I'm thinking something like this... Keen to hear thoughts.

My approach was this:
   void function(T _this, ...args...);

Explicit 'this' pointer; only works with ABI's that pass 'this' as the
first integer argument.

What I suggest is:
   void function(T this, ...args...);

Note, I use keyword 'this' as the first argument. This is the key that
distinguishes the expression as a member-function pointer rather than a
typical function pointer. Calls through this function pointer would know
to use the method calling convention rather than the static function
calling convention.

For 'extern(C++) void function(T this)', that would be to use the C++
'thiscall' convention.

I think this makes good sense, because other than the choice of calling
convention, it really is just a 'function' in every other way.


Can't we just say that a delegate declared as extern(C++) is a member 
function? Or do you want to use member functions without connecting to 
C++ as well?


--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Manu
On 10 June 2013 16:50, Jacob Carlborg d...@me.com wrote:

 On 2013-06-08 01:21, Manu wrote:

 So from my dconf talk, I detailed a nasty hack to handle member function
 pointers in D.
 My approach is not portable, so I'd like to see an expression formalised
 in D, so this sort of interaction with C++ is possible, and also it may
 be useful in D code directly.

 I'm thinking something like this... Keen to hear thoughts.

 My approach was this:
void function(T _this, ...args...);

 Explicit 'this' pointer; only works with ABI's that pass 'this' as the
 first integer argument.

 What I suggest is:
void function(T this, ...args...);

 Note, I use keyword 'this' as the first argument. This is the key that
 distinguishes the expression as a member-function pointer rather than a
 typical function pointer. Calls through this function pointer would know
 to use the method calling convention rather than the static function
 calling convention.

 For 'extern(C++) void function(T this)', that would be to use the C++
 'thiscall' convention.

 I think this makes good sense, because other than the choice of calling
 convention, it really is just a 'function' in every other way.


 Can't we just say that a delegate declared as extern(C++) is a member
 function?


That seems pretty awkward to me. Basically a hack.
A function pointer is not a delegate, so I don't see why that should be
used to describe one.
Also, extern(C++) delegates are useful too in their own right

Or do you want to use member functions without connecting to C++ as well?


I haven't needed to yet... but that doesn't mean it might not be useful.
It would probably be used in D for tight binding with other systems.
AngelScript binds to native code with member function pointers... just off
the top of my head.


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 09:23, Manu wrote:


That seems pretty awkward to me. Basically a hack.
A function pointer is not a delegate, so I don't see why that should be
used to describe one.


It depends on how you look at it. In D a delegate is a function pointer 
with a context pointer. In C++ a pointer to a member function is 
basically the same, the context pointer is just passed separately.



Also, extern(C++) delegates are useful too in their own right


To do what? As far as I know C++ doesn't have anything corresponding to 
a D delegate.



I haven't needed to yet... but that doesn't mean it might not be useful.
It would probably be used in D for tight binding with other systems.
AngelScript binds to native code with member function pointers... just
off the top of my head.


Actually I don't see why you can't use a delegate for this. The only 
difference is that it won't be virtual.


--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Manu
On 10 June 2013 18:04, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 09:23, Manu wrote:

  That seems pretty awkward to me. Basically a hack.
 A function pointer is not a delegate, so I don't see why that should be
 used to describe one.


 It depends on how you look at it. In D a delegate is a function pointer
 with a context pointer. In C++ a pointer to a member function is basically
 the same, the context pointer is just passed separately.


A function pointer is a pointer. A delegate is a pointer to a function and
a context pointer, ie, 2 pointers.
A pointer to a method is just a pointer to a function, but it's a special
function which receives a 'this' argument with a special calling convention.
It's definitely useful to be able to express a 'thiscall' function pointer.

 Also, extern(C++) delegates are useful too in their own right


 To do what? As far as I know C++ doesn't have anything corresponding to a
 D delegate.


C++ has FastDelegate, which I use to interact with D delegates all the
time! ;)
extern(C++) delegate is required to specify the appropriate calling
convention, otherwise it's just a delegate like usual.

 I haven't needed to yet... but that doesn't mean it might not be useful.
 It would probably be used in D for tight binding with other systems.
 AngelScript binds to native code with member function pointers... just
 off the top of my head.


 Actually I don't see why you can't use a delegate for this. The only
 difference is that it won't be virtual.


I'm just trying to show that sometimes you don't want a delegate, you just
want a function pointer.
delegate's contain the function pointer I'm after, so I can access it
indirectly, but it's just not so useful. It's not typed (is void*), and you
can't call through it.


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 11:45, Manu wrote:


A function pointer is a pointer. A delegate is a pointer to a function
and a context pointer, ie, 2 pointers.
A pointer to a method is just a pointer to a function, but it's a
special function which receives a 'this' argument with a special calling
convention.
It's definitely useful to be able to express a 'thiscall' function pointer.


It's not very useful without the context pointer, i.e. this.


Also, extern(C++) delegates are useful too in their own right


To do what? As far as I know C++ doesn't have anything corresponding
to a D delegate.


C++ has FastDelegate, which I use to interact with D delegates all the
time! ;)


I didn't know about that. Is that something that is in the language or 
standard library?



extern(C++) delegate is required to specify the appropriate calling
convention, otherwise it's just a delegate like usual.


I see.


I'm just trying to show that sometimes you don't want a delegate, you
just want a function pointer.


Then use a function pointer.


delegate's contain the function pointer I'm after, so I can access it
indirectly, but it's just not so useful. It's not typed (is void*), and
you can't call through it.


The function pointer of a delegate is typed, it's the context pointer 
that is void*.


Sorry, I'm just trying to understand what you're doing, what problems 
you have. You can compose and decompose delegates using its built-in 
properties ptr and funcptr.


You can do something like:

class Foo
{
int i;

void a () { writeln(Foo.a i=, i); }
void b () { writeln(Foo.b i=, i); }
}

void main ()
{
auto f1 = new Foo;
f1.i = 3;
auto dg = f1.a;
dg();

auto f2 = new Foo;
f2.i = 4;
dg.ptr = cast(void*) f2;
dg();

dg.funcptr = Foo.b;
dg();
}

The only thing that doesn't work with the above is if I change the 
context pointer to a subclass of Foo which overrides the method I want 
to call. It will still call the method in Foo unless I change funcptr.


--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Michel Fortin

On 2013-06-10 08:04:43 +, Jacob Carlborg d...@me.com said:


On 2013-06-10 09:23, Manu wrote:


That seems pretty awkward to me. Basically a hack.
A function pointer is not a delegate, so I don't see why that should be
used to describe one.


It depends on how you look at it. In D a delegate is a function pointer 
with a context pointer. In C++ a pointer to a member function is 
basically the same, the context pointer is just passed separately.


But a true member function pointer is also parametrized on the type of 
this, unlike a delegate, letting you change the object pointer in a 
type-safe manner.


(And implementation-wise, C++ function pointers can be really 
complicated beasts in order to support virtual calling and 
multiple/virtual inheritance. sizeof can even change depending on the 
type of this. That's not what you want in D.)



I haven't needed to yet... but that doesn't mean it might not be useful.
It would probably be used in D for tight binding with other systems.
AngelScript binds to native code with member function pointers... just
off the top of my head.


Actually I don't see why you can't use a delegate for this. The only 
difference is that it won't be virtual.


Type-safety. I mean, you can do this if you want:

auto funcptr = Object.toString;
auto object = new Object;

// now call our function using object
string delegate() deleg;
deleg.ptr = cast(void*)object;
deleg.funcptr = funcptr;

but this is not type-safe: the funcptr type (string function()) is 
actually wrong (it'll only work if called from a delegate) and the 
object pointer the in the delegate is a void*. All Manu is asking is 
that funcptr is of a correct type so you can call it directly by 
supplying this as an argument, like this:


funcptr(object);

The problem is that this correct type for the function pointer does 
not exist currently. Calling a member function uses a different ABI, so 
the type needs to know somehow its a pointer to a member function (and 
that its first parameter is this), otherwise the generated code at 
the call site will be all wrong.


--
Michel Fortin
michel.for...@michelf.ca
http://michelf.ca/



Re: Member function pointers

2013-06-10 Thread Manu
On 10 June 2013 21:35, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 11:45, Manu wrote:

  A function pointer is a pointer. A delegate is a pointer to a function
 and a context pointer, ie, 2 pointers.
 A pointer to a method is just a pointer to a function, but it's a
 special function which receives a 'this' argument with a special calling
 convention.
 It's definitely useful to be able to express a 'thiscall' function
 pointer.


 It's not very useful without the context pointer, i.e. this.


You supply 'this' at the time of calling. Read my OP.

 Also, extern(C++) delegates are useful too in their own right


 To do what? As far as I know C++ doesn't have anything corresponding
 to a D delegate.


 C++ has FastDelegate, which I use to interact with D delegates all the
 time! ;)


 I didn't know about that. Is that something that is in the language or
 standard library?


It's Don's work of art. It's also how I came to find out about D in the
first place ;)

 extern(C++) delegate is required to specify the appropriate calling
 convention, otherwise it's just a delegate like usual.


 I see.


  I'm just trying to show that sometimes you don't want a delegate, you
 just want a function pointer.


 Then use a function pointer.


There's no way to specify to use the 'thiscall' calling convention.
What I propose is a syntax that would describe a member function pointer,
and imply the appropriate calling convention.

 delegate's contain the function pointer I'm after, so I can access it
 indirectly, but it's just not so useful. It's not typed (is void*), and
 you can't call through it.


 The function pointer of a delegate is typed, it's the context pointer that
 is void*.

 Sorry, I'm just trying to understand what you're doing, what problems you
 have. You can compose and decompose delegates using its built-in properties
 ptr and funcptr.

 You can do something like:

 class Foo
 {
 int i;

 void a () { writeln(Foo.a i=, i); }
 void b () { writeln(Foo.b i=, i); }
 }

 void main ()
 {
 auto f1 = new Foo;
 f1.i = 3;
 auto dg = f1.a;
 dg();

 auto f2 = new Foo;
 f2.i = 4;
 dg.ptr = cast(void*) f2;
 dg();

 dg.funcptr = Foo.b;
 dg();
 }

 The only thing that doesn't work with the above is if I change the context
 pointer to a subclass of Foo which overrides the method I want to call. It
 will still call the method in Foo unless I change funcptr.


I wouldn't say that doesn't work, I'd say that works perfectly. A delegate
is just a 'this' and function pair. If you change 'this', there's no reason
the function should change.

funcptr pretends to be typed, but the type is just wrong. In your example,
the type is 'void function()', it should be 'void function(Foo this)'.
So it's actually a lie. You can't call it. I'm not sure why it's typed at
all... just a crash waiting to happen.
So what I'm suggesting is a syntax to express a member function pointer,
and then it could be properly typed.


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 14:36, Manu wrote:


You supply 'this' at the time of calling. Read my OP.


Yes, exactly. It needs this. It's the same thing as a delegate. It's 
just that with the delegate the context pointer and function pointer is 
combined. A function pointer (member or free) is useless if it's not called.



It's Don's work of art. It's also how I came to find out about D in the
first place ;)


I see.


There's no way to specify to use the 'thiscall' calling convention.
What I propose is a syntax that would describe a member function
pointer, and imply the appropriate calling convention.


Right. I suggested a different syntax, but you want to reserve that 
syntax for something that match a library implementation, that's not 
even in the standard.


It's like saying I want int[] to match MyIntArray implemented in C++.


funcptr pretends to be typed, but the type is just wrong. In your
example, the type is 'void function()', it should be 'void function(Foo
this)'.


void function() is part of the complete type. It becomes complete with 
the context pointer.



So it's actually a lie. You can't call it. I'm not sure why it's typed
at all... just a crash waiting to happen.


You can put a free function in a delegate and call it through the 
delegate. I guess you don't want that to be possible either.



So what I'm suggesting is a syntax to express a member function pointer,
and then it could be properly typed.


I don't think there's anything wrong with supporting C++ member function 
pointers but I don't think we need to add new syntax for it.


--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 14:32, Michel Fortin wrote:


Type-safety. I mean, you can do this if you want:

 auto funcptr = Object.toString;
 auto object = new Object;

 // now call our function using object
 string delegate() deleg;
 deleg.ptr = cast(void*)object;
 deleg.funcptr = funcptr;

but this is not type-safe: the funcptr type (string function()) is
actually wrong (it'll only work if called from a delegate) and the
object pointer the in the delegate is a void*. All Manu is asking is
that funcptr is of a correct type so you can call it directly by
supplying this as an argument, like this:

 funcptr(object);

The problem is that this correct type for the function pointer does
not exist currently. Calling a member function uses a different ABI, so
the type needs to know somehow its a pointer to a member function (and
that its first parameter is this), otherwise the generated code at the
call site will be all wrong.


Then he's asking for (more) type safe delegates and support for C++ 
member function pointers.


--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Dmitry Olshansky

08-Jun-2013 03:21, Manu пишет:

So from my dconf talk, I detailed a nasty hack to handle member function
pointers in D.
My approach is not portable, so I'd like to see an expression formalised
in D, so this sort of interaction with C++ is possible, and also it may
be useful in D code directly.

I'm thinking something like this... Keen to hear thoughts.

My approach was this:
   void function(T _this, ...args...);

Explicit 'this' pointer; only works with ABI's that pass 'this' as the
first integer argument.


I decided to see how convenient can be a solution to auto-generate a 
thunk function that has exactly this signutre. In ABIs where this is 
passed as first parameters that shouldn't be much of overhead.


Here is my first try, it needs to handle overload sets but that could be 
added. Second point is perfect forwarding (there is forward in 
std.typecons, avoided for now). It may as well depend on compiler bugs 
but it looks nice and clean :)


module mem_fun;

import std.traits, std.stdio;

template memThunk(string call, T, U...)
if(is(T == class))
{
auto memThunk(T self, U args)
{
return mixin(self. ~ call~(args));
}
}

struct memberFunc(T)
if(is(T == class))
{
static @property auto opDispatch(string fn)()
{
alias FnType = typeof(mixin(T.~fn));

return memThunk!(fn, T, ParameterTypeTuple!FnType);
}
}

class A{
void foo(int k)
{
writefln(Quack %d!\n, k);
}
}

unittest
{
void function (A, int) fun = memberFunc!A.foo;
A a = new A();
fun(a, 45); //prints Quack 45!
}


P.S. Having a way to express this-call calling convention explicitly 
could be very useful still especially taking into account recent 
enhancements to the extern(C++) support.


--
Dmitry Olshansky


Re: Member function pointers

2013-06-10 Thread Maxim Fomin

On Monday, 10 June 2013 at 12:53:34 UTC, Jacob Carlborg wrote:

On 2013-06-10 14:36, Manu wrote:
funcptr pretends to be typed, but the type is just wrong. In 
your
example, the type is 'void function()', it should be 'void 
function(Foo

this)'.


void function() is part of the complete type. It becomes 
complete with the context pointer.


I wouldn't say so. The fact that you pass context has nothing to 
do with determining type. For example, you can pass A class 
instead of B to B method, but B method would still keep its 
original type.


So yes, there is a type problem in language when function taking 
some parameter is declared as having no such parameter. This is a 
serious hole in type system.




Re: Member function pointers

2013-06-10 Thread Manu
On 10 June 2013 22:53, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 14:36, Manu wrote:

  You supply 'this' at the time of calling. Read my OP.


 Yes, exactly. It needs this. It's the same thing as a delegate. It's
 just that with the delegate the context pointer and function pointer is
 combined. A function pointer (member or free) is useless if it's not called.


  It's Don's work of art. It's also how I came to find out about D in the
 first place ;)


 I see.


  There's no way to specify to use the 'thiscall' calling convention.
 What I propose is a syntax that would describe a member function
 pointer, and imply the appropriate calling convention.


 Right. I suggested a different syntax, but you want to reserve that syntax
 for something that match a library implementation, that's not even in the
 standard.

 It's like saying I want int[] to match MyIntArray implemented in C++.


No, I'm not talking about delegates. I'm not talking about FastDelegate
(that was an aside when you commented that C++ has no concept of delegate).
I'm just talking about function pointers. Not sure where you get this
analogy from?

 funcptr pretends to be typed, but the type is just wrong. In your
 example, the type is 'void function()', it should be 'void function(Foo
 this)'.


 void function() is part of the complete type. It becomes complete with
 the context pointer.


The context pointer type is not present in the type. So the function can't
be used/called.
It also doesn't know how to call it. What's the calling convention for
'void function()'? cdecl?

 So it's actually a lie. You can't call it. I'm not sure why it's typed
 at all... just a crash waiting to happen.


 You can put a free function in a delegate and call it through the
 delegate. I guess you don't want that to be possible either.


A free function? Like a static function? You can assign it, but it'll
crash. Free functions are cdecl, methods are thiscall.
If you know the ABI and it receives 'this' as the first integer argument,
you can fabricate a compatible signature and it won't crash, but it's not
portable.
This is my whole point about the type-safety. If we create an expression to
describe a method pointer, then we can actually do it safely and portably.

 So what I'm suggesting is a syntax to express a member function pointer,
 and then it could be properly typed.


 I don't think there's anything wrong with supporting C++ member function
 pointers but I don't think we need to add new syntax for it.


I'm not suggesting supporting 'C++ member function pointers', they are
completely bat-shit crazy.
I'm suggesting a distinctly D way. They will be useful when interfacing
C++, and also on their own, and unlike C++, they won't be totally mental.


Re: Member function pointers

2013-06-10 Thread Manu
On 10 June 2013 22:56, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 14:32, Michel Fortin wrote:

  Type-safety. I mean, you can do this if you want:

  auto funcptr = Object.toString;
  auto object = new Object;

  // now call our function using object
  string delegate() deleg;
  deleg.ptr = cast(void*)object;
  deleg.funcptr = funcptr;

 but this is not type-safe: the funcptr type (string function()) is
 actually wrong (it'll only work if called from a delegate) and the
 object pointer the in the delegate is a void*. All Manu is asking is
 that funcptr is of a correct type so you can call it directly by
 supplying this as an argument, like this:

  funcptr(object);

 The problem is that this correct type for the function pointer does
 not exist currently. Calling a member function uses a different ABI, so
 the type needs to know somehow its a pointer to a member function (and
 that its first parameter is this), otherwise the generated code at the
 call site will be all wrong.


 Then he's asking for (more) type safe delegates and support for C++ member
 function pointers.


I'm really not asking for delegates (although they could become more
typesafe given my suggestion), just a member function pointer. And not C++
style as you say, my suggestion is much simpler than that, and would fit
nicely in D.


Re: Member function pointers

2013-06-10 Thread David Nadlinger

On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:
I think this makes good sense, because other than the choice of 
calling

convention, it really is just a 'function' in every other way.


Another less intrusive option would be to just add 
extern(CppThisCall) and extern(DThisCall) or something along the 
lines, which would be specified to pass the first parameter as if 
it was a this pointer.


David


Re: Member function pointers

2013-06-10 Thread David Nadlinger

On Monday, 10 June 2013 at 13:45:37 UTC, Manu wrote:

What's the calling convention for
'void function()'? cdecl?


Walter's very own calling convention. It is supposed to match 
cdecl everywhere but x86, but has the argument order reversed. On 
x86, it's a custom one that's similar to stdcall in some ways.


David


Re: Member function pointers

2013-06-10 Thread Manu
On 10 June 2013 23:49, David Nadlinger c...@klickverbot.at wrote:

 On Monday, 10 June 2013 at 13:45:37 UTC, Manu wrote:

 What's the calling convention for
 'void function()'? cdecl?


 Walter's very own calling convention. It is supposed to match cdecl
 everywhere but x86, but has the argument order reversed. On x86, it's a
 custom one that's similar to stdcall in some ways.


Indeed. I presume 'extern(C) void function()' is cdecl though?
Likewise 'extern(C++) void function(T this)' would be 'thiscall', and 'void
function(T this)' would be whatever D's method calling convention happens
to be.


Re: Member function pointers

2013-06-10 Thread Manu
On 10 June 2013 23:46, David Nadlinger c...@klickverbot.at wrote:

 On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:

 I think this makes good sense, because other than the choice of calling
 convention, it really is just a 'function' in every other way.


 Another less intrusive option would be to just add extern(CppThisCall) and
 extern(DThisCall) or something along the lines, which would be specified to
 pass the first parameter as if it was a this pointer.


That would also do the business. Do you think that's less intrusive?
It feels a little hacky though. 'DThisCall' isn't really 'extern' so to
speak.
I like my suggestion a lot more. Little details like, what would you name
the 'this' argument? You'll end up with conventions like 'void function(T
_this)', and that's a bit untrue because there isn't an argument named
'_this', it's called 'this' inside the method.


Re: Member function pointers

2013-06-10 Thread David Nadlinger

On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:

On 10 June 2013 23:46, David Nadlinger c...@klickverbot.at
Another less intrusive option would be to just add 
extern(CppThisCall) and
extern(DThisCall) or something along the lines, which would be 
specified to

pass the first parameter as if it was a this pointer.



That would also do the business. Do you think that's less 
intrusive?


Less intrusive in the way that it is a minimal addition to the 
language itself (we already have several calling conventions), 
whereas your suggestion would require adding a special case to 
the grammar.


That's not to say I don't like your proposal, though. I just 
wanted to put the option on the table to be sure we are getting 
somewhere with this, even if some people might be opposed to the 
grammar change. This issue has been bugging me for quite some 
time as well.


It feels a little hacky though. 'DThisCall' isn't really 
'extern' so to speak.


extern(D) exists today – extern(xyz) should really be called 
abi(xyz), callingconv(xyz) or something like that instead.


David


Re: Member function pointers

2013-06-10 Thread Manu
On 11 June 2013 00:28, Michel Fortin michel.for...@michelf.ca wrote:

 On 2013-06-10 14:11:31 +, David Nadlinger c...@klickverbot.at
 said:

  On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:

 On 10 June 2013 23:46, David Nadlinger c...@klickverbot.at

 Another less intrusive option would be to just add extern(CppThisCall)
 and
 extern(DThisCall) or something along the lines, which would be
 specified to
 pass the first parameter as if it was a this pointer.


 That would also do the business. Do you think that's less intrusive?


 Less intrusive in the way that it is a minimal addition to the language
 itself (we already have several calling conventions), whereas your
 suggestion would require adding a special case to the grammar.

 That's not to say I don't like your proposal, though. I just wanted to
 put the option on the table to be sure we are getting somewhere with this,
 even if some people might be opposed to the grammar change. This issue has
 been bugging me for quite some time as well.


 It's inelegant, but it could work.

 I just find it sad that we have to use a different calling convention for
 member functions. I mean, it'd be much more elegant be if a member function
 could simply be called from a void function(Object) by supplying this
 as the first argument? Wouldn't it be better to adapt the ABI to fit the
 language rather than adapt the language to fit the ABI?


The ABI is the better part of half a century old...


Re: Member function pointers

2013-06-10 Thread Michel Fortin

On 2013-06-10 14:11:31 +, David Nadlinger c...@klickverbot.at said:


On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:

On 10 June 2013 23:46, David Nadlinger c...@klickverbot.at

Another less intrusive option would be to just add extern(CppThisCall) and
extern(DThisCall) or something along the lines, which would be specified to
pass the first parameter as if it was a this pointer.


That would also do the business. Do you think that's less intrusive?


Less intrusive in the way that it is a minimal addition to the language 
itself (we already have several calling conventions), whereas your 
suggestion would require adding a special case to the grammar.


That's not to say I don't like your proposal, though. I just wanted to 
put the option on the table to be sure we are getting somewhere with 
this, even if some people might be opposed to the grammar change. This 
issue has been bugging me for quite some time as well.


It's inelegant, but it could work.

I just find it sad that we have to use a different calling convention 
for member functions. I mean, it'd be much more elegant be if a member 
function could simply be called from a void function(Object) by 
supplying this as the first argument? Wouldn't it be better to adapt 
the ABI to fit the language rather than adapt the language to fit the 
ABI?


--
Michel Fortin
michel.for...@michelf.ca
http://michelf.ca/



Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 15:47, Manu wrote:


I'm really not asking for delegates (although they could become more
typesafe given my suggestion), just a member function pointer. And not
C++ style as you say, my suggestion is much simpler than that, and would
fit nicely in D.


I give up, I don't understand what you want.

--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Manu
On 11 June 2013 00:43, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 15:47, Manu wrote:

  I'm really not asking for delegates (although they could become more
 typesafe given my suggestion), just a member function pointer. And not
 C++ style as you say, my suggestion is much simpler than that, and would
 fit nicely in D.


 I give up, I don't understand what you want.


...a member function pointer syntax. It's not that complex.

My suggestion is: void function(T this) funcptr;
This is a function pointer (not a delegate), but using keyword 'this' gives
the critical detail to the compiler that it's a member function pointer,
and to use the appropriate calling convention when making calls through
this pointer.
UFCS makes it awesome.


Re: Member function pointers

2013-06-10 Thread David Nadlinger

On Monday, 10 June 2013 at 14:43:50 UTC, Jacob Carlborg wrote:

On 2013-06-10 15:47, Manu wrote:

I'm really not asking for delegates (although they could 
become more
typesafe given my suggestion), just a member function pointer. 
And not
C++ style as you say, my suggestion is much simpler than that, 
and would

fit nicely in D.


I give up, I don't understand what you want.


Let me try to summarize it in code:

---
class A { void foo(); }
auto memberFun = (A.foo).funcptr;

auto a = new A;
memberFun(a);
---

David


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 17:36, Manu wrote:


My suggestion is: void function(T this) funcptr;
This is a function pointer (not a delegate), but using keyword 'this'
gives the critical detail to the compiler that it's a member function
pointer, and to use the appropriate calling convention when making calls
through this pointer.
UFCS makes it awesome.


What I don't understand is what this give you that a delegate doesn't. 
You need the this pointer to call the function pointer anyway. With a 
delegate it's bundled.


--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 17:40, David Nadlinger wrote:


Let me try to summarize it in code:

---
class A { void foo(); }
auto memberFun = (A.foo).funcptr;

auto a = new A;
memberFun(a);
---


Why is this better than a delegate?

--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Manu
On 11 June 2013 02:26, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 17:40, David Nadlinger wrote:

  Let me try to summarize it in code:

 ---
 class A { void foo(); }
 auto memberFun = (A.foo).funcptr;

 auto a = new A;
 memberFun(a);
 ---


 Why is this better than a delegate?


It's not 'better', it's different.


Re: Member function pointers

2013-06-10 Thread Manu
On 11 June 2013 02:28, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 17:36, Manu wrote:

  My suggestion is: void function(T this) funcptr;
 This is a function pointer (not a delegate), but using keyword 'this'
 gives the critical detail to the compiler that it's a member function
 pointer, and to use the appropriate calling convention when making calls
 through this pointer.
 UFCS makes it awesome.


 What I don't understand is what this give you that a delegate doesn't. You
 need the this pointer to call the function pointer anyway. With a
 delegate it's bundled.


It's just a pointer, 'this' is associated at the call site. And it's
strongly typed.
If you don't want a bundle, why be forced to use a bundled type?

Consider this, why would you ever want an int* when you can have an int[]?
We could remove the syntax for int*, and make it only accessible via
int[].ptr... and make: is(typeof(int[].ptr) == size_t)? :)


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 18:34, Manu wrote:

On 11 June 2013 02:26, Jacob Carlborg d...@me.com mailto:d...@me.com
wrote:

On 2013-06-10 17:40, David Nadlinger wrote:

Let me try to summarize it in code:

---
class A { void foo(); }
auto memberFun = (A.foo).funcptr;

auto a = new A;
memberFun(a);
---


Why is this better than a delegate?


It's not 'better', it's different.


class A { void foo(); }
auto memberFun = (A.foo).funcptr;

auto a = new A;
void delegate () dg;
dg.funcptr = memberFun;
dg.ptr = cast(void*) a;
dg();

The details can be hidden in a function call. Sure, a delegate could be 
type safe but still don't see the point.


--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread dennis luehring

Am 10.06.2013 18:28, schrieb Jacob Carlborg:

On 2013-06-10 17:36, Manu wrote:


My suggestion is: void function(T this) funcptr;
This is a function pointer (not a delegate), but using keyword 'this'
gives the critical detail to the compiler that it's a member function
pointer, and to use the appropriate calling convention when making calls
through this pointer.
UFCS makes it awesome.


What I don't understand is what this give you that a delegate doesn't.
You need the this pointer to call the function pointer anyway. With a
delegate it's bundled.



maybe he just don't need one to handle the this ptr because he wants to 
call several/hundrets of member-functions?


Re: Member function pointers

2013-06-10 Thread Jacob Carlborg

On 2013-06-10 18:38, dennis luehring wrote:


maybe he just don't need one to handle the this ptr because he wants to
call several/hundrets of member-functions?


How does he call a pointer to a member function without the this pointer?

--
/Jacob Carlborg


Re: Member function pointers

2013-06-10 Thread Manu
On 11 June 2013 02:43, Jacob Carlborg d...@me.com wrote:

 On 2013-06-10 18:34, Manu wrote:

 On 11 June 2013 02:26, Jacob Carlborg d...@me.com mailto:d...@me.com

 wrote:

 On 2013-06-10 17:40, David Nadlinger wrote:

 Let me try to summarize it in code:

 ---
 class A { void foo(); }
 auto memberFun = (A.foo).funcptr;

 auto a = new A;
 memberFun(a);
 ---


 Why is this better than a delegate?


 It's not 'better', it's different.


 class A { void foo(); }
 auto memberFun = (A.foo).funcptr;

 auto a = new A;
 void delegate () dg;
 dg.funcptr = memberFun;
 dg.ptr = cast(void*) a;
 dg();

 The details can be hidden in a function call. Sure, a delegate could be
 type safe but still don't see the point.


You can see how much work that is right? And it's still not typesafe.
It's totally a hack.


Re: Member function pointers

2013-06-10 Thread Steven Schveighoffer

On Mon, 10 Jun 2013 12:45:12 -0400, Jacob Carlborg d...@me.com wrote:


On 2013-06-10 18:38, dennis luehring wrote:


maybe he just don't need one to handle the this ptr because he wants to
call several/hundrets of member-functions?


How does he call a pointer to a member function without the this  
pointer?


Like this:

void callRandomMember(C[] objs, memberPointerToCMethod p)
{
   objs[random(0, objs.length)].p();
}

Essentially, you bind at call time to form a delegate.  But the member  
function pointer's 'this' must be strongly typed.


-Steve


Re: Member function pointers

2013-06-10 Thread Simen Kjaeraas

On Mon, 10 Jun 2013 14:53:33 +0200, Jacob Carlborg d...@me.com wrote:


On 2013-06-10 14:36, Manu wrote:


funcptr pretends to be typed, but the type is just wrong. In your
example, the type is 'void function()', it should be 'void function(Foo
this)'.


void function() is part of the complete type. It becomes complete with  
the context pointer.


This is utter horseshit. Not that it's part of the complete type, nor even
that it becomes complete with the context pointer (though that is highly
dubious at best), but the type of funcptr. It's a disgrace, simple as that.
It should either be typeless, or it should take a void* as its first
argument. void* means 'magic ahead', so it would be kinda ok.

--
Simen


Re: Member function pointers

2013-06-10 Thread David Nadlinger

On Monday, 10 June 2013 at 20:31:32 UTC, Simen Kjaeraas wrote:

or it should take a void* as its first
argument. void* means 'magic ahead', so it would be kinda ok.


This would encourage people to try something like 
dg.funcptr(dg.ptr, ...), which is not correct ABI-wise.


David


Re: Member function pointers

2013-06-10 Thread Kenji Hara
Manu, is this that you want?

class C
{
int foo() { printf(invoke C.foo()\n); return 1; }
int bar() { printf(invoke C.bar()\n); return 2; }
int bar(string s) { printf(invoke C.bar(string)\n); return s.length; }
}
class D : C
{
override int foo() { printf(invoke D.func\n); return 4; }
}

void main()
{
D d = new D();

MemFunPtr!C.foo!() fpFoo = d;
MemFunPtr!C.bar!() fpBar = d;
MemFunPtr!C.bar!(string) fpBar2 = d;

assert(fpFoo() == 4);
assert(fpBar() == 2);
assert(fpBar2(hello) == 5);

static assert(fpFoo.sizeof == (void*).sizeof);
}

// -
// Implementation
// -

import std.traits, std.typetuple;

template MemFunPtr(C) if (is(C == class))
{
mixin GenName!C;
}
mixin template GenName(C, size_t i = 0)
{
alias names = allMembers!C;
static if (i = names.length)
{
/* do nothing */
}
else
{
enum name = names[i];
alias vfuncs = TypeTuple!(__traits(getVirtualFunctions, C, name));
static if (vfuncs.length  0)
{
struct _Impl(Params...)
{
private:
C obj;
alias VtblEntry = GetVtblEntry!(C, name, Params);
private:
this(C obj) { this.obj = obj; }

auto ref opCall(Params args)
{
alias R = ReturnType!(VtblEntry.func);

R delegate(Params) dg;
dg.ptr = *cast(void**)obj;
dg.funcptr = cast(R
function(Params))obj.__vptr[VtblEntry.vindex];
return dg(args);
}
}
mixin(alias _Impl ~name~;);
}
mixin .GenName!(C, i + 1);
}
}
template GetVtblEntry(C, string name, Params...)
{
alias names = allMembers!C;
template Impl(size_t ofs, size_t i)
{
alias vfuncs = TypeTuple!(__traits(getVirtualFunctions, C,
names[i]));
static if (names[i] != name)
{
alias Impl = Impl!(ofs + vfuncs.length, i + 1);
}
else
{
static assert(vfuncs.length  0);
template Impl2(size_t j)
{
static if (is(ParameterTypeTuple!(vfuncs[j]) == Params))
{
enum vindex = ofs + j;
alias func = vfuncs[j];
}
else
alias Impl2 = Impl2!(j + 1);
}
alias Impl = Impl2!(0);
}
}
alias GetVtblEntry = Impl!(1/*vtbl[0] == TypeInfo*/, 0);
}

template baseMembers(BC...)
{
static if (BC.length  1)
{
alias baseMembers =
TypeTuple!( allMembers!(BC[0]),
baseMembers!(BC[1 .. $]) );
}
else static if (BC.length == 1)
{
alias baseMembers = allMembers!(BC[0]);
}
else
alias baseMembers = TypeTuple!();
}
template derivedMembers(C)
{
alias derivedMembers =
TypeTuple!( __traits(derivedMembers, C) );
}
template allMembers(C)
{
alias allMembers =
TypeTuple!( baseMembers!(BaseClassesTuple!C),
__traits(derivedMembers, C) );
}

Kenji Hara


2013/6/8 Manu turkey...@gmail.com

 So from my dconf talk, I detailed a nasty hack to handle member function
 pointers in D.
 My approach is not portable, so I'd like to see an expression formalised
 in D, so this sort of interaction with C++ is possible, and also it may be
 useful in D code directly.

 I'm thinking something like this... Keen to hear thoughts.

 My approach was this:
   void function(T _this, ...args...);

 Explicit 'this' pointer; only works with ABI's that pass 'this' as the
 first integer argument.

 What I suggest is:
   void function(T this, ...args...);

 Note, I use keyword 'this' as the first argument. This is the key that
 distinguishes the expression as a member-function pointer rather than a
 typical function pointer. Calls through this function pointer would know to
 use the method calling convention rather than the static function calling
 convention.

 For 'extern(C++) void function(T this)', that would be to use the C++
 'thiscall' convention.

 I think this makes good sense, because other than the choice of calling
 convention, it really is just a 'function' in every other way.

 Now taken this as a declaration syntax, I think calls would be made via
 UFCS.

 T x;
 void function(T this) mp;

 mp(x); // I guess this is fine
 x.mp(); // but UFCS really makes this concept nice!

 So the final detail, is how to capture one of these member function
 pointers from within D...
 I initially thought about a syntax, but this is so niche, I don't think it
 warrants a syntax.
 So my current best idea is to introduce 2 properties to delegates, so that
 the function pointer (of this type) can be accessed via the delegate syntax.

 delegate d = x.f;
 void function(T this) mp = d.funcPtr;

 An interesting side effect, is that 

Re: Member function pointers

2013-06-07 Thread Adam D. Ruppe

On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:
Currently, to get the instance or function pointers from a 
delegate, you need to do something like:


delegates have two members, ptr and funcptr:
http://dlang.org/function.html

As a fun fact, if you modify druntime's allocator to be malloc(), 
you can use free(delegate.ptr) to manually manage closures, 
though this takes a lot of care to know if it actually should be 
freed or not.


Anyway, the ptr member there is always void*, however, so at 
least one cast is required to actually use it. Perhaps the 
language could be extended to make this strongly typed, but then 
you'd have to change the whole visible type as assigning say, a 
closure to a delegate variable would need to be a different type 
than a class member; I guess this is what you're talking about 
though.


idk, I've kinda wanted pointer to members before but I also think 
D's delegates being so versatile and interchangeable is totally 
boss.


I don't know a syntax to describe the type of a closure, so 
when a delegate is typed with a closure instead of a 
struct/class,

what is 'C' in the struct template above?


That's a tricky one, perhaps it could be a tuple of the captured 
variables' type.


Re: Member function pointers

2013-06-07 Thread Michel Fortin

On 2013-06-07 23:21:53 +, Manu turkey...@gmail.com said:


Thoughts?


Reminds me of something similar I implemented a while ago:
http://michelf.ca/projects/d-objc/syntax/#selector-literals

Not only I think member function pointers are doable, but I think 
they're solely missing. There have been situations where I'd have used 
them but instead had to hack my way using a delegate. That was to build 
a bridge for Objective-C (before I decided to hack the compiler). I'd 
guess you're doing something of the sort too?


--
Michel Fortin
michel.for...@michelf.ca
http://michelf.ca/



Re: Member function pointers

2013-06-07 Thread Manu
On 8 June 2013 09:42, Adam D. Ruppe destructiona...@gmail.com wrote:

 On Friday, 7 June 2013 at 23:22:03 UTC, Manu wrote:

 Currently, to get the instance or function pointers from a delegate, you
 need to do something like:


 delegates have two members, ptr and funcptr:
 http://dlang.org/function.html

 As a fun fact, if you modify druntime's allocator to be malloc(), you can
 use free(delegate.ptr) to manually manage closures, though this takes a lot
 of care to know if it actually should be freed or not.

 Anyway, the ptr member there is always void*, however, so at least one
 cast is required to actually use it. Perhaps the language could be extended
 to make this strongly typed, but then you'd have to change the whole
 visible type as assigning say, a closure to a delegate variable would need
 to be a different type than a class member; I guess this is what you're
 talking about though.


Indeed, I apologise for my ignorance! The properties are already there...
but they're not properly typed.

idk, I've kinda wanted pointer to members before but I also think D's
 delegates being so versatile and interchangeable is totally boss.


I agree, a delegate is almost always what I want. But a delegate is really
just a compound concept, and without a way to express it's fundamental
parts, which in certain circumstances (like in my case) are useful on their
own, then it feels like a bit of magic.

 I don't know a syntax to describe the type of a closure, so when a
 delegate is typed with a closure instead of a struct/class,
 what is 'C' in the struct template above?


 That's a tricky one, perhaps it could be a tuple of the captured
 variables' type.


Yeah, that was my initial feeling too... and I think it could be quite
workable in that way.


Re: Member function pointers

2013-06-07 Thread Manu
On 8 June 2013 09:48, Michel Fortin michel.for...@michelf.ca wrote:

 On 2013-06-07 23:21:53 +, Manu turkey...@gmail.com said:

  Thoughts?


 Reminds me of something similar I implemented a while ago:
 http://michelf.ca/projects/d-**objc/syntax/#selector-literalshttp://michelf.ca/projects/d-objc/syntax/#selector-literals

 Not only I think member function pointers are doable, but I think they're
 solely missing. There have been situations where I'd have used them but
 instead had to hack my way using a delegate. That was to build a bridge for
 Objective-C (before I decided to hack the compiler). I'd guess you're doing
 something of the sort too?


Precisely. The concept is already embedded inside of delegate, but delegate
is framed like a piece of magic, rather than a well defined compound of
more primitive pieces.
Those primitive pieces would be useful in certain cases (like mine, and
yours).

I think the only missing detail is a way to express a 'thiscall' function
pointer, which I believe my suggestion satisfies quite nicely.


Re: Member function pointers

2013-06-07 Thread Adam D. Ruppe

On Friday, 7 June 2013 at 23:54:55 UTC, Manu wrote:

The properties are already there...
but they're not properly typed.


I just don't think they can be unless we change the visible type 
which isn't always what we want but, check this out:


// this new type keeps track of the exact type of the pointer
// and manages the delegate so we can cast with some sanity...
struct PointerToMemberFunction(Class, Ret, T...) if(is(Class : 
Object)) {

private Ret delegate(T) dg;
@property Class object() { return cast(Class) dg.ptr; }
@property void object(Class rhs) { dg.ptr = cast(void*) rhs; }
Ret opCall(T t) {
assert(dg.ptr !is null, null this);
static if(is(Ret == void))
dg(t);
else
return dg(t);
}
}

// this helps us construct the above
template ptrToMember(alias blargh) {
// I'm writing out the function template longhand
// because I want to use blargh as a type and
// dmd won't let me do it without an intermediate

// dmd complains type expected, not __traits so we use
// this to work around it
template workaround(T) { alias workaround = T; }

alias ObjectType = workaround!(__traits(parent, blargh));

auto ptrToMember(ObjectType a = null) {
import std.traits;
PointerToMemberFunction!(
ObjectType,
ReturnType!blargh,
ParameterTypeTuple!blargh
) mem;
mem.dg.funcptr = blargh;
mem.dg.ptr = cast(void*) a;
return mem;
}
}


actually i just realized maybe this should not be a function at 
all, so it is easy to use as a class member, without having to 
write an extra typeof(). That's probably more valuable than the 
initialiser which as you'll see below is optional anyway.


Anyway, then you can use it like this:

class A {
void foo() {writeln(foo from , name);}
int bar(string s) {writeln(bar ,s, from , name); return 10; }
this(string n) { name = n; }
string name;
}

class B : A {
this(string n) { super(n); }
override void foo() { writeln(derived foo from , name); }
}


void main() {
A a = new A(a);
B c = new B(c);
Object ob = a;

auto ptr = ptrToMember!(B.foo)(c); // initialize the object here
ptr();
ptr.object = a;
ptr();

auto ptr2 = ptrToMember!(A.bar); // initialize to null..
ptr2.object = ptr.object; // can assign later
ptr2(hey);
}


And if you play around with the types there, you'll see the 
compile will fail if you do something uncool. Though the error 
messages sometimes suck, what the hell: test2.d(58): Error: not 
a property ptr.object... actually it is, but I was passing it an 
A when it required a B. That's a type mismatch, not a missing 
property.


But whatever, at least it *did* fail to compile, so we have our 
type safety.



And if I threw in an alias this on a getter property, we could 
assign these beasties to regular delegates too. Not half bad.


But regular delegate assigning to this is prohibited because we 
can't be sure their context pointer is the right kind of class. 
This would be true if the compiler automatically did the 
ptrToMember!() too, so let's say we change a.foo to return one 
of these strongly typed things instead of a void* delegate like 
it does now.


auto ptr = a.foo; // is ptr a void delegate() or a pointer to 
specifically a void() member of class A?



That matters because if the former (current behavior), this 
compiles:


ptr = { writeln(hello!); };


but if the latter, that will not, it will complain that the this 
pointers are of mismatching type (or not a property lol). Of 
course, with alias this style behavior, you could explicitly 
write out


void delegate() ptr = a.foo; // ok, use looser type
ptr = {...}; // perfectly fine



So I guess we wouldn't be losing much, but since we both agree a 
delegate is almost always what we want, maybe the library 
solution of ptrToMember is better to keep auto in a Just Works 
state.




I'm presuming you're already doing something similar for your C++ 
interop, if not, I'm pretty sure this same idea would work there 
too, at least to a 'good enough' state, even if not technically 
portable.



Yeah, that was my initial feeling too... and I think it could 
be quite workable in that way.


Aye, and this would require the compiler's help. Can't hit 'good 
enough' on that with templates.


Re: Member function pointers

2013-06-07 Thread Manu
On 8 June 2013 10:24, Adam D. Ruppe destructiona...@gmail.com wrote:

 On Friday, 7 June 2013 at 23:54:55 UTC, Manu wrote:

 The properties are already there...
 but they're not properly typed.


 I just don't think they can be unless we change the visible type which
 isn't always what we want but, check this out:

 // this new type keeps track of the exact type of the pointer
 // and manages the delegate so we can cast with some sanity...
 struct PointerToMemberFunction(Class, Ret, T...) if(is(Class : Object)) {
 private Ret delegate(T) dg;
 @property Class object() { return cast(Class) dg.ptr; }
 @property void object(Class rhs) { dg.ptr = cast(void*) rhs; }
 Ret opCall(T t) {
 assert(dg.ptr !is null, null this);
 static if(is(Ret == void))
 dg(t);
 else
 return dg(t);
 }
 }

 // this helps us construct the above
 template ptrToMember(alias blargh) {
 // I'm writing out the function template longhand
 // because I want to use blargh as a type and
 // dmd won't let me do it without an intermediate

 // dmd complains type expected, not __traits so we use
 // this to work around it
 template workaround(T) { alias workaround = T; }

 alias ObjectType = workaround!(__traits(parent, blargh));

 auto ptrToMember(ObjectType a = null) {
 import std.traits;
 PointerToMemberFunction!(
 ObjectType,
 ReturnType!blargh,
 ParameterTypeTuple!blargh
 ) mem;
 mem.dg.funcptr = blargh;
 mem.dg.ptr = cast(void*) a;
 return mem;
 }
 }


 actually i just realized maybe this should not be a function at all, so it
 is easy to use as a class member, without having to write an extra
 typeof(). That's probably more valuable than the initialiser which as
 you'll see below is optional anyway.

 Anyway, then you can use it like this:

 class A {
 void foo() {writeln(foo from , name);}
 int bar(string s) {writeln(bar ,s, from , name); return 10; }
 this(string n) { name = n; }
 string name;
 }

 class B : A {
 this(string n) { super(n); }
 override void foo() { writeln(derived foo from , name); }
 }


 void main() {
 A a = new A(a);
 B c = new B(c);
 Object ob = a;

 auto ptr = ptrToMember!(B.foo)(c); // initialize the object here
 ptr();
 ptr.object = a;
 ptr();

 auto ptr2 = ptrToMember!(A.bar); // initialize to null..
 ptr2.object = ptr.object; // can assign later
 ptr2(hey);
 }


 And if you play around with the types there, you'll see the compile will
 fail if you do something uncool. Though the error messages sometimes suck,
 what the hell: test2.d(58): Error: not a property ptr.object... actually
 it is, but I was passing it an A when it required a B. That's a type
 mismatch, not a missing property.

 But whatever, at least it *did* fail to compile, so we have our type
 safety.


 And if I threw in an alias this on a getter property, we could assign
 these beasties to regular delegates too. Not half bad.

 But regular delegate assigning to this is prohibited because we can't be
 sure their context pointer is the right kind of class. This would be true
 if the compiler automatically did the ptrToMember!() too, so let's say we
 change a.foo to return one of these strongly typed things instead of a
 void* delegate like it does now.

 auto ptr = a.foo; // is ptr a void delegate() or a pointer to
 specifically a void() member of class A?


 That matters because if the former (current behavior), this compiles:

 ptr = { writeln(hello!); };


 but if the latter, that will not, it will complain that the this pointers
 are of mismatching type (or not a property lol). Of course, with alias
 this style behavior, you could explicitly write out

 void delegate() ptr = a.foo; // ok, use looser type
 ptr = {...}; // perfectly fine



 So I guess we wouldn't be losing much, but since we both agree a delegate
 is almost always what we want, maybe the library solution of ptrToMember is
 better to keep auto in a Just Works state.



 I'm presuming you're already doing something similar for your C++ interop,
 if not, I'm pretty sure this same idea would work there too, at least to a
 'good enough' state, even if not technically portable.


I initially started with something like this. But look how much code it is!
I actually deleted it all and went for my non-portable hack.

My implementation was different. You've basically wrapped up a delegate,
and made something that emulates a delegate (I'm not sure why?).
I don't want a delegate, I want a function pointer. So my solution was
similar, but wrapped up a function pointer and aliased a delegate to 

Re: Member function pointers

2013-06-07 Thread Adam D. Ruppe

On Saturday, 8 June 2013 at 01:11:46 UTC, Manu wrote:
I initially started with something like this. But look how much 
code it is!


Yeah...

You've basically wrapped up a delegate, and made something that 
emulates a delegate

(I'm not sure why?).


I just wanted to add type safety to a delegate; to get rid of the 
visible cast(void*) and vice versa, to see what it would look 
like.


Re: Member function pointers

2013-06-07 Thread Michel Fortin

On 2013-06-07 23:57:40 +, Manu turkey...@gmail.com said:


Precisely. The concept is already embedded inside of delegate, but delegate
is framed like a piece of magic, rather than a well defined compound of
more primitive pieces.


Delegates are not parametrized on the type of this, which makes them 
easier to move around. I would not change delegates.


But function pointers with a this parameter would be useful. You can 
achieve this using a template struct containing a pointer and a call 
method: the call method would generate a local delegate variable from 
the pointer and and call it. What you can't do without compiler support 
is get such a pointer in a type-safe manner.


--
Michel Fortin
michel.for...@michelf.ca
http://michelf.ca/



Re: Member function pointers

2013-06-07 Thread Manu
On 8 June 2013 12:29, Michel Fortin michel.for...@michelf.ca wrote:

 On 2013-06-07 23:57:40 +, Manu turkey...@gmail.com said:

  Precisely. The concept is already embedded inside of delegate, but
 delegate
 is framed like a piece of magic, rather than a well defined compound of
 more primitive pieces.


 Delegates are not parametrized on the type of this, which makes them
 easier to move around. I would not change delegates.


Actually, that's very true. Good point, and I think this is almost the key
distinction.

But function pointers with a this parameter would be useful. You can
 achieve this using a template struct containing a pointer and a call
 method: the call method would generate a local delegate variable from the
 pointer and and call it. What you can't do without compiler support is get
 such a pointer in a type-safe manner.


Yup, this is what I originally did. It's big and ugly, I didn't like it,
and deleted it. I think the syntax I suggest is simple and obvious, and
naturally, typesafe.