www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Member function pointers

reply Manu <turkeyman gmail.com> writes:
--047d7b2e49623de24b04de98b218
Content-Type: text/plain; charset=UTF-8

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 'delegate' could actually be understood
as a strongly-typed small struct, whereas currently, it's just a magic
thing:

Given: RT delegate(A x, B y) d = &c.m;

It would look like:
struct delegate(C)
{
  C thisPointer;
  RT function(C this, A x, B, y) funcPointer;
}

Currently, to get the instance or function pointers from a delegate, you
need to do something like:
delegate d;
void** pd = cast(void**)&d;
T instancePointer = cast(T)pd[0];
void function(T this) functionPointer = cast(RT function(T this))pd[1];

Casting through a void array like that is pretty horrible.
Adding 2 properties to delegate to get either of those things can makes
sense once it is possible to express the type of the function pointer,
which would now be possible with the syntax above.

So, I quite like the transparency introduced when a delegate can be
explicitly described in the language. But there is one loose detail...

void f()
{
  void g() {}
  void delegate() d = &g; // delegate 'this' is a closure
}

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?


Thoughts?
Is there reason to outright ban this sort of expression?
I think this actually clarifies some details of the language, and reduces a
currently 'magic' thing into a well-defined, strongly-typed concept.

- Manu

--047d7b2e49623de24b04de98b218
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">So from my dconf talk, I detailed a nasty hack to handle m=
ember function pointers in D.<div>My approach is not portable, so I&#39;d l=
ike 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.<div>
<br></div><div style>I&#39;m thinking something like this... Keen to hear t=
houghts.</div></div><div style><br></div><div style>My approach was this:</=
div><div style>=C2=A0 void function(T _this, ...args...);<br></div><div sty=
le>
<br></div><div style>Explicit &#39;this&#39; pointer; only works with ABI&#=
39;s that pass &#39;this&#39; as the first integer argument.<br></div><div =
style><br></div><div style>What I suggest is:<br></div><div style>=C2=A0 vo=
id function(T this, ...args...);<br>
</div><div style><br></div><div style>Note, I use keyword &#39;this&#39; as=
 the first argument. This is the key that distinguishes the expression as a=
 member-function pointer rather than a typical function pointer. Calls thro=
ugh this function pointer would know to use the method calling convention r=
ather than the static function calling convention.</div>
<div style><br></div><div style>For &#39;extern(C++) void function(T this)&=
#39;, that would be to use the C++ &#39;thiscall&#39; convention.</div><div=
 style><br></div><div style>I think this makes good sense, because other th=
an the choice of calling convention, it really is just a &#39;function&#39;=
 in every other way.<br>
</div><div style><br></div><div style>Now taken this as a declaration synta=
x, I think calls would be made via UFCS.</div><div style><br></div><div>T x=
;</div><div style>void function(T this) mp;<br></div><div style><br></div>
<div style>mp(x); // I guess this is fine<br></div><div style><a href=3D"ht=
tp://x.mp">x.mp</a>(); // but UFCS really makes this concept nice!</div><di=
v style><br></div><div style>So the final detail, is how to capture one of =
these member function pointers from within D...</div>
<div style>I initially thought about a syntax, but this is so niche, I don&=
#39;t think it warrants a syntax.</div><div style>So my current best idea i=
s to introduce 2 properties to delegates, so that the function pointer (of =
this type) can be accessed via the delegate syntax.</div>
<div style><br></div><div style>delegate d =3D &amp;x.f;</div><div style>vo=
id function(T this) mp =3D d.funcPtr;</div><div style><br></div><div style>=
An interesting side effect, is that &#39;delegate&#39; could actually be un=
derstood as a strongly-typed small struct, whereas currently, it&#39;s just=
 a magic thing:</div>
<div style><br></div><div style>Given: RT delegate(A x, B y) d =3D &amp;c.m=
;</div><div style><br></div><div style>It would look like:</div><div style>=
struct delegate(C)</div><div style>{</div><div style>=C2=A0 C thisPointer;<=
/div>
<div style>=C2=A0 RT function(C this, A x, B, y) funcPointer;</div><div sty=
le>}</div><div style><br></div><div style>Currently, to get the instance or=
 function pointers from a delegate, you need to do something like:</div><di=
v style>
delegate d;</div><div style>void** pd =3D cast(void**)&amp;d;</div><div sty=
le>T instancePointer =3D cast(T)pd[0];</div><div style>void function(T this=
) functionPointer =3D cast(RT function(T this))pd[1];</div><div style><br><=
/div>
<div style>Casting through a void array like that is pretty horrible.</div>=
<div style>Adding 2 properties to delegate to get either of those things ca=
n makes sense once it is possible to express the type of the function point=
er, which would now be possible with the syntax above.</div>
<div style><br></div><div style>So, I quite like the transparency introduce=
d when a delegate can be explicitly described in the language. But there is=
 one loose detail...</div><div style><br></div><div style>void f()</div>
<div style>{</div><div style>=C2=A0 void g() {}</div><div style>=C2=A0 void=
 delegate() d =3D &amp;g; // delegate &#39;this&#39; is a closure<br></div>=
<div style>}</div><div style><br></div><div style>I don&#39;t know a syntax=
 to describe the type of a closure, so when a delegate is typed with a clos=
ure instead of a struct/class, what is &#39;C&#39; in the struct template a=
bove?</div>
<div style><br></div><div style><br></div><div style>Thoughts?</div><div st=
yle>Is there reason to outright ban this sort of expression?</div><div styl=
e>I think this actually clarifies some details of the language, and reduces=
 a currently &#39;magic&#39; thing into a well-defined, strongly-typed conc=
ept.</div>
<div style><br></div><div style>- Manu</div></div>

--047d7b2e49623de24b04de98b218--
Jun 07 2013
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Jun 07 2013
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-06-07 23:21:53 +0000, Manu <turkeyman 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.fortin michelf.ca http://michelf.ca/
Jun 07 2013
parent Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-06-07 23:57:40 +0000, Manu <turkeyman 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.fortin michelf.ca http://michelf.ca/
Jun 07 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--047d7b676104a086d204de992721
Content-Type: text/plain; charset=UTF-8

