Clang Language Extensionsによると、C++11のlambda式からBlocksポインタへの変換が自動で行われるみたいなので試してみました。
なお、確認にあたって利用したXcodeのバージョンは5.0 (5A1412)です。
簡単な例
拡張子を.mmにしておけば、lambdaで次のように書くことができます。
auto cmptr = [](id x, id y) -> NSComparisonResult { return [x compare:y]; };
auto array = @[ @"spam", @"foo", @"bar", @"bazz" ];
auto sorted = [array sortedArrayUsingComparator:cmptr];
NSLog(@"%@", [sorted componentsJoinedByString:@", "]);
//=> bar, bazz, foo, spam
なお、内部的にはこのlambdaから該当シグネチャのBlockへの変換演算子 (返されるBlockオブジェクトはlambdaへの転送だけを行う) を使うことで実現しているようです。
詳細はClang Language Extensionsの「Interoperability with C++11 lambdas」を参照ください。
複雑な例
もう少し複雑な例として、以前の記事「Objective-C上でブロックオブジェクトによる高階関数を用いてソートする方法について」と同じコードをlambdaで書き直してみました。
auto compByName = [](File* a, File* b) { return [a.name compare:b.name]; };
auto compByIName = [](File* a, File* b) { return [a.name caseInsensitiveCompare:b.name]; };
auto makeCompByDir = [](NSComparator f) {
return [f](File* a, File* b) {
BOOL adir = a.isDirectory;
BOOL bdir = b.isDirectory;
if (a.isDirectory == b.isDirectory) return f(a, b);
return (adir && ! bdir)? NSOrderedAscending : NSOrderedDescending;
};
};
auto makeCompByKind = [](NSComparator f) {
return [f](File* a, File* b) -> NSComparisonResult {
NSComparisonResult res = [a.name.pathExtension
caseInsensitiveCompare:b.name.pathExtension];
return res == NSOrderedSame? f(a, b) : res;
};
};
auto sorted = [array sortedArrayUsingComparator:makeCompByDir(makeCompByKind(compByName))];
以前の記事がARC未対応であったりしますが、上のコードと比べてもあまり代わりませんね。
ちょっと違うのは、autoを利用していることと、fを明示的にキャプチャしていることくらいでしょうか。
なお、Objective-C++にするとautoでBlocksの宣言が省略できるようになるので、個人的にはそれだけでもとても嬉しかったりします。
auto compByName = ^(id a, id b) {
return [[a name] compare:[b name]];
};
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。