Thread overview
pointer to member without 'this' - mem_fun like
Mar 18, 2008
Vlad
Mar 18, 2008
Frits van Bommel
Mar 18, 2008
Vlad
Mar 18, 2008
Frits van Bommel
Mar 18, 2008
Vlad
Mar 18, 2008
Derek Parnell
Mar 18, 2008
Vlad
Mar 18, 2008
Frits van Bommel
March 18, 2008
Hi list,

I was wondering if D has something like C's mem_fun, where one can pass a pointer to a member function of a class, that later can be called with various 'this' instances.

Furthermore, does a similar mechanism for data members exist?

Thank you,
Vlad
March 18, 2008
Vlad wrote:
> Hi list,
> 
> I was wondering if D has something like C's mem_fun, where one can pass a pointer to a member function of a class, that later can be called with various 'this' instances.

No, sorry.
It does have delegates, but then the vtable lookup is performed when the delegate is constructed. If that's okay, (i.e. if you only use this for instances of the same type or subtypes that don't override that method) you should be able to take a delegate and assign a new 'this' (.ptr) to it before calling it...

> Furthermore, does a similar mechanism for data members exist?

No. You could hack something together with pointer arithmetic, but it won't be pretty. Some kind of wrapper could perhaps be written as a struct template though.
March 18, 2008
Frits van Bommel wrote:
> Vlad wrote:
>> Hi list,
>>
>> I was wondering if D has something like C's mem_fun, where one can pass a pointer to a member function of a class, that later can be called with various 'this' instances.
> 
> No, sorry.
> It does have delegates, but then the vtable lookup is performed when the delegate is constructed. If that's okay, (i.e. if you only use this for instances of the same type or subtypes that don't override that method) you should be able to take a delegate and assign a new 'this' (.ptr) to it before calling it...
> 

Thanks, this should do it - however I still need an(other) instance when passing the delegate, right?

>> Furthermore, does a similar mechanism for data members exist?
> 
> No. You could hack something together with pointer arithmetic, but it won't be pretty. Some kind of wrapper could perhaps be written as a struct template though.

Yeah, that was silly of me:). I will be using 'setters' and revert to the previous answer.

Thank you very much!

Vlad
March 18, 2008
Vlad wrote:
> Frits van Bommel wrote:
>> Vlad wrote:
>>> Hi list,
>>>
>>> I was wondering if D has something like C's mem_fun, where one can pass a pointer to a member function of a class, that later can be called with various 'this' instances.
>>
>> No, sorry.
>> It does have delegates, but then the vtable lookup is performed when the delegate is constructed. If that's okay, (i.e. if you only use this for instances of the same type or subtypes that don't override that method) you should be able to take a delegate and assign a new 'this' (.ptr) to it before calling it...
>>
> 
> Thanks, this should do it - however I still need an(other) instance when passing the delegate, right?

You *might* get away with using &Class.memberfn to fill in dg.funcptr. But I've never tried this, so you might want to make sure it works before using it for anything serious.
March 18, 2008
On Tue, 18 Mar 2008 11:27:23 +0200, Vlad wrote:

> Hi list,
> 
> I was wondering if D has something like C's mem_fun, where one can pass a pointer to a member function of a class, that later can be called with various 'this' instances.

Excuse my ignorance, but what is the benefit of this technique?

- --
Derek Parnell
Melbourne, Australia
skype: derek.j.parnell
March 18, 2008
"Frits van Bommel" <fvbommel@REMwOVExCAPSs.nl> wrote in message news:fro9ip$dib$1@digitalmars.com...
>>
>> Thanks, this should do it - however I still need an(other) instance when passing the delegate, right?
>
> You *might* get away with using &Class.memberfn to fill in dg.funcptr. But I've never tried this, so you might want to make sure it works before using it for anything serious.

It does work, at least in my experience.  Of course this bypasses any vtable lookup so you'll just be getting the implementation of the method from Class.


March 18, 2008
Derek Parnell wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On Tue, 18 Mar 2008 11:27:23 +0200, Vlad wrote:
> 
>> Hi list,
>>
>> I was wondering if D has something like C's mem_fun, where one can pass a pointer to a member function of a class, that later can be called with various 'this' instances.
> 
> Excuse my ignorance, but what is the benefit of this technique?
> 
> - --
> Derek Parnell

Example: writing a map()-like function that works on a collection of objects and calling a method on them, instead of a free function



