オブジェクトの互換性はなく、 obj-c のクラスを C++ で継承したりその逆はできないみたいですが、それ以外のことは一通りできており、 C++ で設計、記述したクラスに実に自然に mac の GUI を被せることができて結構感動したものです。
もうこれでくだらない glue を沢山書かなくていいんだ!
それはそれで大変素晴らしいことなのですが、それでは C++11 ではどうなのかというところが気になりました。
気になる事は試してみましょう。
まず、 clang で C++11 を有効にするには -std=c++11 をつけてコンパイルします。
更に、 C++11 の新しい標準ライブラリを使うには -stdlib=libc++ をつけます。
libstdc++ とかではありません。
cmake でいうとこうです。
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")ただ一つ問題があります。
cmake の project に .m が混在しているとこれはエラーになってしまいます。
.mm だけならば問題ありません。 project を別けるかしましょう。
無論、自分で makefile を書くならば suffix ルールを別けるだけで済みます。
まぁ、全部 .mm にしちゃいましょう。
これで準備は完了です。
界面に関わらないことであれば、概ね C++11 の機能が使えるようです。
クロージャ
C++ のコンテキストでクロージャを呼び出すことは難なくできました。これを obj-c のメソッドに渡すことを考えてみましょう。
Test::foobar というクロージャを受け取って呼び出す obj-c のクラスを考えます。
Test* test = [Test alloc];
const char* msg = "Hello";
[test foobar:[msg](){printf ("%s\n", msg);}];太字がクロージャであります。
Test の実装はこんな感じ。
@interface Test : NSObject結果は以下の通り。
@end
@implementation Test
- (void) foobar:(std::function< void(void) >)closure
{
printf("call begin\n");
closure();
printf("call end\n");
}
@end
call begin問題なく受け渡すことができました。
Hello
call end
__attribute__
クロージャが使えるならかなり色々なことができそうです。界面に関わるうち、構文上どうにもならなそうなもの以外(例えば obj-c メソッドのシグネチャでrvalue 制約や型推論を使う等)は一通り使えそうです。
構文上厳しそうなものといえば [[]] による __attribute__ です。
GNU 拡張の __attribute__ ディレクティブを、 clang は理解しますが、折角仕様に盛り込まれたのだからそっちを使ったほうがいいです(もっとも、 no_inline だけは効いてくれたことがないですが)。
でもこいつは [] で括る obj-c の文法と相性が悪そうです。
float vec4 [[align(4)]] [1];
float vec8 [[align(8)]] [1];
float vec16 [[align(16)]] [1];
printf("vec4:%p vec8:%p vec16:%p\n", vec4, vec8, vec16);一応コンパイルは通りました。ですが実行結果は以下の通り。
vec4:0x7fff5fbfee78 vec8:0x7fff5fbfee74 vec16:0x7fff5fbfee70手元の clang では残念ながら [[align(x)]] 自体が動いていないようです。
gcc-4.9 では大丈夫だったように思うのですが。
まぁ、使えるんじゃないですかね?(鼻をほじりながら)
0 件のコメント:
コメントを投稿