www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Code example for function/delegate as template argument ?

reply chmike <christophe meessen.net> writes:
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 03 2016
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
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 03 2016
parent reply chmike <christophe meessen.net> writes:
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
parent Basile B. <b2.temp gmx.com> writes:
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
prev sibling next sibling parent reply Basile B. <b2.temp gmx.com> writes:
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
parent reply chmike <christophe meessen.net> writes:
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
parent reply Basile B. <b2.temp gmx.com> writes:
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
parent chmike <christophe meessen.net> writes:
Thank you Basile and Teoh.
May 04 2016
prev sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
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