为什么 std::tr1::function 可以与 Objective-C 块一起使用?

发布于 2024-10-31 06:01:08 字数 356 浏览 2 评论 0原文

当我发现以下代码实际上可以工作时,我感到非常惊讶:

std::vector<int> list /*= ...*/;
std::tr1::function<void(int)> func = ^(int i) {
  return i + 1;
};

std::for_each(list.begin(), list.end(), func);

似乎 std::tr1::function 能够从 Objective-C 块构建,但我不确定如何构建,因为(我上次检查过),它的实现并不专门处理块。它是否以某种方式隐式地吸出了底层函数指针?另外,这种行为是否未定义并且可能会改变?

I was pretty surprised when I found that the following code actually works:

std::vector<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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

澜川若宁 2024-11-07 06:01:08

更新:我错了,这就是它真正有效的原因

std::tr1::function 的模板参数只是定义了结果的签名函数对象,而不是它实际包装的类型。因此,被包装的对象只需要提供一个具有匹配签名的operator()。块引用,就像函数指针一样,隐式地具有这样的 operator() (显然,因此您可以调用它们)。

旧的、不正确的答案(所以评论是有道理的)

我强烈怀疑它的工作原理,因为该块没有捕获周围范围的任何变量。在这种情况下,无需维护状态,因此块引用可以表示为裸函数指针。如果我们更改代码,

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);

它应该无法编译,因为该块必须携带捕获的 counter 值。 (当然,除非 std::tr1::function 的实现已专门更新为支持块)

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)

毁梦 2024-11-07 06:01:08

尽管您可以将块视为 Objective-C 对象,并且 Objective-C 对块有很多支持,但块并不限于 Objective-C。您还可以在 C 和 C++ 中使用块。请参阅本文了解更多信息。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文