Jump to page: 1 2
Thread overview
how to do member function pointer in D?
Jul 30, 2008
newbie
Jul 30, 2008
Russell Lewis
Jul 30, 2008
newbie
Jul 30, 2008
BCS
Jul 30, 2008
newbie
Jul 30, 2008
BCS
Jul 30, 2008
newbie
Jul 30, 2008
BCS
Jul 30, 2008
newbie
Jul 30, 2008
BCS
Jul 31, 2008
u
Jul 31, 2008
BCS
Jul 31, 2008
JAnderson
Jul 31, 2008
u
Jul 31, 2008
Kirk McDonald
Jul 31, 2008
u
Jul 31, 2008
JAnderson
July 30, 2008
Hi,

I want to be able to create a member function pointer type from a class (not from an object of that class), i.e.

class A {
  void f() {}
  void g() {}
}

(member function pointer) mfp = &A.f; // what's the sytax for the type?

// also I want the compiler to report error if I pass g() to mfp:
mfp = &A.g;   // type error!

// and mfp can be invoked on different object instance of A: A a1, a2;

mfp(a1);   // call a1.f(), what's the right syntax?
mfp(a2);   // call a2.f()

Thanks.
July 30, 2008
Although people have presented hacks to do this, there isn't a standard way to do this in D.

Of course, you could use a function literal to accomplish this:
  mfp = function void(A obj) { obj.f(); };
That isn't techically a member function pointer, but it is pretty similar.

Do you have a compelling use case where you need member-function-pointer but delegates or the function literal above wouldn't work?  I haven't yet heard of one, but of course they might exist. :)

Russ

newbie wrote:
> Hi,
> 
> I want to be able to create a member function pointer type from a class (not
> from an object of that class), i.e.
> 
> class A {
>   void f() {}
>   void g() {}
> }
> 
> (member function pointer) mfp = &A.f; // what's the sytax for the type?
> 
> // also I want the compiler to report error if I pass g() to mfp:
> mfp = &A.g;   // type error!
> 
> // and mfp can be invoked on different object instance of A:
> A a1, a2;
> 
> mfp(a1);   // call a1.f(), what's the right syntax?
> mfp(a2);   // call a2.f()
> 
> Thanks.
July 30, 2008
The main problem is that I want to let the D compiler check the type for me: e.g.

mfp1 = function void(A obj) { obj.f(); };
mfp2 = function void(A obj) { obj.g(); };
void function(A) fp;   // suppose fp is what I intended to call A.f()

fp = mfp1;    // cass 1: OK
fp = mfp2;    // cass 2: OK
mfp1 = mfp2;  // cass 3: also OK

Of course this is because fp is specified by the signature of it's arguments type and return type.

I want a member function pointer type that is more strict than this, i.e. both case (2 & 3) will cause compiler type error.

Another minor issue with your suggested approach is that: I have to write those wrappers for all the member function that I want to use.


== Quote from Russell Lewis (webmaster@villagersonline.com)'s article
> Although people have presented hacks to do this, there isn't a standard
> way to do this in D.
> Of course, you could use a function literal to accomplish this:
>    mfp = function void(A obj) { obj.f(); };
> That isn't techically a member function pointer, but it is pretty similar.
> Do you have a compelling use case where you need member-function-pointer
> but delegates or the function literal above wouldn't work?  I haven't
> yet heard of one, but of course they might exist. :)
> Russ
> newbie wrote:
> > Hi,
> >
> > I want to be able to create a member function pointer type from a class (not from an object of that class), i.e.
> >
> > class A {
> >   void f() {}
> >   void g() {}
> > }
> >
> > (member function pointer) mfp = &A.f; // what's the sytax for the type?
> >
> > // also I want the compiler to report error if I pass g() to mfp:
> > mfp = &A.g;   // type error!
> >
> > // and mfp can be invoked on different object instance of A: A a1, a2;
> >
> > mfp(a1);   // call a1.f(), what's the right syntax?
> > mfp(a2);   // call a2.f()
> >
> > Thanks.

July 30, 2008
Reply to Newbie,

> The main problem is that I want to let the D compiler check the type
> for me: e.g.
> 
> mfp1 = function void(A obj) { obj.f(); };
> mfp2 = function void(A obj) { obj.g(); };
> void function(A) fp;   // suppose fp is what I intended to call A.f()
> fp = mfp1;    // cass 1: OK
> fp = mfp2;    // cass 2: OK
> mfp1 = mfp2;  // cass 3: also OK
> Of course this is because fp is specified by the signature of it's
> arguments type and return type.
> 
> I want a member function pointer type that is more strict than this,
> i.e. both case (2 & 3) will cause compiler type error.
> 

That is not something the type system can do. The two methods operate on the same object type, take the same args and return the same type. As far as the type system system is concerned, they are identical.

