7

I have been learning D, and am in particular very excited for it's Generic programming capabilities. Delegates are wonderful, and apparently they have completely replaced member-function-pointers, so I was stuck when I wanted to implement something like the following:

template <typename T>
void DispatchMethodForAll(std::vector<T*> & container, void (T::* func)(void))
{
  for(typename std::vector<T*>::iterator it = container.begin(); it != container.end(); ++it)
      (*it)->*func();
}

According to what I have learned of function pointers and delegates in D, is that neither of them can do this, since function pointers can only be declared for global functions, and delegates have to be bound to an object, there is no "partial delegate" that I can find. As seen here, I cannot use a delegate, since there is no single object that can be bound to the method that is to be called.

I know that I could do it with mixins, and essentially make it a macro. However this really doesn't sound D-like, and I figured there should be "The correct way"

Ramon Zarazua B.
  • 7,195
  • 4
  • 22
  • 26

2 Answers2

6

You could still use a delegate here.

void DispatchMethodForAll(T)(T*[] container, void delegate(T*) action)
{
    foreach (it; container)
        action(it);
}

...

DispatchMethodForAll(container, (Foo* foo) { foo.func(); });

Example: http://www.ideone.com/9HUJa

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • BTW, I think this solution is, more or less, maybe with a little abstraction, what a *c++ pointer to virtual method* ends up being. – BCS Nov 08 '11 at 19:53
  • It is almost exactly that. I think this is the "proper" way to do it although I was hoping to be able to do it without having to adapt a function into a delegate. I'm also curious to see what kind of code the compiler will spit out, because I hope that it won't generate unnecessary memory allocations. – Ramon Zarazua B. Nov 10 '11 at 18:44
3

you can take a page out of the std.algorithm to find out how it does that

void DispatchMethodForAll(alias func, T)(T container)
{
    alias unaryFun!func _func
    foreach (it; container)
        _func(it);
}

btw a delegate can be bound to a struct and the compiler can create a custom struct from local (stack allocated) variables and define a delegate on that

this happens with

void foo(){
    int[] array;
    int i=0;
    void bar(int a){
        i+=a;
    }
    void DispatchMethodForAll(&bar)(array);
    writeln(i);//prints the sum of array
}

bar is a delegate bound to a struct with (at least) a member i of type int of which the local variable i is an alias

ratchet freak
  • 47,288
  • 5
  • 68
  • 106