digitalmars.D.learn - Taking a function or delegate as argument.
- simendsjo (35/35) Jan 10 2012 If I want to have a method taking a callback function, I have to specify...
- Mike Parker (14/18) Jan 10 2012 The simple way:
- Mike Parker (2/20) Jan 10 2012 And of course, wrap should be calling fn(j), not function(j)!
- simendsjo (3/21) Jan 10 2012 Yeah, but a bit tedious.. I found toDelegate:
- Jacob Carlborg (5/29) Jan 10 2012 Or make it a template parameter and check if it's callable using
- simendsjo (6/35) Jan 10 2012 Like this?
- bls (14/43) Jan 10 2012 What's wrong with toDelegate ? Seems to be pretty handy.
- Jacob Carlborg (6/51) Jan 10 2012 A template parameter with a template constraint will accept any callable...
- Stewart Gordon (9/11) Jan 10 2012 Indeed, this is done in the C++ STL quite a lot.
- Jacob Carlborg (4/18) Jan 10 2012 Yeah, it all depends on what the needs are.
- Stewart Gordon (12/14) Jan 10 2012 Moreover, if you want to save the callback for later use, you need to di...
- Jacob Carlborg (4/21) Jan 10 2012 I've been doing the same thing myself.
- simendsjo (21/39) Jan 10 2012 I tried the following, but I get some error messages:
If I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons. import std.stdio, std.traits; void f(int i, void function(int) fn) { fn(i); } void d(int i, void delegate(int) dg) { dg(i); } // ugly.. void g(F)(int i, F callback) { static assert(isSomeFunction!F, "callback is not a function"); static assert(__traits(compiles, { callback(i); }), "callback does not take int as a parameter"); callback(i); } void fcb(int i) { writeln(i); } void main() { // Error: function t.f (int i, void function(int) fn) is not callable using argument types (int,void delegate(int)) // f(1, (int i) { writeln(i); }); f(2, &fcb); d(3, (int i) { writeln(i); }); //Error: function t.d (int i, void delegate(int) dg) is not callable using argument types (int,void function(int)) //d(4, &fcb); g(5, &fcb); g(6, (int i) { writeln(i); }); //g(7, 7); // not a function //g(8, (string s) { }); // does not take int as arg }
Jan 10 2012
On 1/10/2012 10:05 PM, simendsjo wrote:If I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012
On 1/10/2012 10:43 PM, Mike Parker wrote:On 1/10/2012 10:05 PM, simendsjo wrote:And of course, wrap should be calling fn(j), not function(j)!If I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012
On 10.01.2012 14:43, Mike Parker wrote:On 1/10/2012 10:05 PM, simendsjo wrote:Yeah, but a bit tedious.. I found toDelegate: http://dlang.org/phobos/std_functional.html#toDelegateIf I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012
On 2012-01-10 14:48, simendsjo wrote:On 10.01.2012 14:43, Mike Parker wrote:Or make it a template parameter and check if it's callable using std.traits.isCallable. -- /Jacob CarlborgOn 1/10/2012 10:05 PM, simendsjo wrote:Yeah, but a bit tedious.. I found toDelegate: http://dlang.org/phobos/std_functional.html#toDelegateIf I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012
On 10.01.2012 15:53, Jacob Carlborg wrote:On 2012-01-10 14:48, simendsjo wrote:Like this? void callback(F)(int i, F fn) if(isCallable!F) { fn(i); } .. but then the parameters wouldn't be documented.On 10.01.2012 14:43, Mike Parker wrote:Or make it a template parameter and check if it's callable using std.traits.isCallable.On 1/10/2012 10:05 PM, simendsjo wrote:Yeah, but a bit tedious.. I found toDelegate: http://dlang.org/phobos/std_functional.html#toDelegateIf I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012
On 01/10/2012 06:53 AM, Jacob Carlborg wrote:On 2012-01-10 14:48, simendsjo wrote:What's wrong with toDelegate ? Seems to be pretty handy. //simple snip import std.functional; int main() { int delegate( int i) dg; alias dg callback; callback = toDelegate(&test); writeln( callback( 12 ) ); readln(); return 0; } int test(int i) { return 30 +i;}On 10.01.2012 14:43, Mike Parker wrote:Or make it a template parameter and check if it's callable using std.traits.isCallable.On 1/10/2012 10:05 PM, simendsjo wrote:Yeah, but a bit tedious.. I found toDelegate: http://dlang.org/phobos/std_functional.html#toDelegateIf I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012
On 2012-01-10 20:24, bls wrote:On 01/10/2012 06:53 AM, Jacob Carlborg wrote:A template parameter with a template constraint will accept any callable type. Function pointer, delegate, struct/class overloading the call operator and so on. -- /Jacob CarlborgOn 2012-01-10 14:48, simendsjo wrote:What's wrong with toDelegate ? Seems to be pretty handy. //simple snip import std.functional; int main() { int delegate( int i) dg; alias dg callback; callback = toDelegate(&test); writeln( callback( 12 ) ); readln(); return 0; } int test(int i) { return 30 +i;}On 10.01.2012 14:43, Mike Parker wrote:Or make it a template parameter and check if it's callable using std.traits.isCallable.On 1/10/2012 10:05 PM, simendsjo wrote:Yeah, but a bit tedious.. I found toDelegate: http://dlang.org/phobos/std_functional.html#toDelegateIf I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012
On 10/01/2012 19:56, Jacob Carlborg wrote: <snip>A template parameter with a template constraint will accept any callable type. Function pointer, delegate, struct/class overloading the call operator and so on.Indeed, this is done in the C++ STL quite a lot. The drawback is that templated methods lose their virtuality, because it cannot be known in advance on what types the template will be instantiated in order to populate the vtable. FWIW my utility library includes a delegate wrapper: http://pr.stewartsplace.org.uk/d/sutil/ (dgwrap works in both D1 and D2, though other bits of the library need updating to current D2) Stewart.
Jan 10 2012
On 2012-01-11 02:05, Stewart Gordon wrote:On 10/01/2012 19:56, Jacob Carlborg wrote: <snip>Yeah, it all depends on what the needs are. -- /Jacob CarlborgA template parameter with a template constraint will accept any callable type. Function pointer, delegate, struct/class overloading the call operator and so on.Indeed, this is done in the C++ STL quite a lot. The drawback is that templated methods lose their virtuality, because it cannot be known in advance on what types the template will be instantiated in order to populate the vtable. FWIW my utility library includes a delegate wrapper: http://pr.stewartsplace.org.uk/d/sutil/ (dgwrap works in both D1 and D2, though other bits of the library need updating to current D2) Stewart.
Jan 10 2012
On 10/01/2012 19:56, Jacob Carlborg wrote: <snip>A template parameter with a template constraint will accept any callable type. Function pointer, delegate, struct/class overloading the call operator and so on.Moreover, if you want to save the callback for later use, you need to distinguish the cases. But it really just boils down to: - if it's a global or static function, wrap it in a delegate - if it's a type with static opCall, wrap class.opCall in a delegate - if it's an object with an opCall, just use &obj.opCall I've just had a look at std.functional.toDelegate and it seems it does this straight off. But the way it wraps a static function in a delegate is a lot more complicated than what my library does - is this just in order to support non-D linkage? And I see it has the same limitation of not supporting variadics. Stewart.
Jan 10 2012
On 2012-01-11 02:21, Stewart Gordon wrote:On 10/01/2012 19:56, Jacob Carlborg wrote: <snip>I've been doing the same thing myself. -- /Jacob CarlborgA template parameter with a template constraint will accept any callable type. Function pointer, delegate, struct/class overloading the call operator and so on.Moreover, if you want to save the callback for later use, you need to distinguish the cases. But it really just boils down to: - if it's a global or static function, wrap it in a delegate - if it's a type with static opCall, wrap class.opCall in a delegate - if it's an object with an opCall, just use &obj.opCall I've just had a look at std.functional.toDelegate and it seems it does this straight off. But the way it wraps a static function in a delegate is a lot more complicated than what my library does - is this just in order to support non-D linkage? And I see it has the same limitation of not supporting variadics. Stewart.
Jan 10 2012
On 10.01.2012 14:43, Mike Parker wrote:On 1/10/2012 10:05 PM, simendsjo wrote:I tried the following, but I get some error messages: h(9, (int i) { writeln(i); }); t.d(46): Error: template t.h(F) if (isCompatibleFunction!(F,void function(int))) does not match any function template declaration t.d(46): Error: template t.h(F) if (isCompatibleFunction!(F,void function(int))) cannot deduce template function from argument types !()(int,void delegate(int)) template isCompatibleFunction(Src, Dest) { static assert(isSomeFunction!Src, "Source is not a function"); static assert(isSomeFunction!Dest, "Destination is not a function"); enum bool isCompatibleFunction = is(ParameterTypeTuple!Src == ParameterTypeTuple!Dest) && is(ParameterStorageClassTuple!Src == ParameterStorageClassTuple!Dest) && is(ReturnType!Src == ReturnType!Dest); } void h(F)(int i, F callback) if(isCompatibleFunction!(F, void function(int))) { callback(i); }If I want to have a method taking a callback function, I have to specify if it should take a function or delegate even if I don't really care. What's the best way to accept either? I cannot see any wrapper for something like this in std.typecons.The simple way: void callback(int i, void delegate(int) dg) { dg(i); } void callback(int i, void function(int) fn) { void wrap(int j) { function(j); } callback(i, &wrap); }
Jan 10 2012