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

10

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

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块构造,但我不确定具体如何,因为(据我所知),它的实现没有专门处理块。它是否在隐含地提取基础函数指针?此外,这种行为是否未定义且有可能发生更改?


1
从C++的角度来看,您的std::function持有一个指向任何类似于void f(int)的东西的指针。如果这就是块的样子,它就可以工作(否则不行)。 - Bo Persson
2个回答

6

更新:我错了,这就是为什么它确实起作用的原因

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

如果不特别更新std::tr1::function以支持block,则编译应该失败,因为block必须将捕获的值counter随它一起传递。


4
只要函数签名正确,std(::tr1)::function 对于它所要调用的内容并不关心。你应该从 Objective-C 块中得到类似于一个函数对象的东西,而 std(::tr1)::function 可以很好地调用一个函数。我认为 Objective-C 块与 C++0x lambda 差不多,因为它们基本上都是函数对象,所以 std(::tr1)::function 也可以很好地操作 lambda。 :) - Xeo

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接