www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function pointer to member function.

reply "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
I would like to get access to a member function pointer. Taking
the this* as
the first argument.

class Foo
{
     void bar(int a)
     {
        //do something awesome
     }
}

unittest
{
     Foo a = new Foo();
     Foo b = new Foo();

     auto fp = getFP!(Foo.bar);
     fp(a, 1); //Basically calls a.foo(1)
     fp(b, 1); //Basically calls b.foo(1)
}

How should i implement getFP above? Is it even possible?
Oct 16 2013
parent reply "Chris Cain" <clcain uncg.edu> writes:
On Thursday, 17 October 2013 at 01:17:21 UTC, TheFlyingFiddle 
wrote:
 I would like to get access to a member function pointer. Taking
 the this* as
 the first argument.

 ...snip...
 How should i implement getFP above? Is it even possible?
Well, it's certainly possible. If you were to do this: ``` delegate void(int) dg = &a.bar; dg(1); ``` then you'd see the behavior you're looking for. Basically the class reference is stored in dg.ptr and the function is in dg.funcptr. With that in mind, I whipped this up: ``` import std.stdio; class Foo { char c; this() { c = 'a'; } this(char _c) { c = _c; } void bar(int i) { writeln("i = ", i, " c = ", c); } } import std.traits; //ParentOf!S is pseudocode representing __traits(parent, S) //ReturnType!S function(ParentOf!S, ParameterTypeTuple!S) auto getFP(alias S)() if(isSomeFunction!S) { mixin("alias Parent = " ~ __traits(parent, S).stringof ~ ";"); return (Parent r, ParameterTypeTuple!S t) { ReturnType!S delegate(ParameterTypeTuple!S) dg; dg.funcptr = &S; dg.ptr = cast(void*) r; return dg(t); }; } void main() { Foo a = new Foo(); Foo b = new Foo('b'); auto fp = getFP!(Foo.bar); fp(a, 1); fp(b, 2); } ``` Now one thing to note is that I'm not confident it's bug-free. It does work in this test case, but I couldn't use __traits(parent, S) as a type, so I used a mixin to kind of force it to work. So I'm not fully sure whether it will work in all cases, but if someone else has some improvements, that's fine. Another thing: I didn't spend too much time on the template constraint. "isSomeFunction" is almost certainly too permissive. I just threw it together and I haven't coded in D for a while. I hope this helped!
Oct 16 2013
parent "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
On Thursday, 17 October 2013 at 03:21:38 UTC, Chris Cain wrote:
 On Thursday, 17 October 2013 at 01:17:21 UTC, TheFlyingFiddle 
 wrote:
 I would like to get access to a member function pointer. Taking
 the this* as
 the first argument.

 ...snip...
 How should i implement getFP above? Is it even possible?
Well, it's certainly possible. If you were to do this: ``` delegate void(int) dg = &a.bar; dg(1); ``` then you'd see the behavior you're looking for. Basically the class reference is stored in dg.ptr and the function is in dg.funcptr. With that in mind, I whipped this up: ``` import std.stdio; class Foo { char c; this() { c = 'a'; } this(char _c) { c = _c; } void bar(int i) { writeln("i = ", i, " c = ", c); } } import std.traits; //ParentOf!S is pseudocode representing __traits(parent, S) //ReturnType!S function(ParentOf!S, ParameterTypeTuple!S) auto getFP(alias S)() if(isSomeFunction!S) { mixin("alias Parent = " ~ __traits(parent, S).stringof ~ ";"); return (Parent r, ParameterTypeTuple!S t) { ReturnType!S delegate(ParameterTypeTuple!S) dg; dg.funcptr = &S; dg.ptr = cast(void*) r; return dg(t); }; } void main() { Foo a = new Foo(); Foo b = new Foo('b'); auto fp = getFP!(Foo.bar); fp(a, 1); fp(b, 2); } ``` Now one thing to note is that I'm not confident it's bug-free. It does work in this test case, but I couldn't use __traits(parent, S) as a type, so I used a mixin to kind of force it to work. So I'm not fully sure whether it will work in all cases, but if someone else has some improvements, that's fine. Another thing: I didn't spend too much time on the template constraint. "isSomeFunction" is almost certainly too permissive. I just threw it together and I haven't coded in D for a while. I hope this helped!
Thanks, this works well for my needs.
Oct 17 2013