Pseudocode:
(with a 'free function'):

string in[] = ...
int out[] = map (in, len);

(with a 'member_fun'):
T in[] = ...
T out[] = map(in, &T.do_something);

or even:
T in[] = ...
int out[] = map(in, &T.get_some_int_property)

March 18, 2008
Jarrett Billingsley wrote:
> "Frits van Bommel" <fvbommel@REMwOVExCAPSs.nl> wrote in message news:fro9ip$dib$1@digitalmars.com...
>>> Thanks, this should do it - however I still need an(other) instance when passing the delegate, right?
>> You *might* get away with using &Class.memberfn to fill in dg.funcptr. But I've never tried this, so you might want to make sure it works before using it for anything serious.
> 
> It does work, at least in my experience.  Of course this bypasses any vtable lookup so you'll just be getting the implementation of the method from Class. 
> 
> 

It didn't work for me (see full code below)..

On the same topic, I see in the "Template parameters" heading here (http://www.digitalmars.com/d/1.0/templates-revisited.html) that template syntax to force a member of a type does not exist either:(

I am trying to generalize the initialization of the fields of a struct/class with setters from something like a database rowset (and also to learn D;)

(here's the code: change &author.name to &Author.name)

import std.stdio;

void set_field(T,F)(T instance, void delegate(F) setter)
{
    setter("zz");
}

class Author {
    private string _name;
    string name() {
        return _name;
    }
    void name(string name) {
        _name = name;
    }
}

int main(char[][] args)
{
    Author author = new Author();
    set_field!(Author,string)(author, &author.name);
    writefln(author.name);
    return 0;
}
March 18, 2008
"Vlad" <b100dian@gmail.com> wrote in message news:47DFC12D.8020604@gmail.com...
> Jarrett Billingsley wrote:
>> "Frits van Bommel" <fvbommel@REMwOVExCAPSs.nl> wrote in message news:fro9ip$dib$1@digitalmars.com...
>>>> Thanks, this should do it - however I still need an(other) instance when passing the delegate, right?
>>> You *might* get away with using &Class.memberfn to fill in dg.funcptr. But I've never tried this, so you might want to make sure it works before using it for anything serious.
>>
>> It does work, at least in my experience.  Of course this bypasses any vtable lookup so you'll just be getting the implementation of the method from Class.
>
> It didn't work for me (see full code below)..

> (here's the code: change &author.name to &Author.name)

>     set_field!(Author,string)(author, &author.name);

No, that isn't going to work, because when you get &Author.name, you only have one half of the puzzle.  It's just a function.  You need to factor in the instance somehow.

void set_field(T,F)(T instance, void function(F) setter)
{
    void delegate(F) dg;
    dg.funcptr = setter;
    dg.ptr = cast(void*)instance;
    dg("zz");
}

This is one way to do it.  Another way is to have the code generated at compile time instead:

template set_field(char[] name)
{
    void set_field(T)(T instance)
    {
        mixin("instance." ~ name ~ " = `zz`;");
    }
}

...

set_field!("name")(author);


March 18, 2008
Vlad wrote:
> Example: writing a map()-like function that works on a collection of objects and calling a method on them, instead of a free function
> 
> Pseudocode:
> (with a 'free function'):
> 
> string in[] = ...
> int out[] = map (in, len);
> 
> (with a 'member_fun'):
> T in[] = ...
> T out[] = map(in, &T.do_something);
> 
> or even:
> T in[] = ...
> int out[] = map(in, &T.get_some_int_property)

Normal D way to do something like this:
---
// Note: 'in' and 'out' are keywords so they can't be used as variables
T[] input = ...
// free function:
int[] out1 = map (input, &len); // if map accepts raw function pointers
                                // otherwise, use something like below
// member function:
U[] out2 = map(input, (T t) { return t.do_something; });
// or even:
int[] out3 = map(input, (T t) { op1(t); op2(t); return op3(t); });
---
It's a bit longer, but doesn't require extra getters & setters just for this.
The second parameter to map in the latter two examples is a delegate literal; it can contain any block of code, and can even access local variables in the surrounding code if needed.
You'll need to overload map (or turn it into a template function) if you want to also accept function pointers as in my first example. Of course if you want it to allow multiple input and output array types it'll have to be a template function anyway so that shouldn't be a problem.


P.S. Normally the operation to apply is the *first* parameter to a function called 'map'.