On 8 June 2013 09:42, Adam D. Ruppe <destructionator 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. --047d7b676104a086d204de992721 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 8 June 2013 09:42, Adam D. Ruppe <span dir=3D"ltr">&lt;= <a href=3D"mailto:destructionator gmail.com" target=3D"_blank">destructiona= tor gmail.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div clas= s=3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On Friday, 7 June 2013 at = 23:22:03 UTC, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Currently, to get the instance or function pointers from a delegate, you ne= ed to do something like:<br> </blockquote> <br></div> delegates have two members, ptr and funcptr:<br> <a href=3D"http://dlang.org/function.html" target=3D"_blank">http://dlang.o= rg/function.html</a><br> <br> As a fun fact, if you modify druntime&#39;s allocator to be malloc(), you c= an 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.<br> <br> 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&#39;d have to change the whole visib= le 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&#39;re talk= ing about though.<br> </blockquote><div><br></div><div style>Indeed, I apologise for my ignorance= ! The properties are already there... but they&#39;re not properly typed.</= div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 = .8ex;border-left:1px #ccc solid;padding-left:1ex"> idk, I&#39;ve kinda wanted pointer to members before but I also think D&#39= ;s delegates being so versatile and interchangeable is totally boss.</block= quote><div><br></div><div style>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&#39;s fundamental parts, which in certain circumstances (like= in my case) are useful on their own, then it feels like a bit of magic.</d= iv> <div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex= ;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"im"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> I don&#39;t know a syntax to describe the type of a closure, so when a dele= gate is typed with a closure instead of a struct/class,<br> what is &#39;C&#39; in the struct template above?<br> </blockquote> <br></div> That&#39;s a tricky one, perhaps it could be a tuple of the captured variab= les&#39; type.<br> </blockquote></div><br></div><div class=3D"gmail_extra" style>Yeah, that wa= s my initial feeling too... and I think it could be quite workable in that = way.</div></div> --047d7b676104a086d204de992721--
Jun 07 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--001a11c209d231723b04de993282
Content-Type: text/plain; charset=UTF-8

On 8 June 2013 09:48, Michel Fortin <michel.fortin michelf.ca> wrote:

 On 2013-06-07 23:21:53 +0000, Manu <turkeyman gmail.com> said:

  Thoughts?

Reminds me of something similar I implemented a while ago: http://michelf.ca/projects/d-**objc/syntax/#selector-literals<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?

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. --001a11c209d231723b04de993282 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 8 June 2013 09:48, Michel Fortin <span dir=3D"ltr">&lt;= <a href=3D"mailto:michel.fortin michelf.ca" target=3D"_blank">michel.fortin= michelf.ca</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div class= =3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex">On 2013-06-07 23:21:53 +0000, Manu &lt;<a hr= ef=3D"mailto:turkeyman gmail.com" target=3D"_blank">turkeyman gmail.com</a>= &gt; said:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Thoughts?<br> </blockquote> <br> Reminds me of something similar I implemented a while ago:<br> <a href=3D"http://michelf.ca/projects/d-objc/syntax/#selector-literals" tar= get=3D"_blank">http://michelf.ca/projects/d-<u></u>objc/syntax/#selector-li= terals</a><br> <br> Not only I think member function pointers are doable, but I think they&#39;= re solely missing. There have been situations where I&#39;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&#39;d guess you= &#39;re doing something of the sort too?</blockquote> <div><br></div><div style>Precisely. The concept is already embedded inside= of delegate, but delegate is framed like a piece of magic, rather than a w= ell defined compound of more primitive pieces.</div><div style>Those primit= ive pieces would be useful in certain cases (like mine, and yours).</div> <div style><br></div><div style>I think the only missing detail is a way to= express a &#39;thiscall&#39; function pointer, which I believe my suggesti= on satisfies quite nicely.</div></div></div></div> --001a11c209d231723b04de993282--
Jun 07 2013
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Jun 07 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--001a1132f8faaacb3804de9a3a74
Content-Type: text/plain; charset=UTF-8

