digitalmars.D.learn - D equivalent of C++ bind ?
- chmike (28/28) May 10 2016 Is there an equivalent in D of the C++11 std.bind template class
- rikki cattermole (19/19) May 10 2016 I know this really isn't what you want, but it may help you:
- chmike (1/1) May 10 2016 Thanks. This does the job but it's not as concise.
- =?UTF-8?B?QW5kcsOp?= (12/13) May 10 2016 I've never missed C++'s bind functionality because D has first
- Dsby (4/5) May 12 2016 The std.functional.partial can not use in runtime, only on
- Olivier Pisano (3/3) May 10 2016 Salut Christophe,
- Gary Willoughby (2/3) May 10 2016 See http://dlang.org/phobos/std_functional.html#partial
- Dsby (32/61) May 12 2016 I write one, bind functon to a delegate.
Is there an equivalent in D of the C++11 std.bind template class [http://en.cppreference.com/w/cpp/utility/functional/bind] ? Here is a blog post showing different examples of its use https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/ A possible use case is for a callback function/delegate with the expected signature bool cb(int error). I would like to pass a function bool myCb(int error, ref int myArg) instead with the variable myArg being given as predefined argument. Here is an example. ---- int count = 0; bool myCb(int error, ref int myArg) { if (myArg >= 6) return false; writeln(++myArg); return true; } void async_task(void function(int error) cb) { . . . while cb(0) . . . } void main() { . . . async_task( ??? myCb ??? count ??? ); . . . } ---- In C++ we would write async_task(std::bind(myCb, std::placeholders::_1, count));
May 10 2016
I know this really isn't what you want, but it may help you: void doFunc(int a, int b, string text) { import std.stdio : writeln; writeln(text, ": ", a, " <> ", b); } void receiver(void delegate(string text) del) { del("Hey"); } void main() { struct Binder { int a, b; void function(int, int, string) del; void call(string text) { del(a, b, text); } } Binder binder = Binder(1, 3, &doFunc); receiver(&binder.call); }
May 10 2016
Thanks. This does the job but it's not as concise.
May 10 2016
On Tuesday, 10 May 2016 at 15:33:03 UTC, chmike wrote:Thanks. This does the job but it's not as concise.I've never missed C++'s bind functionality because D has first class support for delegates. If async_task is changed to the following: void async_task(void delegate(int error) cb) { . . . while cb(0) . . . } You could just adapt a call to it using a lambda function: async_task( (error) => myCb(error, count) ); D makes sure the enclosing stack is copied to the heap and count is reachable. Maybe this helps... Regards, André
May 10 2016
On Tuesday, 10 May 2016 at 15:33:03 UTC, chmike wrote:Thanks. This does the job but it's not as concise.The std.functional.partial can not use in runtime, only on complier time. and it can not bind args that more than one.
May 12 2016
Salut Christophe, Did you have a look at https://dlang.org/phobos/std_functional.html#partial ?
May 10 2016
On Tuesday, 10 May 2016 at 09:39:53 UTC, chmike wrote:Is there an equivalent in D of the C++11 std.bind template classSee http://dlang.org/phobos/std_functional.html#partial
May 10 2016
On Tuesday, 10 May 2016 at 09:39:53 UTC, chmike wrote:Is there an equivalent in D of the C++11 std.bind template class [http://en.cppreference.com/w/cpp/utility/functional/bind] ? Here is a blog post showing different examples of its use https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/ A possible use case is for a callback function/delegate with the expected signature bool cb(int error). I would like to pass a function bool myCb(int error, ref int myArg) instead with the variable myArg being given as predefined argument. Here is an example. ---- int count = 0; bool myCb(int error, ref int myArg) { if (myArg >= 6) return false; writeln(++myArg); return true; } void async_task(void function(int error) cb) { . . . while cb(0) . . . } void main() { . . . async_task( ??? myCb ??? count ??? ); . . . } ---- In C++ we would write async_task(std::bind(myCb, std::placeholders::_1, count));I write one, bind functon to a delegate. In here: https://github.com/putao-dev/collie/blob/master/source/collie/utils/functional.d this is the code: auto bind(T,Args...)(auto ref T fun,Args args) if (isCallable!(T)) { alias FUNTYPE = Parameters!(fun); static if(is(Args == void)) { static if(isDelegate!T) return fun; else return toDelegate(fun); } else static if(FUNTYPE.length > args.length) { alias DTYPE = FUNTYPE[args.length..$]; return delegate(DTYPE ars){ TypeTuple!(FUNTYPE) value; value[0..args.length] = args[]; value[args.length..$] = ars[]; return fun(value); }; } else { return delegate(){return fun(args);}; } }
May 12 2016
On Thursday, 12 May 2016 at 10:38:37 UTC, Dsby wrote:I write one, bind functon to a delegate. In here: https://github.com/putao-dev/collie/blob/master/source/collie/utils/functional.d this is the code: auto bind(T,Args...)(auto ref T fun,Args args) if (isCallable!(T)) { alias FUNTYPE = Parameters!(fun); static if(is(Args == void)) { static if(isDelegate!T) return fun; else return toDelegate(fun); } else static if(FUNTYPE.length > args.length) { alias DTYPE = FUNTYPE[args.length..$]; return delegate(DTYPE ars){ TypeTuple!(FUNTYPE) value; value[0..args.length] = args[]; value[args.length..$] = ars[]; return fun(value); }; } else { return delegate(){return fun(args);}; } }Thank you. Would you agree to help me understand it ? The only thing I don't understand is why the function template argument is defined as T and the argument as auto ref T fun. Why the auto ref and not alias T in the template argument list ? This bind is better than Partial!() from std.functional since it accepts any number of parameters. But the given parameters are passed as first arguments of fun. The std::bind of C++ allows to bind any parameter in any order and eventually multiple times. It's really as if a new function was defined with a total liberty degree on its signature. Anyway thank you very much.
May 16 2016
On Monday, 16 May 2016 at 15:11:26 UTC, chmike wrote:On Thursday, 12 May 2016 at 10:38:37 UTC, Dsby wrote:you can remove "auto ref". and I remove the "auto ref" in my use. if used the "alias T", It can not handle all while when the T is a delegate. in C++ std::bind, the arguments order you can sort by used. in D I do not find how to enablement.[...]Thank you. Would you agree to help me understand it ? The only thing I don't understand is why the function template argument is defined as T and the argument as auto ref T fun. Why the auto ref and not alias T in the template argument list ? This bind is better than Partial!() from std.functional since it accepts any number of parameters. But the given parameters are passed as first arguments of fun. The std::bind of C++ allows to bind any parameter in any order and eventually multiple times. It's really as if a new function was defined with a total liberty degree on its signature. Anyway thank you very much.
May 16 2016
On Monday, 16 May 2016 at 15:57:52 UTC, Dsby wrote:you can remove "auto ref". and I remove the "auto ref" in my use. if used the "alias T", It can not handle all while when the T is a delegate. in C++ std::bind, the arguments order you can sort by used. in D I do not find how to enablement.Yes this doesn't look easy. Maybe by using a mixin. Unfortunately this slows down compilation. I don't know the impact on optimization. I'm not sure if converting a function to a delegate is a good thing. It is good for your use case where the bind functions are used as callbacks. But sometime, users may really want to create a function. The user should then use ToDelegate! If he wants to convert the function to a delegate. But from the the documentation, ToDelegate doesn't work with functions with the safe attribute.
May 16 2016