Maybe I'm missing something because what you seem to want doesn't seem useful to me, the restriction you seem to want would restrict the allowable values for fp to exactly one. If this is so, why do you want a variable?

The only use I can think of is if you want to call a the f method from a base class on an object of a derived class. If this is the case you are subverting the type system so you are on your own.

> Another minor issue with your suggested approach is that: I have to
> write those wrappers for all the member function that I want to use.
> 
> == Quote from Russell Lewis (webmaster@villagersonline.com)'s article
> 
>> Although people have presented hacks to do this, there isn't a
>> standard
>> way to do this in D.
>> Of course, you could use a function literal to accomplish this:
>> mfp = function void(A obj) { obj.f(); };
>> That isn't techically a member function pointer, but it is pretty
>> similar.
>> Do you have a compelling use case where you need
>> member-function-pointer
>> but delegates or the function literal above wouldn't work?  I haven't
>> yet heard of one, but of course they might exist. :)
>> Russ
>> newbie wrote:
>>> Hi,
>>> 
>>> I want to be able to create a member function pointer type from a
>>> class (not from an object of that class), i.e.
>>> 
>>> class A {
>>> void f() {}
>>> void g() {}
>>> }
>>> (member function pointer) mfp = &A.f; // what's the sytax for the
>>> type?
>>> 
>>> // also I want the compiler to report error if I pass g() to mfp:
>>> mfp = &A.g;   // type error!
>>> 
>>> // and mfp can be invoked on different object instance of A: A a1,
>>> a2;
>>> 
>>> mfp(a1);   // call a1.f(), what's the right syntax? mfp(a2);   //
>>> call a2.f()
>>> 
>>> Thanks.
>>> 


July 30, 2008
> Maybe I'm missing something because what you seem to want doesn't seem useful to me, the restriction you seem to want would restrict the allowable values for fp to exactly one. If this is so, why do you want a variable?

I want my code to manipulate at function ptr level (instead of just calling the
function).

For now maybe what I can do is declare an invariant variable, which after initialization cannot be assigned to again.

But I have trouble to get this code compiled:

class A {
  void f() {writefln("f()");}
  void g() {writefln("g()");}
}
alias void function(A) FP;

class B {
  static invariant FP mfp1 = function void(A obj) {obj.f();};  // line 11
}

$ dmd memberfunptr.d
memberfunptr.d(11): Error: cannot implicitly convert expression (__funcliteral1)
of type void function(A) to invariant(void function(A))

Why I need to explicitly cast it?  and even after I change the line to:

  static invariant FP mfp1 = cast(invariant FP)(function void(A obj) {obj.f();});

It says:

$ dmd memberfunptr.d
memberfunptr.d(11): Error: non-constant expression __funcliteral1


Anyone know what's the right way to write this?

Thanks.
July 30, 2008
Reply to Newbie,

>> Maybe I'm missing something because what you seem to want doesn't
>> seem useful to me, the restriction you seem to want would restrict
>> the allowable values for fp to exactly one. If this is so, why do you
>> want a variable?
>> 
> I want my code to manipulate at function ptr level (instead of just
> calling the function).
> 
> For now maybe what I can do is declare an invariant variable, which
> after initialization cannot be assigned to again.
> 
> But I have trouble to get this code compiled:
> 
> class A {
> void f() {writefln("f()");}
> void g() {writefln("g()");}
> }
> alias void function(A) FP;
> 
> class B {
> static invariant FP mfp1 = function void(A obj) {obj.f();};// line 11
> }
[...]
> static invariant FP mfp1 = cast(invariant FP)(function void(A obj)
> {obj.f();});
> 
> It says:
> 
> $ dmd memberfunptr.d
> memberfunptr.d(11): Error: non-constant expression __funcliteral1

to clear that error:

static invariant FP mfp1;
static this()
{
mfp1 = cast(invariant FP)(function void(A obj){obj.f();});
}


OTOH I still have no clue what you are trying to do. I suspect their is a simperer way to do what you want.

That said, /I/ often /enjoy/ doing things the far from simple way. <g>


July 30, 2008
> to clear that error:
> static invariant FP mfp1;
> static this()
> {
>  mfp1 = cast(invariant FP)(function void(A obj){obj.f();});
> }

Thanks.

Two more questions:

1) why the cast is necessary? shall I report a bug? e.g.

invariant int a = 1;  // I don't need the cast here!

2) how to do it as global variables? e.g.

If I pull out it from B, and define as global variable:

invariant FP mfp2 = cast(invariant FP)(function void(A obj) {obj.f();});

$ dmd memberfunptr.d
memberfunptr.d(10): Error: non-constant expression __funcliteral1


> OTOH I still have no clue what you are trying to do. I suspect their is a
> simperer way to do what you want.
> That said, /I/ often /enjoy/ doing things the far from simple way. <g>