On 8 June 2013 10:24, Adam D. Ruppe <destructionator 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 the correct type, then created a local delegate populating with 'this' and the function at the call-site... But it's all crap! It's really just abusing a delegate to get at the concept it embed's which doesn't have a proper expression. --001a1132f8faaacb3804de9a3a74 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 8 June 2013 10:24, Adam D. Ruppe <span dir=3D"ltr">&lt;= <a href=3D"mailto:destructionator gmail.com" target=3D"_blank">destructiona= tor gmail.com</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div clas= s=3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On Friday, 7 June 2013 at = 23:54:55 UTC, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> The properties are already there...<br> but they&#39;re not properly typed.<br> </blockquote> <br></div> I just don&#39;t think they can be unless we change the visible type which = isn&#39;t always what we want.... but, check this out:<br> <br> // this new type keeps track of the exact type of the pointer<br> // and manages the delegate so we can cast with some sanity...<br> struct PointerToMemberFunction(Class, Ret, T...) if(is(Class : Object)) {<b= r> =C2=A0 =C2=A0 =C2=A0 =C2=A0 private Ret delegate(T) dg;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 property Class object() { return cast(Class) d= g.ptr; }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 property void object(Class rhs) { dg.ptr =3D c= ast(void*) rhs; }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Ret opCall(T t) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 assert(dg.ptr !is n= ull, &quot;null this&quot;);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 static if(is(Ret = =3D=3D void))<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 dg(t);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 else<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 return dg(t);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> }<br> <br> // this helps us construct the above<br> template ptrToMember(alias blargh) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // I&#39;m writing out the function template lo= nghand<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // because I want to use blargh as a type and<b= r> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // dmd won&#39;t let me do it without an interm= ediate<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // dmd complains &quot;type expected, not __tra= its&quot; so we use<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 // this to work around it<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 template workaround(T) { alias workaround =3D T= ; }<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 alias ObjectType =3D workaround!(__traits(paren= t, blargh));<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto ptrToMember(ObjectType a =3D null) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 import std.traits;<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PointerToMemberFunc= tion!(<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 ObjectType,<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 ReturnType!blargh,<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 ParameterTypeTuple!blargh<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ) mem;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 mem.dg.funcptr =3D = &amp;blargh;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 mem.dg.ptr =3D cast= (void*) a;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return mem;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> }<br> <br> <br> 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&#39;s probably more valuable than the initialiser which as you&#39;l= l see below is optional anyway.<br> <br> Anyway, then you can use it like this:<br> <br> class A {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 void foo() {writeln(&quot;foo from &quot;, name= );}<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 int bar(string s) {writeln(&quot;bar &quot;,s,&= quot; from &quot;, name); return 10; }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 this(string n) { name =3D n; }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 string name;<br> }<br> <br> class B : A {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 this(string n) { super(n); }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 override void foo() { writeln(&quot;derived foo= from &quot;, name); }<br> }<br> <br> <br> void main() {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 A a =3D new A(&quot;a&quot;);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 B c =3D new B(&quot;c&quot;);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Object ob =3D a;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto ptr =3D ptrToMember!(B.foo)(c); // initial= ize the object here<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ptr();<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ptr.object =3D a;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ptr();<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto ptr2 =3D ptrToMember!(A.bar); // initializ= e to null..<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ptr2.object =3D ptr.object; // can assign later= <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ptr2(&quot;hey&quot;);<br> }<br> <br> <br> And if you play around with the types there, you&#39;ll see the compile wil= l fail if you do something uncool. Though the error messages sometimes suck= , what the hell: &quot;test2.d(58): Error: not a property ptr.object&quot;.= .. actually it is, but I was passing it an A when it required a B. That&#39= ;s a type mismatch, not a missing property.<br> <br> But whatever, at least it *did* fail to compile, so we have our type safety= .<br> <br> <br> And if I threw in an alias this on a getter property, we could assign these= beasties to regular delegates too. Not half bad.<br> <br> But regular delegate assigning to this is prohibited because we can&#39;t b= e sure their context pointer is the right kind of class. This would be true= if the compiler automatically did the ptrToMember!() too, so let&#39;s say= we change &amp;a.foo to return one of these strongly typed things instead = of a void* delegate like it does now.<br> <br> auto ptr =3D &amp;a.foo; // is ptr a void delegate() or a pointer to specif= ically a void() member of class A?<br> <br> <br> That matters because if the former (current behavior), this compiles:<br> <br> ptr =3D { writeln(&quot;hello!&quot;); };<br> <br> <br> but if the latter, that will not, it will complain that the this pointers a= re of mismatching type (or &quot;not a property&quot; lol). Of course, with= alias this style behavior, you could explicitly write out<br> <br> void delegate() ptr =3D &amp;a.foo; // ok, use looser type<br> ptr =3D {...}; // perfectly fine<br> <br> <br> <br> So I guess we wouldn&#39;t be losing much, but since we both agree a delega= te is almost always what we want, maybe the library solution of ptrToMember= is better to keep auto in a Just Works state.<br> <br> <br> <br> I&#39;m presuming you&#39;re already doing something similar for your C++ i= nterop, if not, I&#39;m pretty sure this same idea would work there too, at= least to a &#39;good enough&#39; state, even if not technically portable.<= /blockquote> <div><br></div><div style>I initially started with something like this. But= look how much code it is! I actually deleted it all and went for my non-po= rtable hack.</div><div style><br></div><div style>My implementation was dif= ferent. You&#39;ve basically wrapped up a delegate, and made something that= emulates a delegate (I&#39;m not sure why?).</div> <div style>I don&#39;t want a delegate, I want a function pointer. So my so= lution was similar, but wrapped up a function pointer and aliased a delegat= e to the correct type, then created a local delegate populating with &#39;t= his&#39; and the function at the call-site...</div> <div style>But it&#39;s all crap! It&#39;s really just abusing a delegate t= o get at the concept it embed&#39;s which doesn&#39;t have a proper express= ion.</div></div></div></div> --001a1132f8faaacb3804de9a3a74--
Jun 07 2013
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Jun 07 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--047d7b6dc474d3d5c704de9c6818
Content-Type: text/plain; charset=UTF-8

On 8 June 2013 12:29, Michel Fortin <michel.fortin michelf.ca> wrote:

 On 2013-06-07 23:57:40 +0000, Manu <turkeyman 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. --047d7b6dc474d3d5c704de9c6818 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 8 June 2013 12:29, Michel Fortin <span dir=3D"ltr">&lt;= <a href=3D"mailto:michel.fortin michelf.ca" target=3D"_blank">michel.fortin= michelf.ca</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div class= =3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On 2013-06-07 23:57:40 +00= 00, Manu &lt;<a href=3D"mailto:turkeyman gmail.com" target=3D"_blank">turke= yman gmail.com</a>&gt; said:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Precisely. The concept is already embedded inside of delegate, but delegate= <br> is framed like a piece of magic, rather than a well defined compound of<br> more primitive pieces.<br> </blockquote> <br></div> Delegates are not parametrized on the type of &quot;this&quot;, which makes= them easier to move around. I would not change delegates.<br></blockquote>= <div><br></div><div style>Actually, that&#39;s very true. Good point, and I= think this is almost the key distinction.</div> <div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex= ;border-left:1px #ccc solid;padding-left:1ex"> But function pointers with a &quot;this&quot; parameter would be useful. Yo= u 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 p= ointer and and call it. What you can&#39;t do without compiler support is g= et such a pointer in a type-safe manner.</blockquote> <div><br></div><div style>Yup, this is what I originally did. It&#39;s big = and ugly, I didn&#39;t like it, and deleted it. I think the syntax I sugges= t is simple and obvious, and naturally, typesafe.</div></div></div></div> --047d7b6dc474d3d5c704de9c6818--
Jun 07 2013
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
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
Jun 09 2013
parent reply Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
next sibling parent reply Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
parent Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
prev sibling parent reply Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-06-10 08:04:43 +0000, Jacob Carlborg <doob 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.fortin michelf.ca http://michelf.ca/
Jun 10 2013
parent reply Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
parent reply Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
next sibling parent reply Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-06-10 18:34, Manu wrote:
 On 11 June 2013 02:26, Jacob Carlborg <doob me.com <mailto:doob 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
Jun 10 2013
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
parent reply dennis luehring <dl.soluz gmx.net> writes:
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?
Jun 10 2013
parent Jacob Carlborg <doob me.com> writes:
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
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e013a0adab01bad04dec7a7cc
Content-Type: text/plain; charset=UTF-8

