Why is cref required in this nested bind example?

Hello,
Can someone please explain why a cref is needed in the last line of
the attached code snippet?
Thank you,
Chris
===
#include

On Tue, Dec 4, 2012 at 4:20 PM, Steve Lorimer
Try call the result:
Steve,
Thank you. That was pretty boneheaded of me to leave out. Another
way to get the compiler failure is to just store the result:
//function

Hi Chris, Chris Stankevitz wrote:
Can someone please explain why a cref is needed in the last line of the attached code snippet?
void f() { //bind(b, bind(a));//*1 bind(b, cref(bind(a)));//*2 }
Line *1 isn't doing the same thing as *2 -- see the documentation on nested binds [1]. In short, *1 is evaluating a() (which returns void), then attempting to pass that into the outer bind. I'm not sure if cref is an acceptable call to use there -- I don't know if it would always work. It would be more idiomatic to use protect: bind(b, boost::protect(bind(a))) All assuming that your actually case is more complicated than shown here, and can't be replaced with: bind(b, a); HTH, Nate [1]http://www.boost.org/doc/libs/1_52_0/libs/bind/bind.html#nested_binds

On Tue, Dec 4, 2012 at 4:48 PM, Nathan Crookston
//bind(b, bind(a));//*1 bind(b, cref(bind(a)));//*2
In short, *1 is evaluating a()
Thank you. This surprises me as I thought boost::bind returned an object of type boost::function. I need to understand this better and am about to go read more on this.
It would be more idiomatic to use protect:
bind(b, boost::protect(bind(a)))
I made the change, thank you. Hopefully when I understand better what boost::bind is doing (i.e. not returning a boost::function) it will be obvious why I need boost::protect. My guess is that boost::protect converts whatever boost::bind does return into a boost::function. Thanks again, Chris

On Tue, Dec 4, 2012 at 4:48 PM, Nathan Crookston
wrote: //bind(b, bind(a));//*1 bind(b, cref(bind(a)));//*2
In short, *1 is evaluating a()
Thank you. This surprises me as I thought boost::bind returned an object of type boost::function. I need to understand this better and am about to go read more on this.
The exact return type of boost::bind is unspecified. It's guaranteed to be a function object that is callable with certain arguments, so in that sense you can think of the return type as being *like* a boost::function, but it doesn't have to actually be boost::function (and in practice it won't be, because boost::function's ability to wrap any callable object incurs a performance overhead, which is not necessary for bind).
It would be more idiomatic to use protect:
bind(b, boost::protect(bind(a)))
I made the change, thank you. Hopefully when I understand better what boost::bind is doing (i.e. not returning a boost::function) it will be obvious why I need boost::protect. My guess is that boost::protect converts whatever boost::bind does return into a boost::function.
boost::protect itself just wraps the function object returned by bind() into another function object, which is callable in the same way, but is marked as being "protected". This marking is only meaningful when the function object is used as an argument to another bind expression. The outer bind expression recognizes the marking, and does a different thing based on whether it's there or not: - If the marking is there, it treats the argument like any other function object (in your case, this is the behaviour you desire). - If the marking is not there, it composes the two function objects (see [1] for details). This is an extra feature of boost::bind that allows you to accomplish something that you couldn't otherwise. protect() is provided as a means to disable this feature in cases when you just want the regular behaviour (as in your case). Hope that clears things up a bit. Regards, Nate [1] http://www.boost.org/doc/libs/1_52_0/libs/bind/bind.html#nested_binds
participants (4)
-
Chris Stankevitz
-
Nathan Crookston
-
Nathan Ridge
-
Steve Lorimer