Thread overview
Code example for function/delegate as template argument ?
May 04, 2016
chmike
May 04, 2016
Basile B.
May 04, 2016
chmike
May 04, 2016
Basile B.
May 04, 2016
Basile B.
May 04, 2016
chmike
May 04, 2016
Basile B.
May 04, 2016
chmike
May 04, 2016
H. S. Teoh
May 04, 2016
Hello,

I failed to find some code example for a template class/struct that accept a function/delegate as template argument. All examples I could find use simple value types like int or double.


I piggy bag another question. Defining a function/delegate as function argument is shown in examples. What I could not find is how would I pass an object instance with a method to call ? In C++ we use std::bind. How do we do that in D ?
May 04, 2016
On Wednesday, 4 May 2016 at 06:21:36 UTC, chmike wrote:
> Hello,
>
> I failed to find some code example for a template class/struct that accept a function/delegate as template argument. All examples I could find use simple value types like int or double.
>
>
> I piggy bag another question. Defining a function/delegate as function argument is shown in examples. What I could not find is how would I pass an object instance with a method to call ? In C++ we use std::bind. How do we do that in D ?

Hello, you can use an alias this to pass a lmbda (or a delegate):

----
module runnable;

import std.stdio;

struct Foo(alias fun)
{
    this(string text)
    {
        fun(text);
    }
}

void main(string[] args)
{
    alias fun = (a) => a.writeln;
    auto foo = Foo!fun("hello");
}
----

I suppose that a constraint would be welcome be that's not the point here.
May 04, 2016
On Wednesday, 4 May 2016 at 06:21:36 UTC, chmike wrote:
> Hello,
>
> I failed to find some code example for a template class/struct that accept a function/delegate as template argument. All examples I could find use simple value types like int or double.
>
>
> I piggy bag another question. Defining a function/delegate as function argument is shown in examples. What I could not find is how would I pass an object instance with a method to call ? In C++ we use std::bind. How do we do that in D ?

As for the second question, finding the right method dynamically (virtual method or interface) is easy so I suppose you want to find a member using D reflection.
Here is a quick example:

----
struct Bar
{
    void fun(string text) {text.writeln;}
}

struct Foo
{
    void delegate(string) dg;

    this(T)(T t)
    {
        foreach(member; __traits(allMembers, T))
        {
            foreach(i, overload; __traits(getOverloads, T, member)[])
            {
                auto overloadDg = &__traits(getOverloads, t, member)[i];
                static if (is(typeof(overloadDg) == typeof(dg)))
                {
                    dg = &__traits(getOverloads, t, member)[i];
                    break;
                }
            }
        }
        if (dg)
            dg("found");
    }
}

void main(string[] args)
{
    Bar bar;
    Foo foo = Foo(bar);
}
----

More checkings are possible. Here I just verify that a pointer to a member function is of same type as the delegate to assign.
May 04, 2016
On Wednesday, 4 May 2016 at 06:59:00 UTC, Basile B. wrote:
> . . .
> void main(string[] args)
> {
>     alias fun = (a) => a.writeln;
>     auto foo = Foo!fun("hello");
> }

Is this equivalent to Foo!(a => a.writeln) or is it required to split this in two instructions as you did ? I also thought the parenthesis around the lambda arguments are not required. Is that right ?


May 04, 2016
I think you misunderstood the second question.

Here is another attempt with an example.

// function accepting a function as argument
void foo(function void fg(int)) {
    fg(5);
}

// A class with a none static method with the same signature as the argument function of foo
class Bar {
    void fizz(int a) { writefln("Arg: %s", a); }
}

// An instance of class Bar
auto bar = new Bar;

// Calling foo by passing bar and the method fizz so that bar.fizz() is called when foo calls fg
foo( ??? );

Does the argument type need to be a delegate ?
May 04, 2016
On Wednesday, 4 May 2016 at 10:58:04 UTC, chmike wrote:
> On Wednesday, 4 May 2016 at 06:59:00 UTC, Basile B. wrote:
>> . . .
>> void main(string[] args)
>> {
>>     alias fun = (a) => a.writeln;
>>     auto foo = Foo!fun("hello");
>> }
>
> Is this equivalent to Foo!(a => a.writeln) or is it required to split this in two instructions as you did ? I also thought the parenthesis around the lambda arguments are not required. Is that right ?

Yes this is equivalent, the parens are not required. With a delegate literal they are: "auto foo = Foo!((a){a.writeln;})("hello");
May 04, 2016
On Wed, May 04, 2016 at 06:21:36AM +0000, chmike via Digitalmars-d-learn wrote:
> Hello,
> 
> I failed to find some code example for a template class/struct that accept a function/delegate as template argument. All examples I could find use simple value types like int or double.

The usual way is to use an alias argument:

	class MyClass(alias fun)
		if (is(typeof(fun(0)))) // assuming fun takes 1 int argument
	{
		void method() {
			fun(0);
		}
	}


> I piggy bag another question. Defining a function/delegate as function argument is shown in examples. What I could not find is how would I pass an object instance with a method to call ? In C++ we use std::bind. How do we do that in D ?

You probably need a delegate, since a function (== function pointer) in D is a pointer to a (module-global) function with no context. If you need a context, e.g., an object instance, you need a delegate. Example:

	class C {
		void method(int x) {
			import std.stdio;
			writeln("bing!");
		}
	}
	void fun(void delegate(int) dg) {
		dg(1);
	}
	void main() {
		auto c = new C;
		fun(&c.method);
	}


T

-- 
Long, long ago, the ancient Chinese invented a device that lets them see through walls. It was called the "window".
May 04, 2016
On Wednesday, 4 May 2016 at 11:19:59 UTC, chmike wrote:
> I think you misunderstood the second question.
>
> Here is another attempt with an example.
>
> // function accepting a function as argument
> void foo(function void fg(int)) {
>     fg(5);
> }
>
> // A class with a none static method with the same signature as the argument function of foo
> class Bar {
>     void fizz(int a) { writefln("Arg: %s", a); }
> }
>
> // An instance of class Bar
> auto bar = new Bar;
>
> // Calling foo by passing bar and the method fizz so that bar.fizz() is called when foo calls fg
> foo( ??? );
>
> Does the argument type need to be a delegate ?

It's much more simple then. You need

void foo(void delegate int() dg) {dg(5);}

and yes it must be a delegate.
May 04, 2016
Thank you Basile and Teoh.