On 10 June 2013 16:50, Jacob Carlborg <doob 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. --089e013a0adab01bad04dec7a7cc Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 10 June 2013 16:50, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> <div class=3D"im">On 2013-06-08 01:21, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> So from my dconf talk, I detailed a nasty hack to handle member function<br=

My approach is not portable, so I&#39;d like to see an expression formalise= d<br> in D, so this sort of interaction with C++ is possible, and also it may<br> be useful in D code directly.<br> <br> I&#39;m thinking something like this... Keen to hear thoughts.<br> <br> My approach was this:<br> =C2=A0 =C2=A0void function(T _this, ...args...);<br> <br> Explicit &#39;this&#39; pointer; only works with ABI&#39;s that pass &#39;t= his&#39; as the<br> first integer argument.<br> <br> What I suggest is:<br> =C2=A0 =C2=A0void function(T this, ...args...);<br> <br> Note, I use keyword &#39;this&#39; as the first argument. This is the key t= hat<br> distinguishes the expression as a member-function pointer rather than a<br> typical function pointer. Calls through this function pointer would know<br=

calling convention.<br> <br> For &#39;extern(C++) void function(T this)&#39;, that would be to use the C= ++<br> &#39;thiscall&#39; convention.<br> <br> I think this makes good sense, because other than the choice of calling<br> convention, it really is just a &#39;function&#39; in every other way.<br> </blockquote> <br></div> Can&#39;t we just say that a delegate declared as extern(C++) is a member f= unction?</blockquote><div><br></div><div style>That seems pretty awkward to= me. Basically a hack.</div><div style>A function pointer is not a delegate= , so I don&#39;t see why that should be used to describe one.</div> <div style>Also, extern(C++) delegates are useful too in their own right</d= iv><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .= 8ex;border-left:1px #ccc solid;padding-left:1ex"> Or do you want to use mem= ber functions without connecting to C++ as well?</blockquote> <div><br></div><div style>I haven&#39;t needed to yet... but that doesn&#39= ;t mean it might not be useful.</div><div style>It would probably be used i= n D for tight binding with other systems. AngelScript binds to native code = with member function pointers... just off the top of my head.<br> </div></div></div></div> --089e013a0adab01bad04dec7a7cc--
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--047d7b471f6a9a488504dec9a2fd
Content-Type: text/plain; charset=UTF-8

On 10 June 2013 18:04, Jacob Carlborg <doob 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. --047d7b471f6a9a488504dec9a2fd Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 10 June 2013 18:04, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> <div class=3D"im">On 2013-06-10 09:23, Manu wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> That seems pretty awkward to me. Basically a hack.<br> A function pointer is not a delegate, so I don&#39;t see why that should be= <br> used to describe one.<br> </blockquote> <br></div> It depends on how you look at it. In D a delegate is a function pointer wit= h a context pointer. In C++ a pointer to a member function is basically the= same, the context pointer is just passed separately.</blockquote><div> <br></div><div style>A function pointer is a pointer. A delegate is a point= er to a function and a context pointer, ie, 2 pointers.</div><div style>A p= ointer to a method is just a pointer to a function, but it&#39;s a special = function which receives a &#39;this&#39; argument with a special calling co= nvention.</div> <div style>It&#39;s definitely useful to be able to express a &#39;thiscall= &#39; function pointer.</div><div><br></div><blockquote class=3D"gmail_quot= e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <div class=3D"im"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Also, extern(C++) delegates are useful too in their own right<br> </blockquote> <br></div> To do what? As far as I know C++ doesn&#39;t have anything corresponding to= a D delegate.</blockquote><div><br></div><div style>C++ has FastDelegate, = which I use to interact with D delegates all the time! ;)</div><div style> extern(C++) delegate is required to specify the appropriate calling convent= ion, otherwise it&#39;s just a delegate like usual.</div><div><br></div><bl= ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #= ccc solid;padding-left:1ex"> <div class=3D"im"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> I haven&#39;t needed to yet... but that doesn&#39;t mean it might not be us= eful.<br> It would probably be used in D for tight binding with other systems.<br> AngelScript binds to native code with member function pointers... just<br> off the top of my head.<br> </blockquote> <br></div> Actually I don&#39;t see why you can&#39;t use a delegate for this. The onl= y difference is that it won&#39;t be virtual.</blockquote><div><br></div><d= iv style>I&#39;m just trying to show that sometimes you don&#39;t want a de= legate, you just want a function pointer.</div> <div style>delegate&#39;s contain the function pointer I&#39;m after, so I = can access it indirectly, but it&#39;s just not so useful. It&#39;s not typ= ed (is void*), and you can&#39;t call through it.</div></div></div></div> --047d7b471f6a9a488504dec9a2fd--
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--e89a8f923fb6faf09b04decc0685
Content-Type: text/plain; charset=UTF-8

