16

そのため、Xcode 4.4 にアップグレードしたところ、変更ログで次のことに気付きました。

Apple LLVM コンパイラは、ラムダを含む追加の C++11 機能をサポートします

これは素晴らしいです!そこでコーディングに取り掛かり、いくつかのことを発見しました。

  1. ラムダは、Objective-C ブロックに割り当て可能です。

    void (^block)() = []() -> void { 
        NSLog(@"Inside Lambda called as block!");
    };
    
    block();
    
  2. std::functionObjective-C ブロックを保持できます。

    std::function<void(void)> func = ^{
        NSLog(@"Block inside std::function");
    };
    
    func();
    
  3. Objective-C ブロックをラムダに割り当てることはできません。

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

どうしてこれなの?上で見たことを考えると、この 2 つは意味的に同等であるべきではないでしょうか?

4

2 に答える 2

15

C++11 のラムダのコピー代入演算子は明示的に無効になっています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::functionObjective-C ブロックを保持できます。

  • std::functionとして呼び出すことができる任意の型を保持できますf(a,b,c,...)。ブロックは「呼び出し演算子」をサポートしているため、 . によって保持することもできますstd::function。ただし、Objective-C と C++ は異なるメモリ管理スキームに従っていることに注意してください。そのため、ブロックを にstd::function長時間格納すると、ダングリング参照が発生する可能性があります。

ラムダは、Objective-C ブロックに割り当て可能です。

  • SAHChandler 2のせいです:)。ただし、まだ文書化されていません。

1 : C++11 §5.1.2/19:

ラムダ式に関連付けられたクロージャー型には、削除された (8.4.3) デフォルト コンストラクターと削除されたコピー代入演算子があります。

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

于 2012-07-26T12:47:44.243 に答える
3

ラムダには、各ラムダに固有の独自の実装定義型があります。次のコードもエラーです。

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

std::function呼び出し可能な型を保持するように設計されたラッパーです。それを使用して、異なるタイプの呼び出し可能オブジェクトを保持する必要があります。

于 2012-07-26T12:46:24.393 に答える