I need to hold a collection of member-function pointers, and manipulate it in some way, then later make function calls on different object via these pointers.

I want to protect myself that any these pointers shouldn't be re-assigned to other member functions with the same signatures.

July 30, 2008
Reply to Newbie,

>> to clear that error:
>> static invariant FP mfp1;
>> static this()
>> {
>> mfp1 = cast(invariant FP)(function void(A obj){obj.f();});
>> }
> Thanks.
> 
> Two more questions:
> 
> 1) why the cast is necessary? shall I report a bug? e.g.
> 
> invariant int a = 1;  // I don't need the cast here!
> 
> 2) how to do it as global variables? e.g.
> 
> If I pull out it from B, and define as global variable:
> 
> invariant FP mfp2 = cast(invariant FP)(function void(A obj)
> {obj.f();});
> 
> $ dmd memberfunptr.d
> memberfunptr.d(10): Error: non-constant expression __funcliteral1

same solution as befor (the issue is that the only thing you can put after the '=' ouside of a function is a constant expression and a function litteral isn't one)

//at global scope (OTOH static's are globals)
static invariant FP mfp1;
static this()
{
mfp1 = cast(invariant FP)(function void(A obj){obj.f();});
}


>> OTOH I still have no clue what you are trying to do. I suspect their
>> is a
>> simperer way to do what you want.
>> That said, /I/ often /enjoy/ doing things the far from simple way.
>> <g>
> I need to hold a collection of member-function pointers, and
> manipulate it in some way, then later make function calls on different
> object via these pointers.
> 
> I want to protect myself that any these pointers shouldn't be
> re-assigned to other member functions with the same signatures.
> 

I still don't get it, what type of manipulation (outside self modifying code) can you do that doesn't allow switching in a different function with the same signature?


July 30, 2008
> same solution as befor (the issue is that the only thing you can put after the '=' ouside of a function is a constant expression and a function litteral isn't one)

Why a function literal is not a constant expression?

Especially after I defining a global top level wrapper function in this case. Under the hood, it should just be a raw pointer to some memory address, why this cannot be a constant?

> //at global scope (OTOH static's are globals)
> static invariant FP mfp1;
> static this()
> {
> mfp1 = cast(invariant FP)(function void(A obj){obj.f();});
> }

Thanks again. I can live with this workaround right now, but I'd really like to write it as simple as:

invariant FP mfp2 = function void(A obj) {obj.f();};  // without the cast

> I still don't get it, what type of manipulation (outside self modifying code)

E.g. save in a hash-table, or use them as keys ...

And I'd really like to do self modifying code ;-) I read somewhere that D plan have to AST macros? so we are closer to lisp: http://en.wikipedia.org/wiki/Greenspun%27s_Tenth_Rule

> can you do that doesn't allow switching in a different function with the same signature?

Yes, I do it manually (by writing program carefully). I want the help from the
type system (or the language compiler) to protect me from such violation.

July 30, 2008
Reply to Newbie,

>> same solution as befor (the issue is that the only thing you can put
>> after the '=' ouside of a function is a constant expression and a
>> function litteral isn't one)
>> 
> Why a function literal is not a constant expression?
> 
> Especially after I defining a global top level wrapper function in
> this case. Under the hood, it should just be a raw pointer to some
> memory address, why this cannot be a constant?
> 

don't ask me.

>> //at global scope (OTOH static's are globals)
>> static invariant FP mfp1;
>> static this()
>> {
>> mfp1 = cast(invariant FP)(function void(A obj){obj.f();});
>> }
> Thanks again. I can live with this workaround right now, but I'd
> really like to write it as simple as:
> 
> invariant FP mfp2 = function void(A obj) {obj.f();};  // without the
> cast
> 
>> I still don't get it, what type of manipulation (outside self
>> modifying code)
>> 
> E.g. save in a hash-table, or use them as keys ...
> 

but neither of those will be usefull unless you can assign more than one value to the type

what I'm reading (and I must be missing somthing) is somthing like a hash table where the keys are the number 5 to the values are the number 3.

One idea on what I'm missing; 

Do you want nothing at all to be assigname to the variable after the fist assigment?

class Bob {void a(){} void b(){} }

The_Type fnp = Bob.a;
fnp = Bob.a; // valid or not?

Do you care if other instances of the same type have pointers to other function?

The_Type fnp = Bob.a;


> And I'd really like to do self modifying code ;-) I read somewhere
> that D plan have to AST macros? so we are closer to lisp:
> http://en.wikipedia.org/wiki/Greenspun%27s_Tenth_Rule
> 

IIRC that is with regards to program internals, not the external interface

>> can you do that doesn't allow switching in a different function with
>> the same signature?
>> 
> Yes, I do it manually (by writing program carefully). I want the help
> from the type system (or the language compiler) to protect me from
> such violation.
> 


« First   ‹ Prev
1 2