On 10 June 2013 21:35, Jacob Carlborg <doob 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. --e89a8f923fb6faf09b04decc0685 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 10 June 2013 21:35, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> <div class=3D"im">On 2013-06-10 11:45, Manu wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> A function pointer is a pointer. A delegate is a pointer to a function<br> and a context pointer, ie, 2 pointers.<br> A pointer to a method is just a pointer to a function, but it&#39;s a<br> special function which receives a &#39;this&#39; argument with a special ca= lling<br> convention.<br> It&#39;s definitely useful to be able to express a &#39;thiscall&#39; funct= ion pointer.<br> </blockquote> <br></div> It&#39;s not very useful without the context pointer, i.e. &quot;this&quot;= .<br></blockquote><div><br></div><div style>You supply &#39;this&#39; at th= e time of calling. Read my OP.</div><div><br></div><blockquote class=3D"gma= il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef= t:1ex"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im"> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Also, extern(C++) delegates are useful too in t= heir own right<br> <br> <br> =C2=A0 =C2=A0 To do what? As far as I know C++ doesn&#39;t have anything co= rresponding<br> =C2=A0 =C2=A0 to a D delegate.<br> <br> <br></div><div class=3D"im"> C++ has FastDelegate, which I use to interact with D delegates all the<br> time! ;)<br> </div></blockquote> <br> I didn&#39;t know about that. Is that something that is in the language or = standard library?</blockquote><div><br></div><div style>It&#39;s Don&#39;s = work of art. It&#39;s also how I came to find out about D in the first plac= e ;)</div> <div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex= ;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"im"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> extern(C++) delegate is required to specify the appropriate calling<br> convention, otherwise it&#39;s just a delegate like usual.<br> </blockquote> <br></div> I see.<div class=3D"im"><br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> I&#39;m just trying to show that sometimes you don&#39;t want a delegate, y= ou<br> just want a function pointer.<br> </blockquote> <br></div> Then use a function pointer.</blockquote><div><br></div><div style>There&#3= 9;s no way to specify to use the &#39;thiscall&#39; calling convention.</di= v><div style>What I propose is a syntax that would describe a member functi= on pointer, and imply the appropriate calling convention.</div> <div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex= ;border-left:1px #ccc solid;padding-left:1ex"><div class=3D"im"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> delegate&#39;s contain the function pointer I&#39;m after, so I can access = it<br> indirectly, but it&#39;s just not so useful. It&#39;s not typed (is void*),= and<br> you can&#39;t call through it.<br> </blockquote> <br></div> The function pointer of a delegate is typed, it&#39;s the context pointer t= hat is void*.<br> <br> Sorry, I&#39;m just trying to understand what you&#39;re doing, what proble= ms you have. You can compose and decompose delegates using its built-in pro= perties &quot;ptr&quot; and &quot;funcptr&quot;.<br> <br> You can do something like:<br> <br> class Foo<br> {<br> =C2=A0 =C2=A0 int i;<br> <br> =C2=A0 =C2=A0 void a () { writeln(&quot;Foo.a i=3D&quot;, i); }<br> =C2=A0 =C2=A0 void b () { writeln(&quot;Foo.b i=3D&quot;, i); }<br> }<br> <br> void main ()<br> {<br> =C2=A0 =C2=A0 auto f1 =3D new Foo;<br> =C2=A0 =C2=A0 f1.i =3D 3;<br> =C2=A0 =C2=A0 auto dg =3D &amp;f1.a;<br> =C2=A0 =C2=A0 dg();<br> <br> =C2=A0 =C2=A0 auto f2 =3D new Foo;<br> =C2=A0 =C2=A0 f2.i =3D 4;<br> =C2=A0 =C2=A0 dg.ptr =3D cast(void*) f2;<br> =C2=A0 =C2=A0 dg();<br> <br> =C2=A0 =C2=A0 dg.funcptr =3D &amp;Foo.b;<br> =C2=A0 =C2=A0 dg();<br> }<br> <br> The only thing that doesn&#39;t work with the above is if I change the cont= ext 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 &quot;funcptr&quot;.<= /blockquote> <div><br></div><div style>I wouldn&#39;t say that doesn&#39;t work, I&#39;d= say that works perfectly. A delegate is just a &#39;this&#39; and function= pair. If you change &#39;this&#39;, there&#39;s no reason the function sho= uld change.</div> <div style><br></div><div style>funcptr pretends to be typed, but the type = is just wrong. In your example, the type is &#39;void function()&#39;, it s= hould be &#39;void function(Foo this)&#39;.</div><div style>So it&#39;s act= ually a lie. You can&#39;t call it. I&#39;m not sure why it&#39;s typed at = all... just a crash waiting to happen.</div> <div style>So what I&#39;m suggesting is a syntax to express a member funct= ion pointer, and then it could be properly typed.<br></div></div></div></di= v> --e89a8f923fb6faf09b04decc0685--
Jun 10 2013
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
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
Jun 10 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
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.
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e01184b1849f54e04deccfe6d
Content-Type: text/plain; charset=UTF-8

On 10 June 2013 22:53, Jacob Carlborg <doob 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. --089e01184b1849f54e04deccfe6d Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 10 June 2013 22:53, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid= th:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-l= eft:1ex"> <div>On 2013-06-10 14:36, Manu wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> You supply &#39;this&#39; at the time of calling. Read my OP.<br> </blockquote> <br></div> Yes, exactly. It needs &quot;this&quot;. It&#39;s the same thing as a deleg= ate. It&#39;s just that with the delegate the context pointer and function = pointer is combined. A function pointer (member or free) is useless if it&#= 39;s not called.<div> <br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> It&#39;s Don&#39;s work of art. It&#39;s also how I came to find out about = D in the<br> first place ;)<br> </blockquote> <br></div> I see.<div><br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> There&#39;s no way to specify to use the &#39;thiscall&#39; calling convent= ion.<br> What I propose is a syntax that would describe a member function<br> pointer, and imply the appropriate calling convention.<br> </blockquote> <br></div> Right. I suggested a different syntax, but you want to reserve that syntax = for something that match a library implementation, that&#39;s not even in t= he standard.<br> <br> It&#39;s like saying I want int[] to match MyIntArray implemented in C++.</= blockquote><div><br></div><div style>No, I&#39;m not talking about delegate= s. I&#39;m not talking about FastDelegate (that was an aside when you comme= nted that C++ has no concept of delegate).</div> <div style>I&#39;m just talking about function pointers. Not sure where you= get this analogy from?</div><div style><br></div><blockquote class=3D"gmai= l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef= t-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <div> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> funcptr pretends to be typed, but the type is just wrong. In your<br> example, the type is &#39;void function()&#39;, it should be &#39;void func= tion(Foo<br> this)&#39;.<br> </blockquote> <br></div> &quot;void function()&quot; is part of the complete type. It becomes comple= te with the context pointer.</blockquote><div><br></div><div style>The cont= ext pointer type is not present in the type. So the function can&#39;t be u= sed/called.</div> <div style>It also doesn&#39;t know how to call it. What&#39;s the calling = convention for &#39;void function()&#39;? cdecl?</div><div style><br></div>= <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> <div> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> So it&#39;s actually a lie. You can&#39;t call it. I&#39;m not sure why it&= #39;s typed<br> at all... just a crash waiting to happen.<br> </blockquote> <br></div> You can put a free function in a delegate and call it through the delegate.= I guess you don&#39;t want that to be possible either.</blockquote><div><b= r></div><div style>A free function? Like a static function? You can assign = it, but it&#39;ll crash. Free functions are cdecl, methods are thiscall.</d= iv> <div>If you know the ABI and it receives &#39;this&#39; as the first intege= r argument, you can fabricate a compatible signature and it won&#39;t crash= , but it&#39;s not portable.</div><div style>This is my whole point about t= he type-safety. If we create an expression to describe a method pointer, th= en we can actually do it safely and portably.</div> <div style><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px = 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord= er-left-style:solid;padding-left:1ex"><div> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> So what I&#39;m suggesting is a syntax to express a member function pointer= ,<br> and then it could be properly typed.<br> </blockquote> <br></div> I don&#39;t think there&#39;s anything wrong with supporting C++ member fun= ction pointers but I don&#39;t think we need to add new syntax for it.</blo= ckquote><div><br></div><div style>I&#39;m not suggesting supporting &#39;C+= + member function pointers&#39;, they are completely bat-shit crazy.</div> <div style>I&#39;m suggesting a distinctly D way. They will be useful when = interfacing C++, and also on their own, and unlike C++, they won&#39;t be t= otally mental.</div></div></div></div> --089e01184b1849f54e04deccfe6d--
Jun 10 2013
prev sibling next sibling parent reply "David Nadlinger" <code klickverbot.at> writes:
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
Jun 10 2013
parent reply Michel Fortin <michel.fortin michelf.ca> writes:
On 2013-06-10 14:11:31 +0000, "David Nadlinger" <code klickverbot.at> said:

 On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:
 On 10 June 2013 23:46, David Nadlinger <code 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.fortin michelf.ca http://michelf.ca/
