Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

ゲーム開発者のための C++11/C++14

第14回 全ゲ連での講演資料です。 Twitter: @Reputeless

  • Loggen Sie sich ein, um Kommentare anzuzeigen.

ゲーム開発者のための C++11/C++14

  1. 1. Ryo Suzuki @Reputeless 2013.9.14 全日本学生ゲーム開発者連合(全ゲ連) 第 14 回交流会 v1.03 Siv3D 開発者 早稲田大学
  2. 2. 1 2𝜋𝜎2 𝑒𝑥𝑝 − 𝑥 − 𝜇 2 2𝜎2 正規分布とゲーム
  3. 3. 正規分布とゲーム
  4. 4. 正規分布とゲーム
  5. 5. 正規分布とゲーム
  6. 6. ゲームで現実味のある ランダムな結果をつくるとき 正規分布が役に立つ 正規分布とゲーム
  7. 7. C++11では正規分布する乱数を 簡単につくる機能が追加
  8. 8. A Proposal to Add an Extensible Random Number Facility to the Standard Library (Revision 2) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1452.html
  9. 9. ゲーム開発者にとって 優しく便利になった最新の C++
  10. 10. 最新の C++ でゲーム開発を するための 14 のガイドライン
  11. 11. C++ の進化
  12. 12. C++98 major C++03 bug fix only C++11 major C++14 minor C++17 major C++11 は 13 年ぶりのアップデート
  13. 13. C++11/14 での進化 • コードを短く簡単にする • 間違いやすさを減らす • 実行時性能を向上させる • 機能を増やす
  14. 14. Visual Studio は 着実に C++11/14 に対応 2010. 4 2010 auto, move, nullptr lamdas, <random> 2012. 9 2012 Range-based for, enum class <chrono> , <ratio>. <thread> 2013. 6 2013 Preview Variadic templates initializer_lists, C++14 libs 2013. 9 2013 RC Non-static data member init defaulted / deleted functions 2013. 11 2013 2013 Q4 2013 + CTP constexpr, noexcept C++14 generic lamdas
  15. 15. Visual Studio 2010/2012/2013 でサポートされている機能を対象
  16. 16. 最新の C++ でゲーム開発を するための 14 のガイドライン
  17. 17. 新しい 乱数ライブラリを 使おう 1.
  18. 18. <random> ヘッダの乱数エンジンは高品質 な乱数生成器を提供する 適切な分布クラスを定義することで、乱数 の型、範囲、分散のしかたを簡単にコント ロールできる 要約
  19. 19. 従来の rand() の欠点 • 最大値が 32767 と小さい (Visual Studio) • 偏りが生じやすい • 型や分布を柔軟に指定できない
  20. 20. 新しい乱数ライブラリ <random> ヘッダに定義 乱数エンジン メルセンヌ・ツイスター法や ハードウェアエントロピーによる乱数生成器 分布クラス 乱数の型と範囲、分散方法を定義
  21. 21. mt19937 rng; for (int i=0; i<10; ++i) cout << rng() << '¥n'; 乱数エンジン [1/3] メルセンヌ・ツイスター法による乱数生成
  22. 22. mt19937 rng(123456); for (int i=0; i<10; ++i) cout << rng() << '¥n'; 乱数エンジン [2/3] 乱数のシード値を指定
  23. 23. random_device rng; for (int i=0; i<10; ++i) cout << rng() << '¥n'; 乱数エンジン [3/3] ハードウェア・エントロピー・ソースを 基にした予測不能な乱数生成
  24. 24. 乱数生成器の比較 乱数の質 速度 rand() 低い 早い mt19937 優秀 早い random_device 真の乱数 遅い
  25. 25. mt19937 rng{ random_device()() }; for (int i=0; i<10; ++i) cout << rng() << '¥n'; 乱数エンジンの工夫 random_device で mt19937 のシード作成
  26. 26. mt19937 rng; uniform_int_distribution<int> dist(1,6); for (int i=0; i<10; ++i) cout << dist(rng) << '¥n'; // 3 1 3 6 5 2 6 ... 整数の一様分布 指定した範囲の整数が等確率で出現
  27. 27. mt19937 rng; uniform_real_distribution<double> dist(-100.0,100.0); for (int i=0; i<10; ++i) cout << dist(rng) << '¥n'; // 62.9447 -72.90463 81.15846 ... 実数の一様分布 指定した範囲の実数が等確率で出現
  28. 28. ベルヌーイ分布 指定した確率で true が出現 mt19937 rng; bernoulli_distribution dist(0.5); if (dist(rng)) cout << "おもて¥n"; else cout << "うら¥n";
  29. 29. 正規分布 平均 μ, 標準偏差 σ の正規分布に したがって値が出現 mt19937 rng(); normal_distribution<double> dist(170.0,6.0); for (int i=0; i<10; ++i) cout << dist(rng) << '¥n';
  30. 30. 0.000…% の 異常値を避けるために 適切にクランプする 正規分布の注意 3m級の巨人
  31. 31. <random> ヘッダの乱数エンジンは高品質 な乱数生成器を提供する 適切な分布クラスを定義することで、乱数 の型、範囲、分散のしかたを簡単にコント ロールできる 復習
  32. 32. 型の宣言は autoに任せよう 2.
  33. 33. 長い型名や、わかりにくい型名は auto を使って省略しよう auto を使っていて const や参照型が欲し い場合は、const や & を記述すること 要約
  34. 34. auto x = 5; // int auto y = 3.5f; // float auto z = sin(3.14); // double // 実際は上記のような単純な場面では // 読みにくくなるので使うべきでない auto [1/4] 宣言した変数の型を右辺の 初期化子から静的に推論
  35. 35. vector<int>::iterator i = max_element(v.begin(),v.end()); map<string,pair<int,string>>::iterator k = m.find("key"); auto [2/4] 長い型名を省略する
  36. 36. auto [3/4] 長い型名を省略する auto i = max_element(v.begin(),v.end()); auto k = m.find("key");
  37. 37. const auto x = 5; // const int vector<vector<int>> vv(10); auto a = vv[0]; // vector<int> auto& b = vv[0]; // vector<int>& const auto& c = vv[0]; // const vector<int>& auto [4/4] const 修飾や参照の宣言
  38. 38. 長い型名や、わかりにくい型名は auto を使って省略しよう auto を使っていて const や参照型が欲し い場合は、const や & を記述すること 復習
  39. 39. 範囲ベースの ループを使おう 3.
  40. 40. 範囲ベースのループを使うと、単純なルー プを短く記述できる ループカウンタのような不必要な変数を減 らし、コードの意図をより明確にしよう 要約
  41. 41. int scores[5] = {40,80,90,60,100}; for (auto& score : scores) score += 10; for (const auto score : scores) cout << score << '¥n'; // 50 90 100 70 110 範囲ベース for ループ [1/5] 単純な for ループを短くできる
  42. 42. 範囲ベース for ループ [2/5] イテレーターを返す begin() / end() メンバ関数を持っていれば使える vector<int> v; list<double> li; string str; for (auto n : v) cout << n << '¥n'; for (auto x : li) cout << x << '¥n'; for (auto ch : str) cout << ch << '¥n';
  43. 43. vector<Widget> widgets; for (auto& widget : widgets) widget.update(); for (const auto& widget : widgets) widget.draw(); 範囲ベース for ループ [3/5] コピーを避けたい場合は参照で
  44. 44. 範囲ベース for ループ [4/5] 二重ループの改善例 double matrix[4][4] = { ... }; for (int i=0; i<4; ++i) { for (int k=0; k<4; ++k) cout << matrix[i][k] << ','; cout << '¥n'; }
  45. 45. double matrix[4][4] = { ... }; for (const auto& row : matrix) { for (const auto elem : row) cout << elem << ','; cout << '¥n'; } 範囲ベース for ループ [5/5] 二重ループの改善例
  46. 46. 範囲ベースのループを使うと、単純なルー プを短く記述できる ループカウンタのような不必要な変数を減 らし、コードの意図をより明確にしよう 復習
  47. 47. ラムダ式を使おう 4.
  48. 48. ラムダ式で関数オブジェクトをローカルに 定義し、アルゴリズムを読みやすくしよう キャプチャを使うと外部の変数をラムダ式 の中で使用できる 要約
  49. 49. アルゴリズムは便利だ [1/3] count_if find_if remove_if for_each generate sort ... 第 3 引数に関数
  50. 50. bool IsEven(int n) { return n%2==0; } vector<int> v; // 偶数の要素を数える size_t x = count_if(v.begin(),v.end(), IsEven); アルゴリズムは便利だ [2/3]
  51. 51. struct IsEven : unary_function<int,bool> { result_type operator() (argument_type n) const { return n%2==0; }}; // 関数オブジェクトは関数ポインタより // インライン化されやすい vector<int> v; size_t x = count_if(v.begin(),v.end(), IsEven()); アルゴリズムは便利だ [3/3]
  52. 52. 述語関数が面倒だ 使う場所と定義する場所が離れている 関数オブジェクトは記述が長い これを解決するのがラムダ式
  53. 53. size_t x = count_if(v.begin(),v.end(), [](int n){ return n%2==0; }); ラムダ式 [1/4]
  54. 54. size_t x = count_if(v.begin(),v.end(), [](int n){ return n%2==0; }); ラムダ式 [2/4] [] () ->T {} で構成される [] キャプチャリスト () 引数 ->T 戻り値の型(省略可) {} 関数の本体
  55. 55. size_t x = count_if(v.begin(),v.end(), [](int n){ return n%2==0; }); ラムダ式 [3/4] ラムダ式は、相当する関数オブジェクトを 自動で作る 可読性とパフォーマンスに優れる
  56. 56. auto Square = [](int n){ return n*n; }; cout << Square(9) << '¥n'; // 81 ラムダ式で遊ぼう [1/7]
  57. 57. auto PrintSquare = [](int n){ cout << n*n << '¥n'; }; PrintSquare(100); // 10000 ラムダ式で遊ぼう [2/7]
  58. 58. const int ar[4] = { 1, 2, 3, 4 }; for_each(begin(ar),end(ar), [](int n){ cout << n*n << ' '; }); // 1 4 9 16 ラムダ式で遊ぼう [3/7]
  59. 59. const int ar[4] = { 1, 2, 3, 4 }; const int x = 10; for_each(begin(ar),end(ar), [=](int n){ cout << n*x << ' '; }); // [=] により、ラムダ式内の x は // 外部からコピーキャプチャ // 10 20 30 40 ラムダ式で遊ぼう [4/7]
  60. 60. const int ar[4] = { 1, 2, 3, 4 }; int sum = 0; for_each(begin(ar),end(ar), [&](int n){ sum += n; }); // [&] により、ラムダ式内の sum は // 外部から参照キャプチャ cout << sum << '¥n'; // 10 ラムダ式で遊ぼう [5/7]
  61. 61. vector<Vec2> pts; // 原点に近い順にソート sort(pts.begin(),pts.end(), [](const Vec2& a, const Vec2& b) { return a.lengthSq()<b.lengthSq(); } ); ラムダ式で遊ぼう [6/7]
  62. 62. vector<Enemy> enemies; int threshold = 20; // HP が threshold 未満の敵を削除 enemies.erase(remove_if( enemies.begin(),enemies.end(), [=](const Enemy& enemy) { return enemy.hp < threshold; }), enemies.end() ); ラムダ式で遊ぼう [7/7]
  63. 63. ラムダ式で関数オブジェクトをローカルに 定義し、アルゴリズムを読みやすくしよう キャプチャを使うと外部の変数をラムダ式 の中で使用できる 復習
  64. 64. Emplacementの 使い所を知ろう 5.
  65. 65. オブジェクトの構築とコンテナへの追加を 同時に行う場合は Emplacement を使おう 適切な場面で使えば push_back に比べて 要素追加のコストを減らせる 要約
  66. 66. vector<Point> v; v.push_back(Point(5,10)); push_back() のコスト 5 10 COPY
  67. 67. vector<Point> v; v.emplace_back(5,10); emplace_back() 5 10
  68. 68. Emplacement [1/2] 要素のコンストラクタ引数を受け取り、コ ンテナ内でオブジェクトを構築する 一時オブジェクトのコピーと破棄のコスト が発生しない 5 10
  69. 69. Emplacement [2/2] vector, deque, map などのコンテナの Emplacement 挿入関数 push_back() → emplace_back() push_front() → emplace_front() insert() → emplace()
  70. 70. 要素追加の使い分け [1/2] vector<T> などに対して push_back() T 型の値 (lvalue / rvalue), { initializer-lists } emplace_back() それ以外の型, 0 個 もしくは 2 個以上の引数
  71. 71. string GetString(); const string str = "Hello"; vector<string> v; v.push_back(str); v.push_back(GetString()); v.push_back({ str[0], 'e'}); v.emplace_back("hello"); v.emplace_back(); v.emplace_back(10,'a'); 要素追加の使い分け [2/2]
  72. 72. オブジェクトの構築とコンテナへの追加を 同時に行う場合は Emplacement を使おう 適切な場面で使えば push_back に比べて 要素追加のコストを減らせる 復習
  73. 73. 強く型付けされた enumを使おう 6.
  74. 74. enum class は enum の強化版で、強い型付 けとスコープを持つ enum class を使えば、整数型への暗黙的な 変換や、列挙子の名前の衝突を防げる 要約
  75. 75. void SetColor(unsigned); enum Team { Red, White }; const unsigned red = 0xffFF0000; SetColor(red); SetColor(Red); // ? 従来の enum の問題点 [1/2] 整数型に暗黙的に変換できるため、 意図しない振る舞いが可能
  76. 76. struct Team { enum { Red, White }; }; struct Palette { enum { Red, Green, Blue }; }; 従来の enum の問題点 [2/2] 名前の衝突を防ぐために スコープを作る必要がある
  77. 77. enum class name : type { enumerator = constexpr, enumerator = constexpr, ... }; enum struct name : type { enumerator = constexpr, enumerator = constexpr, ... }; enum class [1/4] 強い型付けとスコープを持つ列挙型
  78. 78. enum class Team { Red, White }; enum class Month { January = 1, February, ... }; enum class Align : char { Left = 'L', Center = 'C', Right = 'R', }; enum class [2/4]
  79. 79. enum class Team { Red, White }; enum class Palette { Red, Green, Blue }; const Team team = Team::Red; switch (palette) { case Palette::Red : break; case Palette::Green : ... } enum class [3/4] 列挙型名のスコープを持つ
  80. 80. void SetColor(unsigned); enum class Team { Red, White }; const unsigned red = 0xffFF0000; SetColor(red); SetColor(Team::Red); // error const int white = Team::White; // error enum class [4/4] 整数型へ暗黙的に変換されない
  81. 81. enum class は enum の強化版で、強い型付 けとスコープを持つ enum class を使えば、整数型への暗黙的な 変換や、列挙子の名前の衝突を防げる 復習
  82. 82. arrayを活用しよう 7.
  83. 83. array は通常の配列にオーバーヘッド無し でコンテナのインタフェースを提供する array のインタフェースが有効な場面では、 積極的に活用しよう 要約
  84. 84. 配列と array [1/2] 配列はインタフェースが貧弱 const int size = 100; int ar[size]; for (int i=0; i<size; ++i) ar[i] = 10 * i;
  85. 85. 配列と array [2/2] <array> ヘッダの array を使おう array<int,100> ar; for (size_t i=0; i<ar.size(); ++i) ar[i] = 10 * i;
  86. 86. array [1/2] 通常の配列にコンテナのインタフェースを 与えたラッパー size(), at(), begin(), end(), fill() などのメンバ関数を提供 サイズはコンパイル時に決まり、パフォー マンスは通常の配列と変わらない
  87. 87. array [2/2] array<int,5> a = { 5, 10, 15, 20, 25 }; array<int,5> b; b.fill(100); // 要素を全部 100 に a = b; // 要素数が同じなら代入可能 a[0] = 0; for (const auto n : a) cout << n << '¥n';
  88. 88. array は通常の配列にオーバーヘッド無し でコンテナのインタフェースを提供する array のインタフェースが有効な場面では、 積極的に活用しよう 復習
  89. 89. NULLをnullptrに 置き換えよう 8.
  90. 90. ヌルポインタを表す NULL と 0 を nullptr に置き換えよう ヌルポインタの意図が明確になり、オー バーロードのトラブルを防げる 要約
  91. 91. ヌルポインタ [1/3] NULL #define NULL 0 と定義される、単なる数値の 0 nullptr あらゆるポインタ型のヌルポインタを 表すポインタ定数のキーワード 整数には変換できない C++98
  92. 92. ヌルポインタ [2/3] NULL はトラブルの元 void f(int n); void f(const char* s); f(0); f("hello"); f(NULL); // f(int)
  93. 93. ヌルポインタ [3/3] nullptr でオーバーロードを正確に void f(int n); void f(const char* s); f(0); f("hello"); f(nullptr); // f(const char*)
  94. 94. ヌルポインタを表す NULL と 0 を nullptr に置き換えよう ヌルポインタの意図が明確になり、オー バーロードのトラブルを防げる 復習
  95. 95. 右辺値参照を 理解しよう 9.
  96. 96. 右辺値参照と Move セマンティクスによっ て、サイズが大きいオブジェクトのコピー のパフォーマンスが向上する 自分で定義したクラスにも、必要なら Move セマンティクスを実装できる 要約
  97. 97. vector<int> GetVector(); void GetVector(vector<int>& v); vector<int> v = GetVector(); // コピーが発生 GetVector(v); // ok 右辺値参照と Move [1/5] むかーしむかし、大きなオブジェクトを返 す関数は御法度だった
  98. 98. vector<int> GetVector(); void GetVector(vector<int>& v); vector<int> v = GetVector(); // ok GetVector(v); // ok 右辺値参照と Move [2/5] 今はそんなことはない
  99. 99. 右辺値参照と Move [3/5] ptr1 ptr2 コピー完了後に破棄 コピー これまで C++98
  100. 100. 右辺値参照と Move [4/5] ptr1 ptr1 所有権を移動 (Move セマンティクス) これから nullptr
  101. 101. 右辺値参照と Move [5/5] 右辺値 名前のない一時オブジェクト 右辺値参照 (Type&& x) 右辺値を受け取るオーバーロード std::move() 関数 左辺値を右辺値にキャスト
  102. 102. 右辺値参照 実装例 1 struct BigData { BigData(); BigData(const BigData&); BigData(BigData && data) : m_p(data.m_p),m_size(data.m_size) { data.m_p = nullptr; data.m_size = 0; } ~BigData(); int* m_p; int m_size; };
  103. 103. 右辺値参照 実装例 2 struct BigData { BigData(); BigData(const BigData&); BigData(BigData && data) : m_data(move(data.m_data)) { } vector<int> m_data; };
  104. 104. 右辺値参照と Move セマンティクスによっ て、サイズが大きいオブジェクトのコピー のパフォーマンスが向上する 自分で定義したクラスにも、必要なら Move セマンティクスを実装できる 復習
  105. 105. スマートポインタは 補助関数で作ろう 10.
  106. 106. オブジェクトのポインタはスマートポイン タで管理しよう スマートポインタは補助関数で作って、パ フォーマンスの利得と、記述の一貫性を得 よう 要約
  107. 107. さらば new と delete [1/5] new と delete は危険 int* pArray = new int[10000]; delete[] pArray; // 取扱注意
  108. 108. さらば new と delete [2/5] 動的配列は vector か string vector<int> v(10000); string str;
  109. 109. さらば new と delete [3/5] 単一のデータのポインタは・・・ Enemy* pEnemy = new Boss; delete pEnemy;
  110. 110. さらば new と delete [4/5] スマートポインタを使う shared_ptr<Enemy> pEnemy = new Boss; // 自動的に delete してくれる // まだ最適化可能
  111. 111. unique_ptr<Enemy> pEnemy = new Boss; // 自動的に delete してくれる さらば new と delete [5/5] ポインタをコピーしない場合、 unique_ptr を使えばゼロオーバーヘッド
  112. 112. 補助関数 [1/2] スマートポインタは補助関数で作ろう make_shared<T> オブジェクトと管理用データを一緒に 連続領域に new するので効率的 make_unique<T> 名前の一貫性、new の記述が不要に
  113. 113. 補助関数 [2/2] shared_ptr<Enemy> pEnemy = make_shared<Boss>(); unique_ptr<Enemy> pEnemy2 = make_unique<Boss>();
  114. 114. オブジェクトのポインタはスマートポイン タで管理しよう スマートポインタは補助関数で作って、パ フォーマンスの利得と、記述の一貫性を得 よう 復習
  115. 115. Transparent operator functors を使おう 11.
  116. 116. 将来起こりそうな問題は? vector<unsigned> v { 10, 50, 20, 30 }; sort(v.begin(),v.end(), greater<unsigned>());
  117. 117. 将来起こりそうな問題は? vector<unsigned> v { 10, 50, 20, 30 }; sort(v.begin(),v.end(), greater<unsigned>()); vector<int> v { -10, 50, 20, 30 }; sort(v.begin(),v.end(), greater<unsigned>()); // oops!
  118. 118. Transparent operator functors vector<unsigned> v { 10, 50, 20, 30 }; sort(v.begin(),v.end(),greater<>()); 比較・算術用クラステンプレート [less, greater, plus, multiplies …] を テンプレート実引数なしで使える
  119. 119. <functional> ヘッダの関数オブジェクト をテンプレート実引数なしで使おう 単に記述が短いだけでなく、型を変更した 際のトラブルを防げる 復習
  120. 120. 古いイディオムを 捨てよう 12.
  121. 121. これまでのイディオムを新しい C++ の機 能で置き換えられないか再確認しよう C++11/14 はよりシンプルで、高速、安全 な代替手段を提供しているかもしれない 要約
  122. 122. shrink to fit vector<int> v; vector<int>(v).swap(v); vector<int> v; v.shrink_to_fit();
  123. 123. 配列の範囲 int a[] = { 5, 3, 6, 8, 2 }; const int size = sizeof(a)/sizeof(a[0]); sort(a,a+size); int a[] = { 5, 3, 6, 8, 2 }; sort(begin(a),end(a));
  124. 124. Safe bool /* Safe bool は operator bool を定義した オブジェクトの無意味な比較を防ぐ。実装省略 */ struct Something { explicit operator bool() const; };
  125. 125. コンパイル時 assert #define ASSERT_CONCAT_(a, b) a##b #define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) #define STATIC_ASSERT(e,m) ¥ enum{ASSERT_CONCAT(static_assert_,__COUNTER__)=1/(!!(e))} STATIC_ASSERT(sizeof(int)==4,"xxxx"); static_assert(sizeof(int)==4,"xxxx");
  126. 126. これまでのイディオムを新しい C++ の機 能で置き換えられないか再確認しよう C++11/14 はよりシンプルで、高速、安全 な代替手段を提供しているかもしれない 復習
  127. 127. 新しい アルゴリズムを 知ろう 13.
  128. 128. <algorithm> ヘッダの新しいアルゴリズム 関数を知ろう ちょっとした操作やループを、これまでよ り短く、早いコードで書けるようになる 要約
  129. 129. const int a = 5, b = 10, c = 50, d = 20; const int smallest = min(min(min(a,b),c),d); // 5 const int largest = max(max(max(a,b),c),d); // 50 最小/最大値の取得 3 つ以上の変数に対しては 何重もの min() / max() が必要
  130. 130. const int a = 5, b = 10, c = 50, d = 20; const int smallest = min({ a, b, c, d }); // 5 const int largest = max({ a, b, c, d }); // 50 最小/最大値の取得 initializer-list で複数の値を渡す
  131. 131. int a = 25, b = 30; const int smaller = min(a,b); // 25 const int larger = max(a,b); // 30 最小/最大値を同時に取得 min() と max() で比較演算が 2 回必要
  132. 132. int a = 25, b = 30; // results は pair<int,int> 型 const auto results = minmax(a,b); const int smaller = results.first; // 25 const int larger = results.second; // 30 最小/最大値を同時に取得 minmax() で比較演算が 1 回に
  133. 133. int a[100]; // {0,1,2,3,...} で初期化したい vector<int> v(50); // {1000,1001,...} for (int i=0; i<100; ++i) a[i] = i; for (size_t i=0; i<v.size(); ++i) v[i] = i + 1000; 配列に連続した値を代入 ループが必要
  134. 134. int a[100]; // {0,1,2,3,...} vector<int> v(50); // {1000,1001,...} iota(begin(a),end(a),0); iota(v.begin(),v.end(),1000); 配列に連続した値を代入 iota() アルゴリズムを使おう
  135. 135. const int maxVal = 500; // 500円まで bool ruleKept = true; for (size_t i=0; i<v.size(); ++i) { if (v[i] > maxVal) { ruleKept = false; break; } } 全要素の条件チェック ループが必要
  136. 136. const int maxVal = 500; const bool ruleKept = all_of(v.begin(),v.end(), [=](int n){ return n<=maxVal; }); 全要素の条件チェック all_of() アルゴリズムを使おう
  137. 137. const int maxVal = 500; const bool ruleBroken = any_of(v.begin(),v.end(), [=](int n){ return n>maxVal; }); const bool ruleKept = none_of(v.begin(),v.end(), [=](int n){ return n>maxVal; }); 全要素の条件チェック 文脈に応じて any_of() , none_of アルゴリズムも使おう
  138. 138. vector<int> v { 1, 2, 3, 4, 5, 6, 7 }; shuffle(v.begin(), v.end(), mt19937(random_device()())); 要素をランダムに並び替え shuffle() アルゴリズムと 乱数エンジンを使おう
  139. 139. <algorithm> ヘッダの新しいアルゴリズム 関数を知ろう ちょっとした操作やループを、これまでよ り短く、早いコードで書けるようになる 復習
  140. 140. 新しいライブラリを 知ろう 14.
  141. 141. 新しく追加されたライブラリによって、こ れまで難しかった処理や高速なデータ管理 が可能になる 要約
  142. 142. const auto start = chrono::system_clock::now(); // 何らかの処理 const auto end = chrono::system_clock::now(); const chrono::duration<double> elapsed = end - start; cout << "経過時間: " << elapsed.count() << "秒¥n"; <chrono> [1/2] 時間の測定
  143. 143. const chrono::minutes min(5); const chrono::seconds sec(15); // 型は std::chrono::seconds const auto result = min + sec; cout << result.count() << '¥n'; // 315 <chrono> [2/2] 時間の計算と単位の変換
  144. 144. string s = "Hello C++11, C++14 & C++1y!"; const regex e("C¥¥+¥¥+[0-9][0-9a-z]"); smatch m; while (regex_search(s,m,e)) { cout << m[0] << '¥n'; s = m.suffix().str(); } // C++11 C++14 C++1y <regex> [1/2] 正規表現にマッチする文字列の検索
  145. 145. const string s = "C++11, C++14 and C++1y"; const regex e("¥¥d"); cout << regex_replace(s,e,"[$&]") << '¥n'; // C++[1][1], C++[1][4] and C++[1]y <regex> [2/2] 正規表現を使った文字列の置換
  146. 146. tuple<string,int,char> GetStudent() { return make_tuple("John", 86, 'B'); } const auto student = GetStudent(); cout << get<0>(student) << '¥n' << get<1>(student) << '¥n' << get<2>(student) << '¥n'; <tuple> 複数の型をまとめて 1 つの型を作る
  147. 147. unordered_set<string> s = { "C++", "Java", "Ruby", "PHP" }; s.emplace("Haskell"); if (s.find("C#") == s.end()) cout << "not found¥n"; <unordered_set> O(1) で要素にアクセスできる、 ハッシュを使った非順序 set
  148. 148. unordered_map<string,int> m { { "C++98", 1998 }, { "C++11", 2011 } }; m.emplace("C++14",2014); cout << m["C++11"] << '¥n'; // 2011 <unordered_map> O(1) で要素にアクセスできる、 ハッシュを使った非順序 map
  149. 149. 新しく追加されたライブラリによって、こ れまで難しかった処理や高速なデータ管理 が可能になる 復習
  150. 150. 今日紹介したのは、 新しい C++ の一部分
  151. 151. 追加資料 1 Visual C++ で使える C++11 by @nekko1119 さん http://www.slideshare.n et/nekko1119/c11-in- visual-c
  152. 152. 追加資料 2 C++14 Overview by @cpp_akira さん http://www.slideshare.n et/faithandbrave/c14- overview
  153. 153. 追加資料 3 cpprefjp (日本語) http://cpprefjp.github.io/ cppreference.com (英語) http://en.cppreference.com/w/ cplusplus.com (英語) http://www.cplusplus.com/reference/
  154. 154. Question? 1. 新しい乱数ライブラリを使おう 2. 型の宣言は auto に任せよう 3. 範囲ベースのループを使おう 4. ラムダ式を使おう 5. Emplacement の使い所を知ろう 6. 強く型付けされた enum を使おう 7. array を活用しよう 8. NULL を nullptr に置き換えよう 9. 右辺値参照を理解しよう 10. スマートポインタは補助関数で作ろう 11. Transparent operator functors を使おう 12. 古いイディオムを捨てよう 13. 新しいアルゴリズムを知ろう 14. 新しいライブラリを知ろう
  155. 155. 2013.9.14 Ryo Suzuki @Reputeless reputeless@gmail.com 最新の C++ で設計された ゲームとメディアアートの ための C++ ライブラリ Siv3D http://play-siv3d.hateblo.jp/
  156. 156. 更新履歴 2015.1.11 v1.03 p.58 関数名の誤植を修正 p.154 cpprefjp の URL を更新 2013.9.28 v1.02 p.26 コンパイルエラーになるコードを修正 2013.9.17 v1.01 p.42 変数に const をつけていた誤植を修正 p.63 ) が 1 つ多かった誤植を修正

×