【问题标题】:Why does std::tr1::function work with Objective-C Blocks?为什么 std::tr1::function 可以与 Objective-C 块一起使用?
【发布时间】:2011-04-09 19:31:45
【问题描述】:

当我发现以下代码确实有效时,我感到非常惊讶:

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 块构造,但我不太确定如何,因为(上次我检查过)它的实现并没有专门处理块。它是否以某种方式隐含地吸出底层函数指针?此外,这种行为是否未定义并且可能会改变?

【问题讨论】:

  • 从 C++ 的角度来看,您的 std::function 包含一个指向任何看起来像 void f(int) 的指针。如果这是块的样子,它会起作用(否则不会)。
  • @Bavarious 感谢您的标签编辑!

标签: c++ objective-c++ objective-c-blocks


【解决方案1】:

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

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

旧的、不正确的答案(因此 cmets 有意义)

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

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 的实现已被专门更新以支持块)

【讨论】:

  • std(::tr1)::function 完全不在乎它应该调用什么,只要签名有效。您应该从该 Objective-C 块中获得类似函子的东西,并且 std(::tr1)::function 可以完美地调用函数。我认为 Objective-C 块的工作方式类似于 C++0x lambda,std(::tr1)::functions 可以很好地在 lambda 上运行,因为它们基本上是函子。 :)
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    相关资源
    最近更新 更多