Jun 10 2013
parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Michel Fortin" <michel.fortin 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.
Jun 11 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e013c709adfd0ca04decd04e8
Content-Type: text/plain; charset=UTF-8

On 10 June 2013 22:56, Jacob Carlborg <doob 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. --089e013c709adfd0ca04decd04e8 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 10 June 2013 22:56, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> <div class=3D"im">On 2013-06-10 14:32, Michel Fortin wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Type-safety. I mean, you can do this if you want:<br> <br> =C2=A0 =C2=A0 =C2=A0auto funcptr =3D &amp;Object.toString;<br> =C2=A0 =C2=A0 =C2=A0auto object =3D new Object;<br> <br> =C2=A0 =C2=A0 =C2=A0// now call our function using object<br> =C2=A0 =C2=A0 =C2=A0string delegate() deleg;<br> =C2=A0 =C2=A0 =C2=A0deleg.ptr =3D cast(void*)object;<br> =C2=A0 =C2=A0 =C2=A0deleg.funcptr =3D funcptr;<br> <br> but this is not type-safe: the funcptr type (&quot;string function()&quot;)= is<br> actually wrong (it&#39;ll only work if called from a delegate) and the<br> object pointer the in the delegate is a void*. All Manu is asking is<br> that funcptr is of a correct type so you can call it directly by<br> supplying &quot;this&quot; as an argument, like this:<br> <br> =C2=A0 =C2=A0 =C2=A0funcptr(object);<br> <br> The problem is that this &quot;correct type&quot; for the function pointer = does<br> not exist currently. Calling a member function uses a different ABI, so<br> the type needs to know somehow its a pointer to a member function (and<br> that its first parameter is &quot;this&quot;), otherwise the generated code= at the<br> call site will be all wrong.<br> </blockquote> <br></div> Then he&#39;s asking for (more) type safe delegates and support for C++ mem= ber function pointers.</blockquote><div><br></div><div style>I&#39;m really= not asking for delegates (although they could become more typesafe given m= y 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.</div> </div></div></div> --089e013c709adfd0ca04decd04e8--
Jun 10 2013
prev sibling next sibling parent "David Nadlinger" <code klickverbot.at> writes:
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
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--047d7b339f39d219c804decd410c
Content-Type: text/plain; charset=UTF-8

On 10 June 2013 23:46, David Nadlinger <code 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. --047d7b339f39d219c804decd410c Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 10 June 2013 23:46, David Nadlinger <span dir=3D"ltr">&= lt;<a href=3D"mailto:code klickverbot.at" target=3D"_blank">code klickverbo= t.at</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmai= l_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On Friday, 7 June 2013 at = 23:22:03 UTC, Manu wrote:<br> </div><div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin:0= 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> I think this makes good sense, because other than the choice of calling<br> convention, it really is just a &#39;function&#39; in every other way.<br> </blockquote> <br></div> 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.</blockquote><div> <br></div><div style>That would also do the business. Do you think that&#39= ;s less intrusive?</div><div style>It feels a little hacky though. &#39;DTh= isCall&#39; isn&#39;t really &#39;extern&#39; so to speak.</div><div style> I like my suggestion a lot more. Little details like, what would you name t= he &#39;this&#39; argument? You&#39;ll end up with conventions like &#39;vo= id function(T _this)&#39;, and that&#39;s a bit untrue because there isn&#3= 9;t an argument named &#39;_this&#39;, it&#39;s called &#39;this&#39; insid= e the method.</div> </div></div></div> --047d7b339f39d219c804decd410c--
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--e89a8ff1bfcad2b1a204decd43ec
Content-Type: text/plain; charset=UTF-8

On 10 June 2013 23:49, David Nadlinger <code 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. --e89a8ff1bfcad2b1a204decd43ec Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 10 June 2013 23:49, David Nadlinger <span dir=3D"ltr">&= lt;<a href=3D"mailto:code klickverbot.at" target=3D"_blank">code klickverbo= t.at</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmai= l_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On Monday, 10 June 2013 at= 13:45:37 UTC, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> What&#39;s the calling convention for<br> &#39;void function()&#39;? cdecl?<br> </blockquote> <br></div> Walter&#39;s very own calling convention. It is supposed to match cdecl eve= rywhere but x86, but has the argument order reversed. On x86, it&#39;s a cu= stom one that&#39;s similar to stdcall in some ways.</blockquote><div> <br></div><div style>Indeed. I presume &#39;extern(C) void function()&#39; = is cdecl though?</div><div style>Likewise &#39;extern(C++) void function(T = this)&#39; would be &#39;thiscall&#39;, and &#39;void function(T this)&#39;= would be whatever D&#39;s method calling convention happens to be.<br> </div></div></div></div> --e89a8ff1bfcad2b1a204decd43ec--
Jun 10 2013
prev sibling next sibling parent "David Nadlinger" <code klickverbot.at> writes:
On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:
 On 10 June 2013 23:46, David Nadlinger <code 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
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e01184b1860714204decda90e
Content-Type: text/plain; charset=UTF-8

