Why can't I use a boost::function in an Objective-C++ block?
The following code throws an exception
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_function_call> >'
what(): call to empty boost::function
at the line f()
(while executing the block):
void foo(); // assume this is defined somewhere
boost::function<void()> f = boost::bind(&foo);
^(void) {
f();
}();
However, according to the documentation on blocks,
In general you can use C++ objects within a block. Within a member function, references to member variables and functions are via an implicitly imported this pointer and thus appear mutable. There are two co开发者_如何学Cnsiderations that apply if a block is copied:
If you have a __block storage class for what would have been a stack-based C++ object, then the usual copy constructor is used.
If you use any other C++ stack-based object from within a block, it must have a const copy constructor. The C++ object is then copied using that constructor.
This seems to be true normally; if I replace f
above with an instance of a simple class with an operator()()
, the above code runs as expected.
Why doesn't the version with boost::function
work?
It appears that if I modify the declaration with __block
, it works correctly:
__block boost::function<void()> f = boost::bind(&foo);
I'm still not sure why this is - as @Richard mentions in a comment above, it must have to do with the "const copy constructor" as opposed to the "usual copy constructor". I don't know how to check this difference, though; the following works fine:
const boost::function<void()> f = boost::bind(&foo);
const boost::function<void()> g(f);
g();
and if that doesn't call a "const copy constructor", I'm not sure what will.
The example in your answer,
const boost::function<void()> f = boost::bind(&foo);
const boost::function<void()> g(f);
g();
works because you're calling operator()
in the same scope in which its callee was created. f()
would work outside of block scope as well, and calling foo()
would work inside block scope because it is a classic function and is not considered to be "modified" when it is called. The referenced call to a const copy constructor is made when passing the object from containing scope to block scope. It would appear that whatever difference exists in the const copy constructor is failing to copy part of the object through to block scope.
精彩评论