目标C++ 11 - 为什么我们不能给 lambda 分配一个块?



所以,我刚刚升级到Xcode 4.4,我在变更日志中注意到:

Apple LLVM编译器支持额外的C++11功能,包括lambdas

太棒了!所以我开始编码,我发现了一些东西:

  1. Lambdas可分配给Objective-C块:

    void (^block)() = []() -> void { 
        NSLog(@"Inside Lambda called as block!");
    };
    block();
    
  2. std::function可以容纳Objective-C块:

    std::function<void(void)> func = ^{
        NSLog(@"Block inside std::function");
    };
    func();
    
  3. 我们不能将Objective-C块分配给lambda:

    auto lambda = []() -> {
        NSLog(@"Lambda!");
    };
    lambda = ^{ // error!
        NSLog(@"Block!");
    };
    lambda();
    

为什么会这样?考虑到我们上面所看到的,这两者在语义上不应该是等价的吗?

C++11的lambda的复制赋值运算符被显式禁用1。这不是一个"语义等价"的问题。它甚至不能分配回自己。更不用说不相关的类型了。

#include <cstdio>
#include <type_traits>
int main() {
    auto lambda1 = []() -> void { printf("Lambda 1!n"); };
    lambda1 = lambda1;  // error: use of deleted function ‘main()::<lambda()>& main()::<lambda()>::operator=(const main()::<lambda()>&)’
    return 0;
}

std::function可以容纳Objective-C块。

  • CCD_ 3可以保存任何可以作为CCD_ 4调用的类型。由于块支持"invoke运算符",它也可以由std::function持有。但请注意,Objective-C和C++遵循不同的内存管理方案,因此在std::function中长时间存储块可能会导致悬空引用

Lambdas可分配给Objective-C块:

  • 归咎于SAHC处理程序2:)。不过,它还没有记录在案

1:C++11§5.1.2/19:

lambda表达式关联的闭包类型具有已删除的(8.4.3)默认构造函数和已删除的副本赋值运算符。

2:http://llvm.org/viewvc/llvm-project?view=rev&修订版=150620

lambda有自己的实现定义的类型,这些类型特定于每个lambda。以下代码也是一个错误:

auto l1=[](){return 1;}
auto l2=[](){return 2;}
l1=l2; //Error

std::function是一个包装器,它被设计为容纳任何可调用类型;您应该使用它来保存可能具有不同类型的可调用程序。

最新更新