On 11 June 2013 00:28, Michel Fortin <michel.fortin michelf.ca> wrote:

 On 2013-06-10 14:11:31 +0000, "David Nadlinger" <code klickverbot.at>
 said:

  On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:
 On 10 June 2013 23:46, David Nadlinger <code 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... --089e01184b1860714204decda90e Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 11 June 2013 00:28, Michel Fortin <span dir=3D"ltr">&lt= ;<a href=3D"mailto:michel.fortin michelf.ca" target=3D"_blank">michel.forti= n michelf.ca</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div class= =3D"gmail_quote"> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im">On 2013-06-10 14:11:31 +00= 00, &quot;David Nadlinger&quot; &lt;<a href=3D"mailto:code klickverbot.at" = target=3D"_blank">code klickverbot.at</a>&gt; said:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> On Monday, 10 June 2013 at 14:04:29 UTC, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> On 10 June 2013 23:46, David Nadlinger &lt;<a href=3D"mailto:code klickverb= ot.at" target=3D"_blank">code klickverbot.at</a>&gt;<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Another less intrusive option would be to just add extern(CppThisCall) and<= br> extern(DThisCall) or something along the lines, which would be specified to= <br> pass the first parameter as if it was a this pointer.<br> </blockquote> <br> That would also do the business. Do you think that&#39;s less intrusive?<br=

<br> Less intrusive in the way that it is a minimal addition to the language its= elf (we already have several calling conventions), whereas your suggestion = would require adding a special case to the grammar.<br> <br> That&#39;s not to say I don&#39;t like your proposal, though. I just wanted= to put the option on the table to be sure we are getting somewhere with th= is, even if some people might be opposed to the grammar change. This issue = has been bugging me for quite some time as well.<br> </blockquote> <br></div> It&#39;s inelegant, but it could work.<br> <br> I just find it sad that we have to use a different calling convention for m= ember functions. I mean, it&#39;d be much more elegant be if a member funct= ion could simply be called from a &quot;void function(Object)&quot; by supp= lying &quot;this&quot; as the first argument? Wouldn&#39;t it be better to = adapt the ABI to fit the language rather than adapt the language to fit the= ABI?</blockquote> <div><br></div><div style>The ABI is the better part of half a century old.= ..</div></div></div></div> --089e01184b1860714204decda90e--
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e013a0adab6722404dece8b7c
Content-Type: text/plain; charset=UTF-8

On 11 June 2013 00:43, Jacob Carlborg <doob 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. --089e013a0adab6722404dece8b7c Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 11 June 2013 00:43, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> <div class=3D"im">On 2013-06-10 15:47, Manu wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> I&#39;m really not asking for delegates (although they could become more<br=

C++ style as you say, my suggestion is much simpler than that, and would<br=

</blockquote> <br></div> I give up, I don&#39;t understand what you want.</blockquote><div><br></div=
<div style>...a member function pointer syntax. It&#39;s not that complex.=

s) funcptr;</div> <div style>This is a function pointer (not a delegate), but using keyword &= #39;this&#39; gives the critical detail to the compiler that it&#39;s a mem= ber function pointer, and to use the appropriate calling convention when ma= king calls through this pointer.</div> <div style>UFCS makes it awesome.</div></div></div></div> --089e013a0adab6722404dece8b7c--
Jun 10 2013
prev sibling next sibling parent "David Nadlinger" <code klickverbot.at> writes:
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
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--047d7b67610447aa5204decf5b99
Content-Type: text/plain; charset=UTF-8

On 11 June 2013 02:26, Jacob Carlborg <doob 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. --047d7b67610447aa5204decf5b99 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 11 June 2013 02:26, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> <div class=3D"im">On 2013-06-10 17:40, David Nadlinger wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Let me try to summarize it in code:<br> <br> ---<br> class A { void foo(); }<br> auto memberFun =3D (&amp;A.foo).funcptr;<br> <br> auto a =3D new A;<br> memberFun(a);<br> ---<br> </blockquote> <br></div> Why is this better than a delegate?</blockquote><div><br></div><div style>I= t&#39;s not &#39;better&#39;, it&#39;s different.</div></div></div></div> --047d7b67610447aa5204decf5b99--
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e013a0adaae6c3504decf7d7a
Content-Type: text/plain; charset=UTF-8

On 11 June 2013 02:28, Jacob Carlborg <doob 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)? :) --089e013a0adaae6c3504decf7d7a Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 11 June 2013 02:28, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> <div class=3D"im">On 2013-06-10 17:36, Manu wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> My suggestion is: void function(T this) funcptr;<br> This is a function pointer (not a delegate), but using keyword &#39;this&#3= 9;<br> gives the critical detail to the compiler that it&#39;s a member function<b= r> pointer, and to use the appropriate calling convention when making calls<br=

UFCS makes it awesome.<br> </blockquote> <br></div> What I don&#39;t understand is what this give you that a delegate doesn&#39= ;t. You need the &quot;this&quot; pointer to call the function pointer anyw= ay. With a delegate it&#39;s bundled.</blockquote><div><br></div><div style=

it&#39;s strongly typed.</div><div style>If you don&#39;t want a bundle, w= hy be forced to use a bundled type?</div><div style><br></div><div style> Consider this, why would you ever want an int* when you can have an int[]?<= /div><div style>We could remove the syntax for int*, and make it only acces= sible via int[].ptr... and make: is(typeof(int[].ptr) =3D=3D size_t)? :)</d= iv> </div></div></div> --089e013a0adaae6c3504decf7d7a--
Jun 10 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e0115ed163bf9ec04decf96bc
Content-Type: text/plain; charset=UTF-8

