Why does std::tr1::function work with Objective-C Blocks?
I was pretty surprised when I found that the following code actually works:
std::vecto开发者_如何学Gor<int> list /*= ...*/;
std::tr1::function<void(int)> func = ^(int i) {
return i + 1;
};
std::for_each(list.begin(), list.end(), func);
Seems like std::tr1::function
is capable of being constructed from an Objective-C block, but I'm not sure quite how, since (last I checked), its implementation doesn't specifically handle blocks. Is it somehow implicitly sucking out the underlying function pointer? Also, is this behavior undefined and likely to change?
Update: I was wrong, here's why it really works
std::tr1::function
's template parameter simply defines the signature of the resulting function object, not the type it actually wraps. Thus, the wrapped object only needs to offer an operator()
with matching signature. Block references, like function pointers, have such an operator()
implicitly (obviously, so you can call them).
Old, incorrect answer (so the comments make sense)
I strongly suspect it works because the block doesn't capture any variables from the surrounding scope. In that case, there is no state to maintain, so a block reference can be represented as a bare function pointer. If we change the code to
std::vector<int> list /*= ...*/;
int counter = 0;
std::tr1::function<void(int)> func = ^(int i) {
counter++;
return i + counter;
};
std::for_each(list.begin(), list.end(), func);
it should fail to compile, as the block must carry the captured value of counter
around with it. (unless of course the implementation of std::tr1::function
has been specifically updated to support blocks)
Although you can treat blocks as Objective-C objects and Objective-C has a lot of support for blocks, blocks aren't limited to Objective-C. You can also use blocks in C and C++. See this article for more information.
精彩评论