开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