digitalmars.D - Pointers to non-static member functions!
- Daniel Murphy (19/19) Jun 08 2011 Currently, this compiles:
- Michel Fortin (17/41) Jun 08 2011 I think it should work like my D/Objective-C language extension does it
- Daniel Murphy (6/12) Jun 08 2011 This would be nice to have, but the compiler would need to use a differe...
- Michel Fortin (11/14) Jun 08 2011 True. What I mean is that a function type should know whether it needs
- Daniel Murphy (7/13) Jun 08 2011 Ah I see. This could probably be implemented quite easily, but I doubt ...
- Trass3r (4/16) Jun 08 2011 ??
- Daniel Murphy (15/17) Jun 08 2011 I don't think getting a delegate makes any sense without an instance.
- Steven Schveighoffer (22/41) Jun 08 2011 The reason is to allow composition of delegates (not that I think this i...
- Daniel Murphy (22/42) Jun 08 2011 I can see this being useful, but I think it should be done by having
- Steven Schveighoffer (29/80) Jun 08 2011 Yes, but removing type safety does not prevent that from happening, plus...
- Daniel Murphy (18/45) Jun 08 2011 Fun fact: due to bug3797 if you change basically anything except the ret...
- Steven Schveighoffer (25/39) Jun 08 2011 The issue becomes, what is the type of dg.funcptr? And is it useable? ...
- Daniel Gibson (24/32) Jun 08 2011 That'd be nice. I think having a possibility to get a pointer to a
- Michel Fortin (13/94) Jun 08 2011 I was "hacking delegates" a lot in the D/Objective-C bridge (before I
- Steven Schveighoffer (26/108) Jun 08 2011 The issue with hacking delegates I have is that almost certainly you kno...
- Michel Fortin (76/132) Jun 08 2011 This is not at all a feature of Objective-C. This was a workaround.
- Michel Fortin (10/22) Jun 08 2011 Now that I think about it, perhaps UFCS would make all this unnecessary.
- Daniel Murphy (7/12) Jun 08 2011 Somebody recently suggested making a parameter to enable a function to b...
- Steven Schveighoffer (22/70) Jun 08 2011 In this case, the alias points at A.func or something like that, no? So...
- Michel Fortin (55/103) Jun 08 2011 Exactly.
- Jason House (2/15) Jun 08 2011 Shouldn't it be void function(A)? As long as the ABI supports it, that w...
- Daniel Murphy (20/23) Jun 08 2011 Unfortunately the ABI doesn't support it. 'this' must always be the las...
- David Nadlinger (12/31) Jun 08 2011 Oh wow, my previous comment was total nonsense, I confused .func with
- Daniel Murphy (7/18) Jun 08 2011 I think the botched type comes from the compiler's implementation - func...
- Daniel Murphy (5/5) Jun 08 2011 Turned out it was even easier to do than I expected:
- Daniel Murphy (3/8) Jun 08 2011 swap lvalue and rvalue!
Currently, this compiles: class A { void func() {} } void main() { auto p = &A.func; } In this case, typeof(p) is void function(). Calling one of these pointers, of course, can easily give you a segfault as it completely ignores the this pointer. I didn't even realize you could do this until I saw http://d.puremagic.com/issues/show_bug.cgi?id=5986 I understand that it could be useful to have a way to get the address of a non-static member function, but I doubt returning a malformed function pointer is really useful. Does anybody think changing &ClassType.nonStaticMember to return void* would be a bad idea?
Jun 08 2011
On 2011-06-08 04:00:53 -0400, "Daniel Murphy" <yebblies nospamgmail.com> said:Currently, this compiles: class A { void func() {} } void main() { auto p = &A.func; } In this case, typeof(p) is void function(). Calling one of these pointers, of course, can easily give you a segfault as it completely ignores the this pointer. I didn't even realize you could do this until I saw http://d.puremagic.com/issues/show_bug.cgi?id=5986 I understand that it could be useful to have a way to get the address of a non-static member function, but I doubt returning a malformed function pointer is really useful. Does anybody think changing &ClassType.nonStaticMember to return void* would be a bad idea?I think it should work like my D/Objective-C language extension does it for selectors. <http://michelf.com/projects/d-objc/syntax/#selector-literals> &A.func should return a *member* function pointer which wants a 'this' parameter, and when you call it you should be required to add the 'this' argument at the beginning of the argument list, like this: void main() { auto p = &A.func; p(new A); } That'll probably require a syntax to specify a function type that wants a this pointer. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 08 2011
"Michel Fortin" <michel.fortin michelf.com> wrote in message news:isnj6i$2afd$1 digitalmars.com...I think it should work like my D/Objective-C language extension does it for selectors. <http://michelf.com/projects/d-objc/syntax/#selector-literals> &A.func should return a *member* function pointer which wants a 'this' parameter, and when you call it you should be required to add the 'this' argument at the beginning of the argument list, like this:This would be nice to have, but the compiler would need to use a different calling convention or generate multiple function beginnings, as the this parameter must be passed last. This case is related to http://d.puremagic.com/issues/show_bug.cgi?id=2672
Jun 08 2011
On 2011-06-08 09:24:43 -0400, "Daniel Murphy" <yebblies nospamgmail.com> said:This would be nice to have, but the compiler would need to use a different calling convention or generate multiple function beginnings, as the this parameter must be passed last.True. What I mean is that a function type should know whether it needs a 'this' pointer or not, and implicit conversion between a function type that needs a this pointer and one that doesn't need one should be forbidden. And calling such a function directly would either not work, or would require a 'this' to be provided as the first argument (which is then put at the right place according to the ABI rules). -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 08 2011
"Michel Fortin" <michel.fortin michelf.com> wrote in message news:isoa8d$nif$1 digitalmars.com...True. What I mean is that a function type should know whether it needs a 'this' pointer or not, and implicit conversion between a function type that needs a this pointer and one that doesn't need one should be forbidden. And calling such a function directly would either not work, or would require a 'this' to be provided as the first argument (which is then put at the right place according to the ABI rules).Ah I see. This could probably be implemented quite easily, but I doubt it's worth the effort. I think most cases can be done by casting and using a delegate. I don't think pointers to members brought a lot to C++ (apart from complexity and syntax) and they seem mostly unnecessary with D's delegates.
Jun 08 2011
Am 08.06.2011, 10:00 Uhr, schrieb Daniel Murphy <yebblies nospamgmail.com>:Currently, this compiles: class A { void func() {} } void main() { auto p = &A.func; } In this case, typeof(p) is void function()....Does anybody think changing &ClassType.nonStaticMember to return void* would be a bad idea??? Shouldn't this just return a delegate?
Jun 08 2011
"Trass3r" <un known.com> wrote in message news:op.vwq80v023ncmek enigma...?? Shouldn't this just return a delegate?I don't think getting a delegate makes any sense without an instance. I'm talking about this case: class A { void func(); } void main() { // returns a nonsense function pointer auto f = &A.func; // returns a working delegate auto a = new A(); auto g = &a.func; }
Jun 08 2011
On Wed, 08 Jun 2011 09:27:21 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote:"Trass3r" <un known.com> wrote in message news:op.vwq80v023ncmek enigma...The reason is to allow composition of delegates (not that I think this is a worthy reason): class A { void func(); void func2(); } void main() { auto f = &A.func2; auto a = new A(); auto g = &a.func; // delegate g.funcptr = f; g(); // calls a.func2() } I'd argue that a much more useful return type would be a delegate with the this pointer set to null, but then I don't know what funcptr would return. I almost think you need a separate type for it, which seems like a lot of effort for something that's hardly used. -Steve?? Shouldn't this just return a delegate?I don't think getting a delegate makes any sense without an instance. I'm talking about this case: class A { void func(); } void main() { // returns a nonsense function pointer auto f = &A.func; // returns a working delegate auto a = new A(); auto g = &a.func; }
Jun 08 2011
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message news:op.vwrgycgjeav7ka localhost.localdomain...The reason is to allow composition of delegates (not that I think this is a worthy reason): class A { void func(); void func2(); } void main() { auto f = &A.func2; auto a = new A(); auto g = &a.func; // delegate g.funcptr = f; g(); // calls a.func2() } I'd argue that a much more useful return type would be a delegate with the this pointer set to null, but then I don't know what funcptr would return. I almost think you need a separate type for it, which seems like a lot of effort for something that's hardly used. -SteveI can see this being useful, but I think it should be done by having delegate.funcptr be a void* and &ClassType.nonstaticmemberfunction return void*. The type safety provided by the current way it works is an illusion, as the following compiles: class A { void func() { do something using member variables or the vtable etc } } class B { void func() {} } void main() { auto b = new B(); auto dg = &b.func; dg.funcptr = &A.func; dg(); // Probably a segfault }
Jun 08 2011
On Wed, 08 Jun 2011 10:40:48 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote:"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message news:op.vwrgycgjeav7ka localhost.localdomain...Yes, but removing type safety does not prevent that from happening, plus it allows something like this: class A { void func(); int func2(); } void main() { auto a = new A; auto dg = &a.func2(); dg.funcptr = &A.func; // works if dg.funcptr and &A.func are void*, but doesn't work today int x = dg(); // runs and returns garbage } I almost would prefer that hacking delegates would be illegal. Yes, you can get the function pointer and data pointer out of a delegate, but cannot set them. I can't think of any good use cases for them. I'm mixed on whether you should be able to get a member "function pointer". It would be nice to simply make it a normal function pointer that you can call with the appropriate type. BTW, if the calling convention is different, we may be able to allow it via creating a "this" function pointer: assert(is(typeof(&A.func2) == int function(A this))); Since this is a keyword, it can be interpreted as a different calling convention. -SteveThe reason is to allow composition of delegates (not that I think this is a worthy reason): class A { void func(); void func2(); } void main() { auto f = &A.func2; auto a = new A(); auto g = &a.func; // delegate g.funcptr = f; g(); // calls a.func2() } I'd argue that a much more useful return type would be a delegate with the this pointer set to null, but then I don't know what funcptr would return. I almost think you need a separate type for it, which seems like a lot of effort for something that's hardly used. -SteveI can see this being useful, but I think it should be done by having delegate.funcptr be a void* and &ClassType.nonstaticmemberfunction return void*. The type safety provided by the current way it works is an illusion, as the following compiles: class A { void func() { do something using member variables or the vtable etc } } class B { void func() {} } void main() { auto b = new B(); auto dg = &b.func; dg.funcptr = &A.func; dg(); // Probably a segfault }
Jun 08 2011
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message news:op.vwridsuteav7ka localhost.localdomain...Yes, but removing type safety does not prevent that from happening, plus it allows something like this: class A { void func(); int func2(); } void main() { auto a = new A; auto dg = &a.func2(); dg.funcptr = &A.func; // works if dg.funcptr and &A.func are void*, but doesn't work today int x = dg(); // runs and returns garbage }Fun fact: due to bug3797 if you change basically anything except the return type, it _will_ work today!I almost would prefer that hacking delegates would be illegal. Yes, you can get the function pointer and data pointer out of a delegate, but cannot set them. I can't think of any good use cases for them.I think you're right on this. I'll have a look and see how difficult making the delegate properties readonly is. I have actually needed to manually construct a delegate when doing low level calling convention stuff, but you can always do this using unions or casts if you have to.I'm mixed on whether you should be able to get a member "function pointer". It would be nice to simply make it a normal function pointer that you can call with the appropriate type. BTW, if the calling convention is different, we may be able to allow it via creating a "this" function pointer: assert(is(typeof(&A.func2) == int function(A this))); Since this is a keyword, it can be interpreted as a different calling convention. -SteveI can see the theoretical appeal of having member function pointers or being able to call member functions as if they were globals, but I don't think the practical uses really justify introducing new syntax or types or changing the ABI. I also don't think any option which does any of those things has a chance of getting incorporated into dmd. If I can get some kind of consensus I'll try and patch dmd. I think the following covers most of your points, given that you can still do the unsafe thing by casting: Make delegate.funcptr read only and return void* Make &ClassType.nonstaticmemberfunction return void*
Jun 08 2011
On Wed, 08 Jun 2011 11:19:12 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote:I can see the theoretical appeal of having member function pointers or being able to call member functions as if they were globals, but I don't think the practical uses really justify introducing new syntax or types or changing the ABI. I also don't think any option which does any of those things has a chance of getting incorporated into dmd.The issue becomes, what is the type of dg.funcptr? And is it useable? I don't know if returning void * is the right answer, one of the main things I think would be required is: if(dg.funcptr is &A.func) {} Which is really all you can do with a void *, so it does satisfy most requirements. But I don't like that it can be passed into functions that for example, take a void *. It just seems odd that you don't get any type information. What I'd prefer is to have dg.funcptr return a new type like: int function(void this) which means, it cannot be called, because you don't know what type this is. However, accessing the function pointer from the originating type would return: int function(A this); I don't think we need to change the ABI. Calling the function with the given instance type would be the same as constructing the delegate and calling that delegate. As far as "new" syntax, you may have a point. I'll point out however that this is a seldom used "feature", and changing syntax would likely not affect very much code.If I can get some kind of consensus I'll try and patch dmd. I think the following covers most of your points, given that you can still do the unsafe thing by casting: Make delegate.funcptr read only and return void* Make &ClassType.nonstaticmemberfunction return void*Again, I think the read-only for funcptr is good, but void * seems too lax. But it's an acceptable update, better than nothing. -Steve
Jun 08 2011
Am 08.06.2011 16:54, schrieb Steven Schveighoffer:I almost would prefer that hacking delegates would be illegal. Yes, you can get the function pointer and data pointer out of a delegate, but cannot set them. I can't think of any good use cases for them. I'm mixed on whether you should be able to get a member "function pointer". It would be nice to simply make it a normal function pointer that you can call with the appropriate type.That'd be nice. I think having a possibility to get a pointer to a member function that you can use with any instance of the class the method belongs to would be nice. Currently this should be possible by using a delegate and changing its .ptr to the object you want to call the method on (this won't work anymore if the delegates internal pointers are read-only as suggested above). This could be used for something like runtime-reflection (like Java's Method class - which is horribly slow btw, compared to a direct call to a method. For whatever reason.) So you could use object.classinfo.getMembers(), look for the method you want to use (with the name given at runtime!) and then use a function pointer to that Method to efficiently call it on any object of the same type. (So much for the theory, I don't see a way to find out the methods signature to match it to the signature you want, especially for overloaded methods - but maybe I just missed it.) BTW: MemberInfo (and MemberInfo_field and MemberInfo_function) should be documented in the object documentation. And what does MemberInfo_function's typeInfo() return? And is there a way to get a methods signature from MemberInfo_function? (I hope this made sense and I didn't ignore a nicer way to do this - at runtime - that is already implemented) Cheers, - Daniel
Jun 08 2011
On 2011-06-08 10:54:54 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:On Wed, 08 Jun 2011 10:40:48 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote:I was "hacking delegates" a lot in the D/Objective-C bridge (before I decided to bring things directly in the compiler). To make it short, I needed to do that to call the appropriate D function from Objective-C stub method implementation."Steven Schveighoffer" <schveiguy yahoo.com> wrote in message news:op.vwrgycgjeav7ka localhost.localdomain...Yes, but removing type safety does not prevent that from happening, plus it allows something like this: class A { void func(); int func2(); } void main() { auto a = new A; auto dg = &a.func2(); dg.funcptr = &A.func; // works if dg.funcptr and &A.func are void*, but doesn't work today int x = dg(); // runs and returns garbage } I almost would prefer that hacking delegates would be illegal. Yes, you can get the function pointer and data pointer out of a delegate, but cannot set them. I can't think of any good use cases for them.The reason is to allow composition of delegates (not that I think this is a worthy reason): class A { void func(); void func2(); } void main() { auto f = &A.func2; auto a = new A(); auto g = &a.func; // delegate g.funcptr = f; g(); // calls a.func2() } I'd argue that a much more useful return type would be a delegate with the this pointer set to null, but then I don't know what funcptr would return. I almost think you need a separate type for it, which seems like a lot of effort for something that's hardly used. -SteveI can see this being useful, but I think it should be done by having delegate.funcptr be a void* and &ClassType.nonstaticmemberfunction return void*. The type safety provided by the current way it works is an illusion, as the following compiles: class A { void func() { do something using member variables or the vtable etc } } class B { void func() {} } void main() { auto b = new B(); auto dg = &b.func; dg.funcptr = &A.func; dg(); // Probably a segfault }BTW, if the calling convention is different, we may be able to allow it via creating a "this" function pointer: assert(is(typeof(&A.func2) == int function(A this))); Since this is a keyword, it can be interpreted as a different calling convention.I was thinking about that too. Note that it forces int function(A this) to be implicitly castable to int function(void* this) when assigning to a delegate. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 08 2011
On Wed, 08 Jun 2011 13:07:50 -0400, Michel Fortin <michel.fortin michelf.com> wrote:On 2011-06-08 10:54:54 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:The issue with hacking delegates I have is that almost certainly you know what the type of the function pointer is, which means you almost certainly have access to the member function for that type directly, it seems a very strange use case to be able to dynamically address the member functions of a class without knowing the type. When I first wrote the above reason, I tried to think of a compelling real example, I couldn't. Now, you are implementing a bridge to another language that supports a feature, which means you have to implement it. But how often is that feature used in that other language?On Wed, 08 Jun 2011 10:40:48 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote:I was "hacking delegates" a lot in the D/Objective-C bridge (before I decided to bring things directly in the compiler). To make it short, I needed to do that to call the appropriate D function from Objective-C stub method implementation."Steven Schveighoffer" <schveiguy yahoo.com> wrote in message news:op.vwrgycgjeav7ka localhost.localdomain...Yes, but removing type safety does not prevent that from happening, plus it allows something like this: class A { void func(); int func2(); } void main() { auto a = new A; auto dg = &a.func2(); dg.funcptr = &A.func; // works if dg.funcptr and &A.func are void*, but doesn't work today int x = dg(); // runs and returns garbage } I almost would prefer that hacking delegates would be illegal. Yes, you can get the function pointer and data pointer out of a delegate, but cannot set them. I can't think of any good use cases for them.The reason is to allow composition of delegates (not that I think this is a worthy reason): class A { void func(); void func2(); } void main() { auto f = &A.func2; auto a = new A(); auto g = &a.func; // delegate g.funcptr = f; g(); // calls a.func2() } I'd argue that a much more useful return type would be a delegate with the this pointer set to null, but then I don't know what funcptr would return. I almost think you need a separate type for it, which seems like a lot of effort for something that's hardly used. -SteveI can see this being useful, but I think it should be done by having delegate.funcptr be a void* and &ClassType.nonstaticmemberfunction return void*. The type safety provided by the current way it works is an illusion, as the following compiles: class A { void func() { do something using member variables or the vtable etc } } class B { void func() {} } void main() { auto b = new B(); auto dg = &b.func; dg.funcptr = &A.func; dg(); // Probably a segfault }ATM, delegates and functions do not implicitly cast whatsoever. In fact, I would not want the above cast to succeed, what should be implicitly cast is a contravariant function. For example int function(Object this) should implicitly cast to int function(A this). Now, a delegate does not record its 'this' type, so getting the function pointer for the delegate should yield an uncallable function pointer. I proposed in another part of this thread the syntax: int function(void this); This at least gives you type information, but doesn't allow you to unsafely call it. If you wish to explicitly cast it to a viable function, you can. All this is dependent on the idea that a delegate cannot be constructed unless you have the original method (or a type-safe 'delegate-function' such as int function(A this)). I really think that makes sense. -SteveBTW, if the calling convention is different, we may be able to allow it via creating a "this" function pointer: assert(is(typeof(&A.func2) == int function(A this))); Since this is a keyword, it can be interpreted as a different calling convention.I was thinking about that too. Note that it forces int function(A this) to be implicitly castable to int function(void* this) when assigning to a delegate.
Jun 08 2011
On 2011-06-08 13:29:27 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:On Wed, 08 Jun 2011 13:07:50 -0400, Michel Fortin <michel.fortin michelf.com> wrote:This is not at all a feature of Objective-C. This was a workaround. Tell me, if inside a template you have an alias to a member function, how can I call that member function? This won't work: void callMe(alias memberFunc)(Object o) { o.memberFunc(); // won't work, Object has no member called "memberFunc". } What you can do is this: template Binding(alias memberFunc)(Object o) { void delegate() delegateToMember; delegateToMember.ptr = o; delegateToMember.funcptr = &memberFunc; delegateToMember(); } Although even there it won't work very well if your member is a virtual function. I needed to use an ever stranger workaround for that. Here's the actual code from the Objective-C bridge (it's a template which be mixed in the class): /** * Template which can be mixed in a class to bind selector sel to instance * method. * * This will create a receiver function which will forward the call to * method, decapsulating arguments and encapsulating the return value as * appropriate. */ template ObjcBindMethod(alias method, R, char[] sel, A...) { /** * Resolve virtual function and return a delegate to it. This must be * done from a non-static member function otherwise we can't get the * address of the overriding function if there is one. */ private R delegate(A) resolveVirtualCall() { return &method; } /** Call forwarder for a virtual method of this class. */ private static R forwardVirtualCall(objc.runtime.id self, objc.runtime.SEL _cmd, A args) { R delegate(A) delegate() resolve; resolve.ptr = objc.msg.send!(void*)(self, objc.method.selector!("d_object")); resolve.funcptr = &resolveVirtualCall; return resolve()(args); } mixin objc.bridge.ObjcMethodInfo!(forwardVirtualCall, R, sel, A); } Here, the entry point from Objective-C is the forwardVirtualCall function, which does two things: it finds the object pointer, and then it resolves the virtual call, which can only be done in a non-static member function (resolveVirtualCall) because in the absence of an implicit this pointer it won't work. Actually that's not really the entry point from Objective-C, there's a first entry point that performs argument conversion as necessary which then calls this one to call the right virtual function, but that's irrelevant to our case. What would have really simplified things in all this is a C++-style pointer to member function type. But that's not part of D.On 2011-06-08 10:54:54 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:The issue with hacking delegates I have is that almost certainly you know what the type of the function pointer is, which means you almost certainly have access to the member function for that type directly, it seems a very strange use case to be able to dynamically address the member functions of a class without knowing the type. When I first wrote the above reason, I tried to think of a compelling real example, I couldn't. Now, you are implementing a bridge to another language that supports a feature, which means you have to implement it. But how often is that feature used in that other language?On Wed, 08 Jun 2011 10:40:48 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote: I almost would prefer that hacking delegates would be illegal. Yes, you can get the function pointer and data pointer out of a delegate, but cannot set them. I can't think of any good use cases for them.I was "hacking delegates" a lot in the D/Objective-C bridge (before I decided to bring things directly in the compiler). To make it short, I needed to do that to call the appropriate D function from Objective-C stub method implementation.You're right.ATM, delegates and functions do not implicitly cast whatsoever. In fact, I would not want the above cast to succeed, what should be implicitly cast is a contravariant function. For example int function(Object this) should implicitly cast to int function(A this).BTW, if the calling convention is different, we may be able to allow it via creating a "this" function pointer: assert(is(typeof(&A.func2) == int function(A this))); Since this is a keyword, it can be interpreted as a different calling convention.I was thinking about that too. Note that it forces int function(A this) to be implicitly castable to int function(void* this) when assigning to a delegate.Now, a delegate does not record its 'this' type, so getting the function pointer for the delegate should yield an uncallable function pointer. I proposed in another part of this thread the syntax: int function(void this); This at least gives you type information, but doesn't allow you to unsafely call it. If you wish to explicitly cast it to a viable function, you can.Makes sense.All this is dependent on the idea that a delegate cannot be constructed unless you have the original method (or a type-safe 'delegate-function' such as int function(A this)). I really think that makes sense.I won't disagree with anything you say, because I do agree. I know my use case is a fringe one, and I don't need it anymore so I don't care much. And it'd only need one small thing for it to work without all that cumbersome hack: o.memberFunc() // where methodFunc is an alias to a member of o which probably shouldn't be that difficult to implement in the compiler, what's needed is new syntax to distinguish it from a normal member call. Perhaps this? o.(memberFunc)() -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 08 2011
On 2011-06-08 14:13:46 -0400, Michel Fortin <michel.fortin michelf.com> said:I won't disagree with anything you say, because I do agree. I know my use case is a fringe one, and I don't need it anymore so I don't care much. And it'd only need one small thing for it to work without all that cumbersome hack: o.memberFunc() // where methodFunc is an alias to a member of o which probably shouldn't be that difficult to implement in the compiler, what's needed is new syntax to distinguish it from a normal member call. Perhaps this? o.(memberFunc)()Now that I think about it, perhaps UFCS would make all this unnecessary. void callMe(alias memberFunc)(Object o) { o.memberFunc(); // error, no member called "memberFunc" in o memberFunc(o); // works? } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jun 08 2011
"Michel Fortin" <michel.fortin michelf.com> wrote in message news:isog18$13vc$1 digitalmars.com...Now that I think about it, perhaps UFCS would make all this unnecessary. void callMe(alias memberFunc)(Object o) { o.memberFunc(); // error, no member called "memberFunc" in o memberFunc(o); // works? }Somebody recently suggested making a parameter to enable a function to be called with ufcs. void func(int a, int b, Object this) {} A pointer to a function like this could be the same type as a member function pointer.
Jun 08 2011
On Wed, 08 Jun 2011 14:13:46 -0400, Michel Fortin <michel.fortin michelf.com> wrote:On 2011-06-08 13:29:27 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:In this case, the alias points at A.func or something like that, no? So you have enough information to figure out that the member function is from A? That is my point, you almost never *don't know* where the member function comes from. And even if you don't, it's dangerous to simply assume this. In my proposal, I'd guess that &memberFunc would give you a 'delegate-function' pointer, which you could then cast o to the right type (assuming it is that type) and pass it into the function. i.e.: auto fptr = &memberFunc; fptr(cast(thisType!(fptr))o); // thisType gets the type of the 'this' argument from the delegate-function pointerOn Wed, 08 Jun 2011 13:07:50 -0400, Michel Fortin <michel.fortin michelf.com> wrote:This is not at all a feature of Objective-C. This was a workaround. Tell me, if inside a template you have an alias to a member function, how can I call that member function? This won't work: void callMe(alias memberFunc)(Object o) { o.memberFunc(); // won't work, Object has no member called "memberFunc". }On 2011-06-08 10:54:54 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:The issue with hacking delegates I have is that almost certainly you know what the type of the function pointer is, which means you almost certainly have access to the member function for that type directly, it seems a very strange use case to be able to dynamically address the member functions of a class without knowing the type. When I first wrote the above reason, I tried to think of a compelling real example, I couldn't. Now, you are implementing a bridge to another language that supports a feature, which means you have to implement it. But how often is that feature used in that other language?On Wed, 08 Jun 2011 10:40:48 -0400, Daniel Murphy <yebblies nospamgmail.com> wrote: I almost would prefer that hacking delegates would be illegal. Yes, you can get the function pointer and data pointer out of a delegate, but cannot set them. I can't think of any good use cases for them.I was "hacking delegates" a lot in the D/Objective-C bridge (before I decided to bring things directly in the compiler). To make it short, I needed to do that to call the appropriate D function from Objective-C stub method implementation.Although even there it won't work very well if your member is a virtual function. I needed to use an ever stranger workaround for that. Here's the actual code from the Objective-C bridge (it's a template which be mixed in the class):This is an entirely different thing, a delegate removes the virtual-ness of the call. &A.func points to A's function, not to the virtual version (it can't possibly know that without an instance). Having a way to say "call vtable entry for A.func" for a specific object would be nice, but is not a delegate.I'd much prefer memberFunc(o); This is of course for a delegate-function pointer, not for an alias. I'm not sure how an alias would work. -SteveAll this is dependent on the idea that a delegate cannot be constructed unless you have the original method (or a type-safe 'delegate-function' such as int function(A this)). I really think that makes sense.I won't disagree with anything you say, because I do agree. I know my use case is a fringe one, and I don't need it anymore so I don't care much. And it'd only need one small thing for it to work without all that cumbersome hack: o.memberFunc() // where methodFunc is an alias to a member of o
Jun 08 2011
On 2011-06-08 15:21:47 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> said:Exactly.This is not at all a feature of Objective-C. This was a workaround. Tell me, if inside a template you have an alias to a member function, how can I call that member function? This won't work: void callMe(alias memberFunc)(Object o) { o.memberFunc(); // won't work, Object has no member called "memberFunc". }In this case, the alias points at A.func or something like that, no?So you have enough information to figure out that the member function is from A?Yes. (Although I'm not sure you can extract this info from the alias, the compiler has it, and I have it through other means, namely typeof(this)).That is my point, you almost never *don't know* where the member function comes from. And even if you don't, it's dangerous to simply assume this.The member function here is an alias, the compiler knows where this function comes from and can check whether the 'this' pointer is of the right type. It just won't let us call it because there's no syntax. That's the core of the problem. I worked around that by adding a non-virtual member function that just returns a delegate to the virtual one. Constructing the delegate manually is a workaround to call that non-virtual member. I can't call even a non-virtual member function without it because I mixin the same template many times within the same class, which creates ambiguous overloads for "resolveVirtualCall". Taking the address directly and assigning it to a delegate works because I'm not getting the symbol through the object but through the current scope which gives precedence to a function in the template scope. To make that clear, this works: private static R forwardVirtualCall(objc.runtime.id self, objc.runtime.SEL _cmd, A args) { R delegate(A) delegate() resolve; resolve.ptr = objc.msg.send!(void*)(self, objc.method.selector!("d_object")); resolve.funcptr = &resolveVirtualCall; return resolve()(args); } while this doesn't when mixing in the templates multiple times within a class: private static R forwardVirtualCall(objc.runtime.id self, objc.runtime.SEL _cmd, A args) { auto o = cast(typeof(this))objc.msg.send!(void*)(self, objc.method.selector!("d_object")); return o.resolveVirtualCall()(args); } It gives this error: /objc/bridge.d(253): Error: cocoa.foundation.date.NSDate.ObjcBindMethod!(opAdd,NSDate,"addTimeInterval:",double .resolveVirtualCall at /cocoa/foundation/date.d(245) conflicts with cocoa.foundation.date.NSDate.ObjcBindMethod!(isEqualToDate,bool,"isEqualToDate:",NSDate .resolveVirtualCall at /cocoa/foundation/date.d(245) I'm sorry if this wasn't clear the first time, I think it wasn't for me either. It's been a long time since I written or even used that code. To, to summarize: Calling a virtual function relied on defining and calling a non-virtual member. A non-virtual member which was ambiguous and could be called only through a manually-crafted delegate. Hence my need for a manually crafted delegate.In my proposal, I'd guess that &memberFunc would give you a 'delegate-function' pointer, which you could then cast o to the right type (assuming it is that type) and pass it into the function. i.e.: auto fptr = &memberFunc; fptr(cast(thisType!(fptr))o); // thisType gets the type of the 'this' argument from the delegate-function pointerThat would probably work as it's just sugar for creating a delegate manually, with some added type safeties.It'd be nice to have that, even if just as a library solution. Do we have a __traits to get the vtable offset of a function?Although even there it won't work very well if your member is a virtual function. I needed to use an ever stranger workaround for that. Here's the actual code from the Objective-C bridge (it's a template which be mixed in the class):This is an entirely different thing, a delegate removes the virtual-ness of the call. &A.func points to A's function, not to the virtual version (it can't possibly know that without an instance). Having a way to say "call vtable entry for A.func" for a specific object would be nice, but is not a delegate.Agree. Also, an alias could work using the same syntax too if we had UFCS. :-) -- Michel Fortin michel.fortin michelf.com http://michelf.com/I'd much prefer memberFunc(o); This is of course for a delegate-function pointer, not for an alias. I'm not sure how an alias would work.All this is dependent on the idea that a delegate cannot be constructed unless you have the original method (or a type-safe 'delegate-function' such as int function(A this)). I really think that makes sense.I won't disagree with anything you say, because I do agree. I know my use case is a fringe one, and I don't need it anymore so I don't care much. And it'd only need one small thing for it to work without all that cumbersome hack: o.memberFunc() // where methodFunc is an alias to a member of o
Jun 08 2011
Daniel Murphy Wrote:Currently, this compiles: class A { void func() {} } void main() { auto p = &A.func; } In this case, typeof(p) is void function().Shouldn't it be void function(A)? As long as the ABI supports it, that would make the most sense to me... As I understand it, the this pointer is just a hidden parameter.
Jun 08 2011
"Jason House" <jason.james.house gmail.com> wrote in message news:isntm4$2ull$1 digitalmars.com...Shouldn't it be void function(A)? As long as the ABI supports it, that would make the most sense to me... As I understand it, the this pointer is just a hidden parameter.Unfortunately the ABI doesn't support it. 'this' must always be the last parameter, so that kind of conversion would only work for a subset of functions. eg. class A { int funcA(int); } is equivalent to: int function(int, A) and struct S { int a, b, c; } class A { S funcA(int); } is equivalent to: void function(int, S*, A)
Jun 08 2011
Oh wow, my previous comment was total nonsense, I confused .func with the delegate .funcptr property… The bugs probably comes from the delegate .funcptr property being a function pointer of the same signature as the delegate type itself, which doesn't make too much sense: http://d.puremagic.com/issues/show_bug.cgi?id=2672. Presumably because of this, &A.func also has the same type so things match up. However, as not every delegate can be called as a function because of ABI reasons (think about the hidden struct return pointer), changing the type of delegate.funcptr to void* as well might be the better solution. David On 6/8/11 10:00 AM, Daniel Murphy wrote:Currently, this compiles: class A { void func() {} } void main() { auto p =&A.func; } In this case, typeof(p) is void function(). Calling one of these pointers, of course, can easily give you a segfault as it completely ignores the this pointer. I didn't even realize you could do this until I saw http://d.puremagic.com/issues/show_bug.cgi?id=5986 I understand that it could be useful to have a way to get the address of a non-static member function, but I doubt returning a malformed function pointer is really useful. Does anybody think changing&ClassType.nonStaticMember to return void* would be a bad idea?
Jun 08 2011
"David Nadlinger" <see klickverbot.at> wrote in message news:iso2fc$6a2$1 digitalmars.com...Oh wow, my previous comment was total nonsense, I confused .func with the delegate .funcptr property. The bugs probably comes from the delegate .funcptr property being a function pointer of the same signature as the delegate type itself, which doesn't make too much sense: http://d.puremagic.com/issues/show_bug.cgi?id=2672. Presumably because of this, &A.func also has the same type so things match up. However, as not every delegate can be called as a function because of ABI reasons (think about the hidden struct return pointer), changing the type of delegate.funcptr to void* as well might be the better solution. DavidI think the botched type comes from the compiler's implementation - function types have no idea wheather they have a this parameter or not! I'm currently thinking changing &ClassType.nonstaticmemberfunction and delegate.funcptr to return void*, and making delegate.funcptr read-only should smooth off this nasty corner quite nicely.
Jun 08 2011
Turned out it was even easier to do than I expected: https://github.com/yebblies/dmd/commit/ed7a499d689940fd21d23bb658e97b1024a7d6be I'm not sure if delegate.funcptr should return a void* lvalue or a const(void)* rvalue though. The latter would allow you to cast away const and mess with it.
Jun 08 2011
"Daniel Murphy" <yebblies nospamgmail.com> wrote in message news:isofvu$13tv$1 digitalmars.com...Turned out it was even easier to do than I expected: https://github.com/yebblies/dmd/commit/ed7a499d689940fd21d23bb658e97b1024a7d6be I'm not sure if delegate.funcptr should return a void* lvalue or a const(void)* rvalue though. The latter would allow you to cast away const and mess with it.swap lvalue and rvalue!
Jun 08 2011