On 11 June 2013 02:43, Jacob Carlborg <doob me.com> wrote:

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

 On 11 June 2013 02:26, Jacob Carlborg <doob me.com <mailto:doob 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. --089e0115ed163bf9ec04decf96bc Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">On 11 June 2013 02:43, Jacob Carlborg <span dir=3D"ltr">&l= t;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</spa= n> wrote:<br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockqu= ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s= olid;padding-left:1ex"> On 2013-06-10 18:34, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> On 11 June 2013 02:26, Jacob Carlborg &lt;<a href=3D"mailto:doob me.com" ta= rget=3D"_blank">doob me.com</a> &lt;mailto:<a href=3D"mailto:doob me.com" t= arget=3D"_blank">doob me.com</a>&gt;&gt;<div><div class=3D"h5"><br> wrote:<br> <br> =C2=A0 =C2=A0 On 2013-06-10 17:40, David Nadlinger wrote:<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Let me try to summarize it in code:<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ---<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 class A { void foo(); }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto memberFun =3D (&amp;A.foo).funcptr;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto a =3D new A;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 memberFun(a);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ---<br> <br> <br> =C2=A0 =C2=A0 Why is this better than a delegate?<br> <br> <br></div></div><div class=3D"im"> It&#39;s not &#39;better&#39;, it&#39;s different.<br> </div></blockquote> <br><div class=3D"im"> class A { void foo(); }<br> auto memberFun =3D (&amp;A.foo).funcptr;<br> <br> auto a =3D new A;<br></div> void delegate () dg;<br> dg.funcptr =3D memberFun;<br> dg.ptr =3D cast(void*) a;<br> dg();<br> <br> The details can be hidden in a function call. Sure, a delegate could be typ= e safe but still don&#39;t see the point.</blockquote><div><br></div><div s= tyle>You can see how much work that is right? And it&#39;s still not typesa= fe.</div> <div style>It&#39;s totally a hack.</div></div></div></div> --089e0115ed163bf9ec04decf96bc--
Jun 10 2013
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 10 Jun 2013 12:45:12 -0400, Jacob Carlborg <doob 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
Jun 10 2013
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Mon, 10 Jun 2013 14:53:33 +0200, Jacob Carlborg <doob 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
Jun 10 2013
prev sibling next sibling parent "David Nadlinger" <code klickverbot.at> writes:
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
Jun 10 2013
prev sibling next sibling parent d coder via Digitalmars-d <digitalmars-d puremagic.com> writes:
--20cf300fb2d1b79d2d04fa5ebfd6
Content-Type: text/plain; charset=UTF-8

On Mon, Jun 10, 2013 at 10:13 PM, Jacob Carlborg <doob me.com> wrote:

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

 On 11 June 2013 02:26, Jacob Carlborg <doob me.com <mailto:doob 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 --20cf300fb2d1b79d2d04fa5ebfd6 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail= _quote">On Mon, Jun 10, 2013 at 10:13 PM, Jacob Carlborg <span dir=3D"ltr">= &lt;<a href=3D"mailto:doob me.com" target=3D"_blank">doob me.com</a>&gt;</s= pan> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex">On 2013-06-10 18:34, Manu wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> On 11 June 2013 02:26, Jacob Carlborg &lt;<a href=3D"mailto:doob me.com" ta= rget=3D"_blank">doob me.com</a> &lt;mailto:<a href=3D"mailto:doob me.com" t= arget=3D"_blank">doob me.com</a>&gt;&gt;<div><div><br> wrote:<br> <br> =C2=A0 =C2=A0 On 2013-06-10 17:40, David Nadlinger wrote:<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 Let me try to summarize it in code:<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ---<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 class A { void foo(); }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto memberFun =3D (&amp;A.foo).funcptr;<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto a =3D new A;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 memberFun(a);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ---<br> <br> <br> =C2=A0 =C2=A0 Why is this better than a delegate?<br> <br> <br></div></div><div> It&#39;s not &#39;better&#39;, it&#39;s different.<br> </div></blockquote> <br><div> class A { void foo(); }<br> auto memberFun =3D (&amp;A.foo).funcptr;<br> <br> auto a =3D new A;<br></div> void delegate () dg;<br> dg.funcptr =3D memberFun;<br> dg.ptr =3D cast(void*) a;<br> dg();<br> <br> The details can be hidden in a function call. Sure, a delegate could be typ= e safe but still don&#39;t see the point.<span><font color=3D"#888888"><br> <br> -- <br> /Jacob Carlborg<br></font></span></blockquote><div><br></div><div>Greetings= </div><div><br></div><div>Apologies for bringing up this year old thread.</= div><div><br></div><div>With=C2=A0<a href=3D"https://github.com/D-Programmi= ng-Language/dmd/pull/3181" target=3D"_blank">https://github.com/D-Programmi= ng-Language/dmd/pull/3181</a> getting merged, it is no longer feasible to d= irectly assign dg.funcptr (which is not an lvalue now). The problem is that= the code suggested by David also does not work.</div> <div><br></div><div>Is there an alternative?</div><div><br></div><div>Regar= ds</div><div>- Puneet</div></div><br></div></div> --20cf300fb2d1b79d2d04fa5ebfd6--
May 27 2014
prev sibling parent d coder via Digitalmars-d <digitalmars-d puremagic.com> writes:
--20cf30434c644c526c04fa60bca0
Content-Type: text/plain; charset=UTF-8

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

--20cf30434c644c526c04fa60bca0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><a href=3D"https://github.com/D-Programming-Language/=
dmd/pull/3181">https://github.com/D-Programming-Language/dmd/pull/3181</a><=
br></div><div><br></div><div>Daniel asked me to use this. And it works.</di=
v>

<div><br></div><div>Use something like:</div><div><br></div><div>union U</d=
iv><div>{</div><div>=C2=A0 void delegate(int) dg;</div><div>=C2=A0 struct</=
div><div>=C2=A0 {</div><div>=C2=A0 =C2=A0 void* ptr;</div><div>=C2=A0 =C2=
=A0 void function(int) funcptr;</div>

<div>=C2=A0 }</div><div>}</div><div>U u;</div><div>u.dg =3D dg;</div><div>u=
.funcptr =3D ...;</div><div>u.ptr =3D ...;</div><div><br></div><div class=
=3D"gmail_extra"><div class=3D"gmail_quote">Regards</div><div class=3D"gmai=
l_quote">- Puneet</div>

</div></div>

--20cf30434c644c526c04fa60bca0--
May 27 2014