generic lambda
lambda登場時から待ち望んでいた機能です。lambda引数の型を'auto'とすることで"汎用"のlambda式が書けるようになりました。
auto add = [&](const auto& t, const auto& u) { return t + u; }; cout << add(10,4) << endl; cout << add(string("じゅう"), "よん") << endl;
ただしTorinoでは暗黙のキャプチャ、すなわち[&]や[=]を使うと"本リリースではサポートされていませんゴメンナサイ"エラーとなってしまいます。generalized lambda captureと共に、ちゃんと動くようになるまでしばらくのガマンです。
resumable/await
最後に紹介するresumable/awaitは、C++17に提案されている非同期処理のためのできたてホヤホヤの機能。C#なみなさんにはasync/awaitでおなじみです。
resumable/awaitはC++/CXによるストアアプリでその有用さが実感できます。
ストアアプリでは時間のかかる処理に引きずられてUIの反応が鈍るのを徹底的に排除しています。時間のかかりそうな処理を行うAPIはことごとく、メソッド名に"~Async"が付いていて、その制御は結果が得られるのを待たずに呼び出し元に戻ってきます。"非同期処理"ってやつですね。それじゃ結果が得られたときの処理がどうするか……結果が得られたときに行う処理をコールバックに登録しておくというカラクリになっています。
「"背景色変更ボタン"が押されたらダイアログをpop-upし、好みの色をユーザに選ばせる」サンプルを書いてみました。
ボタン・クリックのハンドラはこんなコードになります。
void MainPage::OnButtonClick(Object^ sender, RoutedEventArgs^ args) { MessageDialog^ msgdlg = ref new MessageDialog(L"どの色がお好き?", L"背景色の変更"); msgdlg->Commands->Append(ref new UICommand(L"赤", nullptr, Colors::Red)); msgdlg->Commands->Append(ref new UICommand(L"緑", nullptr, Colors::Green)); msgdlg->Commands->Append(ref new UICommand(L"青", nullptr, Colors::Blue)); // Show the MessageDialog task<IUICommand^> showTask = create_task(msgdlg->ShowAsync()); showTask.then( // ShowAsyncが完了した後の処理は callback で書かにゃならん [this](IUICommand^ command) { // Get the Color value Color clr = safe_cast<Color>(command->Id); // Set the background brush contentGrid->Background = ref new SolidColorBrush(clr); } ); }
背景色変更ボタンが押されたことに反応するイベントハンドラ内のmsgdlg->ShowAsync()でダイアログがpop-upするのですが、その結果が得られることなくすぐさまShowAsync()から戻ってきてしまいます。結果が得られた(ユーザが色を選択した)時の処理(callback)はtask.then()の引数に与えているlambda式です。
この例ではさほどにややこしくはありませんが、非同期APIをいくつも呼ぶことで所望の動作を行う、例えばファイルを開けて/"一行読む"を繰り返して/ファイルを閉じるような場合、何段ものlambdaの入れ子になってしまいます。
Torinoで追加されたresumable/awaitを使うと、"見かけ上"callbackが消えてしまい、上から下に一連の処理を書きおろすことができます。
void MainPage::OnButtonClick(Object^ sender, RoutedEventArgs^ args) __resumable { MessageDialog^ msgdlg = ref new MessageDialog(L"どの色がお好き?", L"背景色の変更"); msgdlg->Commands->Append(ref new UICommand(L"赤", nullptr, Colors::Red)); msgdlg->Commands->Append(ref new UICommand(L"緑", nullptr, Colors::Green)); msgdlg->Commands->Append(ref new UICommand(L"青", nullptr, Colors::Blue)); // Show the MessageDialog IUICommand^ command = __await msgdlg->ShowAsync(); // 「ここで待ってる」かのように書きおろせる! Color clr = safe_cast<Color>(command->Id); contentGrid->Background = ref new SolidColorBrush(clr); }
resumable/awaitのアタマに付いてる'__'は、コンパイラ/ライブラリベンダー独自のもので標準ではないことを表しています。resumable/awaitはC++17に提案された機能/構文で、国際標準として正式に採用されるかは定かではなく、このままずーっと'__'が付いたままとなるかもしれません……。
以上、Visual C++の今後を垣間見ることのできるVisual C++ Compiler November 2013 CTP:Torinoの主要新機能ご紹介でした。
マイクロソフトの開発計画によれば、Visual Studio製品群は以前よりずっと短いスパンでUpdateや改版が行われるとのこと。
.NETが華やかなVisual Studioですが、C++にも頑張ってもらいたいですね。