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

67,940 views

Published on

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

Published in: Technology, Business
3 Comments
339 Likes
Statistics
Notes
  • @ Kinji Mashiro さん コメントありがとうございます。v1.03 の 114 ページのコードは、 Boss クラスが Enemy クラスを継承している前提で書かれているので、間違いではありません。参考: https://ideone.com/u0ZDkm
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 114ページのところはちょっと間違っていませんか?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • とても実用です 本当に勉強になりましたが
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
67,940
On SlideShare
0
From Embeds
0
Number of Embeds
5,809
Actions
Shares
0
Downloads
523
Comments
3
Likes
339
Embeds 0
No embeds

No notes for slide

ゲーム開発者のための 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 つ多かった誤植を修正

×