Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Ryo Suzuki @Reputeless
2013.9.14 全日本学生ゲーム開発者連合(全ゲ連) 第 14 回交流会
v1.03
Siv3D 開発者 早稲田大学
1
2𝜋𝜎2
𝑒𝑥𝑝 −
𝑥 − 𝜇 2
2𝜎2
正規分布とゲーム
正規分布とゲーム
正規分布とゲーム
正規分布とゲーム
ゲームで現実味のある
ランダムな結果をつくるとき
正規分布が役に立つ
正規分布とゲーム
C++11では正規分布する乱数を
簡単につくる機能が追加
A Proposal to Add an Extensible Random
Number Facility to the Standard Library
(Revision 2) http://www.open-std.org/jtc1/s...
ゲーム開発者にとって
優しく便利になった最新の C++
最新の C++ でゲーム開発を
するための 14 のガイドライン
C++ の進化
C++98
major
C++03
bug fix only
C++11
major
C++14
minor
C++17
major
C++11 は
13 年ぶりのアップデート
C++11/14 での進化
• コードを短く簡単にする
• 間違いやすさを減らす
• 実行時性能を向上させる
• 機能を増やす
Visual Studio は
着実に C++11/14 に対応
2010. 4 2010
auto, move, nullptr
lamdas, <random>
2012. 9 2012
Range-based for, enum clas...
Visual Studio 2010/2012/2013
でサポートされている機能を対象
最新の C++ でゲーム開発を
するための 14 のガイドライン
新しい
乱数ライブラリを
使おう
1.
<random> ヘッダの乱数エンジンは高品質
な乱数生成器を提供する
適切な分布クラスを定義することで、乱数
の型、範囲、分散のしかたを簡単にコント
ロールできる
要約
従来の rand() の欠点
• 最大値が 32767 と小さい (Visual Studio)
• 偏りが生じやすい
• 型や分布を柔軟に指定できない
新しい乱数ライブラリ
<random> ヘッダに定義
乱数エンジン
メルセンヌ・ツイスター法や
ハードウェアエントロピーによる乱数生成器
分布クラス
乱数の型と範囲、分散方法を定義
mt19937 rng;
for (int i=0; i<10; ++i)
cout << rng() << '¥n';
乱数エンジン [1/3]
メルセンヌ・ツイスター法による乱数生成
mt19937 rng(123456);
for (int i=0; i<10; ++i)
cout << rng() << '¥n';
乱数エンジン [2/3]
乱数のシード値を指定
random_device rng;
for (int i=0; i<10; ++i)
cout << rng() << '¥n';
乱数エンジン [3/3]
ハードウェア・エントロピー・ソースを
基にした予測不能な乱数生成
乱数生成器の比較
乱数の質 速度
rand() 低い 早い
mt19937 優秀 早い
random_device 真の乱数 遅い
mt19937 rng{ random_device()() };
for (int i=0; i<10; ++i)
cout << rng() << '¥n';
乱数エンジンの工夫
random_device で mt19937 のシード作成
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...
mt19937 rng;
uniform_real_distribution<double>
dist(-100.0,100.0);
for (int i=0; i<10; ++i)
cout << dist(rng) << '¥n';
// ...
ベルヌーイ分布
指定した確率で true が出現
mt19937 rng;
bernoulli_distribution dist(0.5);
if (dist(rng))
cout << "おもて¥n";
else
cout << "うら¥n...
正規分布
平均 μ, 標準偏差 σ の正規分布に
したがって値が出現
mt19937 rng();
normal_distribution<double>
dist(170.0,6.0);
for (int i=0; i<10; ++i)
co...
0.000…% の
異常値を避けるために
適切にクランプする
正規分布の注意
3m級の巨人
<random> ヘッダの乱数エンジンは高品質
な乱数生成器を提供する
適切な分布クラスを定義することで、乱数
の型、範囲、分散のしかたを簡単にコント
ロールできる
復習
型の宣言は
autoに任せよう
2.
長い型名や、わかりにくい型名は
auto を使って省略しよう
auto を使っていて const や参照型が欲し
い場合は、const や & を記述すること
要約
auto x = 5; // int
auto y = 3.5f; // float
auto z = sin(3.14); // double
// 実際は上記のような単純な場面では
// 読みにくくなるので使うべきでない
auto [1/4...
vector<int>::iterator i
= max_element(v.begin(),v.end());
map<string,pair<int,string>>::iterator k
= m.find("key");
auto [...
auto [3/4]
長い型名を省略する
auto i = max_element(v.begin(),v.end());
auto k = m.find("key");
const auto x = 5; // const int
vector<vector<int>> vv(10);
auto a = vv[0]; // vector<int>
auto& b = vv[0]; // vector<int>&...
長い型名や、わかりにくい型名は
auto を使って省略しよう
auto を使っていて const や参照型が欲し
い場合は、const や & を記述すること
復習
範囲ベースの
ループを使おう
3.
範囲ベースのループを使うと、単純なルー
プを短く記述できる
ループカウンタのような不必要な変数を減
らし、コードの意図をより明確にしよう
要約
int scores[5] = {40,80,90,60,100};
for (auto& score : scores)
score += 10;
for (const auto score : scores)
cout << score <...
範囲ベース for ループ [2/5]
イテレーターを返す begin() / end()
メンバ関数を持っていれば使える
vector<int> v;
list<double> li;
string str;
for (auto n : v)...
vector<Widget> widgets;
for (auto& widget : widgets)
widget.update();
for (const auto& widget : widgets)
widget.draw();
範囲...
範囲ベース for ループ [4/5]
二重ループの改善例
double matrix[4][4] = { ... };
for (int i=0; i<4; ++i)
{
for (int k=0; k<4; ++k)
cout << mat...
double matrix[4][4] = { ... };
for (const auto& row : matrix)
{
for (const auto elem : row)
cout << elem << ',';
cout << '...
範囲ベースのループを使うと、単純なルー
プを短く記述できる
ループカウンタのような不必要な変数を減
らし、コードの意図をより明確にしよう
復習
ラムダ式を使おう
4.
ラムダ式で関数オブジェクトをローカルに
定義し、アルゴリズムを読みやすくしよう
キャプチャを使うと外部の変数をラムダ式
の中で使用できる
要約
アルゴリズムは便利だ [1/3]
count_if
find_if
remove_if
for_each
generate
sort ...
第 3 引数に関数
bool IsEven(int n) {
return n%2==0;
}
vector<int> v;
// 偶数の要素を数える
size_t x = count_if(v.begin(),v.end(),
IsEven);
アルゴリズムは便...
struct IsEven : unary_function<int,bool> {
result_type operator()
(argument_type n) const {
return n%2==0;
}}; // 関数オブジェクト...
述語関数が面倒だ
使う場所と定義する場所が離れている
関数オブジェクトは記述が長い
これを解決するのがラムダ式
size_t x = count_if(v.begin(),v.end(),
[](int n){ return n%2==0; });
ラムダ式 [1/4]
size_t x = count_if(v.begin(),v.end(),
[](int n){ return n%2==0; });
ラムダ式 [2/4]
[] () ->T {} で構成される
[] キャプチャリスト
() 引数
->T ...
size_t x = count_if(v.begin(),v.end(),
[](int n){ return n%2==0; });
ラムダ式 [3/4]
ラムダ式は、相当する関数オブジェクトを
自動で作る
可読性とパフォーマンスに優れる
auto Square =
[](int n){ return n*n; };
cout << Square(9) << '¥n'; // 81
ラムダ式で遊ぼう [1/7]
auto PrintSquare =
[](int n){ cout << n*n << '¥n'; };
PrintSquare(100); // 10000
ラムダ式で遊ぼう [2/7]
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]
const int ar[4] = { 1, 2, 3, 4 };
const int x = 10;
for_each(begin(ar),end(ar),
[=](int n){ cout << n*x << ' '; });
// [=]...
const int ar[4] = { 1, 2, 3, 4 };
int sum = 0;
for_each(begin(ar),end(ar),
[&](int n){ sum += n; });
// [&] により、ラムダ式内の sum...
vector<Vec2> pts;
// 原点に近い順にソート
sort(pts.begin(),pts.end(),
[](const Vec2& a, const Vec2& b)
{ return a.lengthSq()<b.lengt...
vector<Enemy> enemies;
int threshold = 20;
// HP が threshold 未満の敵を削除
enemies.erase(remove_if(
enemies.begin(),enemies.end(...
ラムダ式で関数オブジェクトをローカルに
定義し、アルゴリズムを読みやすくしよう
キャプチャを使うと外部の変数をラムダ式
の中で使用できる
復習
Emplacementの
使い所を知ろう
5.
オブジェクトの構築とコンテナへの追加を
同時に行う場合は Emplacement を使おう
適切な場面で使えば push_back に比べて
要素追加のコストを減らせる
要約
vector<Point> v;
v.push_back(Point(5,10));
push_back() のコスト
5 10
COPY
vector<Point> v;
v.emplace_back(5,10);
emplace_back()
5 10
Emplacement [1/2]
要素のコンストラクタ引数を受け取り、コ
ンテナ内でオブジェクトを構築する
一時オブジェクトのコピーと破棄のコスト
が発生しない
5 10
Emplacement [2/2]
vector, deque, map などのコンテナの
Emplacement 挿入関数
push_back() → emplace_back()
push_front() → emplace_front()...
要素追加の使い分け [1/2]
vector<T> などに対して
push_back()
T 型の値 (lvalue / rvalue),
{ initializer-lists }
emplace_back()
それ以外の型,
0 個 もしく...
string GetString();
const string str = "Hello";
vector<string> v;
v.push_back(str);
v.push_back(GetString());
v.push_back(...
オブジェクトの構築とコンテナへの追加を
同時に行う場合は Emplacement を使おう
適切な場面で使えば push_back に比べて
要素追加のコストを減らせる
復習
強く型付けされた
enumを使おう
6.
enum class は enum の強化版で、強い型付
けとスコープを持つ
enum class を使えば、整数型への暗黙的な
変換や、列挙子の名前の衝突を防げる
要約
void SetColor(unsigned);
enum Team { Red, White };
const unsigned red = 0xffFF0000;
SetColor(red);
SetColor(Red); // ?
従来の...
struct Team {
enum { Red, White };
};
struct Palette {
enum { Red, Green, Blue };
};
従来の enum の問題点 [2/2]
名前の衝突を防ぐために
スコープを...
enum class name : type {
enumerator = constexpr,
enumerator = constexpr, ...
};
enum struct name : type {
enumerator = con...
enum class Team { Red, White };
enum class Month {
January = 1, February, ...
};
enum class Align : char {
Left = 'L',
Cen...
enum class Team { Red, White };
enum class Palette { Red, Green, Blue };
const Team team = Team::Red;
switch (palette) {
c...
void SetColor(unsigned);
enum class Team { Red, White };
const unsigned red = 0xffFF0000;
SetColor(red);
SetColor(Team::Re...
enum class は enum の強化版で、強い型付
けとスコープを持つ
enum class を使えば、整数型への暗黙的な
変換や、列挙子の名前の衝突を防げる
復習
arrayを活用しよう
7.
array は通常の配列にオーバーヘッド無し
でコンテナのインタフェースを提供する
array のインタフェースが有効な場面では、
積極的に活用しよう
要約
配列と array [1/2]
配列はインタフェースが貧弱
const int size = 100;
int ar[size];
for (int i=0; i<size; ++i)
ar[i] = 10 * i;
配列と array [2/2]
<array> ヘッダの array を使おう
array<int,100> ar;
for (size_t i=0; i<ar.size(); ++i)
ar[i] = 10 * i;
array [1/2]
通常の配列にコンテナのインタフェースを
与えたラッパー
size(), at(), begin(), end(), fill()
などのメンバ関数を提供
サイズはコンパイル時に決まり、パフォー
マンスは通常の配列と変わら...
array [2/2]
array<int,5> a = { 5, 10, 15, 20, 25 };
array<int,5> b;
b.fill(100); // 要素を全部 100 に
a = b; // 要素数が同じなら代入可能
a[0...
array は通常の配列にオーバーヘッド無し
でコンテナのインタフェースを提供する
array のインタフェースが有効な場面では、
積極的に活用しよう
復習
NULLをnullptrに
置き換えよう
8.
ヌルポインタを表す NULL と 0 を nullptr
に置き換えよう
ヌルポインタの意図が明確になり、オー
バーロードのトラブルを防げる
要約
ヌルポインタ [1/3]
NULL
#define NULL 0
と定義される、単なる数値の 0
nullptr
あらゆるポインタ型のヌルポインタを
表すポインタ定数のキーワード
整数には変換できない
C++98
ヌルポインタ [2/3]
NULL はトラブルの元
void f(int n);
void f(const char* s);
f(0);
f("hello");
f(NULL); // f(int)
ヌルポインタ [3/3]
nullptr でオーバーロードを正確に
void f(int n);
void f(const char* s);
f(0);
f("hello");
f(nullptr); // f(const char*)
ヌルポインタを表す NULL と 0 を nullptr
に置き換えよう
ヌルポインタの意図が明確になり、オー
バーロードのトラブルを防げる
復習
右辺値参照を
理解しよう
9.
右辺値参照と Move セマンティクスによっ
て、サイズが大きいオブジェクトのコピー
のパフォーマンスが向上する
自分で定義したクラスにも、必要なら
Move セマンティクスを実装できる
要約
vector<int> GetVector();
void GetVector(vector<int>& v);
vector<int> v
= GetVector(); // コピーが発生
GetVector(v); // ok
右辺値参照と...
vector<int> GetVector();
void GetVector(vector<int>& v);
vector<int> v = GetVector(); // ok
GetVector(v); // ok
右辺値参照と Mov...
右辺値参照と Move [3/5]
ptr1
ptr2
コピー完了後に破棄
コピー
これまで
C++98
右辺値参照と Move [4/5]
ptr1
ptr1
所有権を移動
(Move セマンティクス)
これから
nullptr
右辺値参照と Move [5/5]
右辺値
名前のない一時オブジェクト
右辺値参照 (Type&& x)
右辺値を受け取るオーバーロード
std::move() 関数
左辺値を右辺値にキャスト
右辺値参照 実装例 1
struct BigData {
BigData();
BigData(const BigData&);
BigData(BigData && data)
: m_p(data.m_p),m_size(data.m_si...
右辺値参照 実装例 2
struct BigData {
BigData();
BigData(const BigData&);
BigData(BigData && data)
: m_data(move(data.m_data)) { }
...
右辺値参照と Move セマンティクスによっ
て、サイズが大きいオブジェクトのコピー
のパフォーマンスが向上する
自分で定義したクラスにも、必要なら
Move セマンティクスを実装できる
復習
スマートポインタは
補助関数で作ろう
10.
オブジェクトのポインタはスマートポイン
タで管理しよう
スマートポインタは補助関数で作って、パ
フォーマンスの利得と、記述の一貫性を得
よう
要約
さらば new と delete [1/5]
new と delete は危険
int* pArray = new int[10000];
delete[] pArray; // 取扱注意
さらば new と delete [2/5]
動的配列は vector か string
vector<int> v(10000);
string str;
さらば new と delete [3/5]
単一のデータのポインタは・・・
Enemy* pEnemy = new Boss;
delete pEnemy;
さらば new と delete [4/5]
スマートポインタを使う
shared_ptr<Enemy> pEnemy = new Boss;
// 自動的に delete してくれる
// まだ最適化可能
unique_ptr<Enemy> pEnemy = new Boss;
// 自動的に delete してくれる
さらば new と delete [5/5]
ポインタをコピーしない場合、
unique_ptr を使えばゼロオーバーヘッド
補助関数 [1/2]
スマートポインタは補助関数で作ろう
make_shared<T>
オブジェクトと管理用データを一緒に
連続領域に new するので効率的
make_unique<T>
名前の一貫性、new の記述が不要に
補助関数 [2/2]
shared_ptr<Enemy> pEnemy
= make_shared<Boss>();
unique_ptr<Enemy> pEnemy2
= make_unique<Boss>();
オブジェクトのポインタはスマートポイン
タで管理しよう
スマートポインタは補助関数で作って、パ
フォーマンスの利得と、記述の一貫性を得
よう
復習
Transparent
operator functors
を使おう
11.
将来起こりそうな問題は?
vector<unsigned> v { 10, 50, 20, 30 };
sort(v.begin(),v.end(),
greater<unsigned>());
将来起こりそうな問題は?
vector<unsigned> v { 10, 50, 20, 30 };
sort(v.begin(),v.end(),
greater<unsigned>());
vector<int> v { -10, 50,...
Transparent operator
functors
vector<unsigned> v { 10, 50, 20, 30 };
sort(v.begin(),v.end(),greater<>());
比較・算術用クラステンプレート
...
<functional> ヘッダの関数オブジェクト
をテンプレート実引数なしで使おう
単に記述が短いだけでなく、型を変更した
際のトラブルを防げる
復習
古いイディオムを
捨てよう
12.
これまでのイディオムを新しい C++ の機
能で置き換えられないか再確認しよう
C++11/14 はよりシンプルで、高速、安全
な代替手段を提供しているかもしれない
要約
shrink to fit
vector<int> v;
vector<int>(v).swap(v);
vector<int> v;
v.shrink_to_fit();
配列の範囲
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 };
s...
Safe bool
/*
Safe bool は operator bool を定義した
オブジェクトの無意味な比較を防ぐ。実装省略
*/
struct Something {
explicit operator bool() const;
};
コンパイル時 assert
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
#define STATIC_ASSERT(e,m...
これまでのイディオムを新しい C++ の機
能で置き換えられないか再確認しよう
C++11/14 はよりシンプルで、高速、安全
な代替手段を提供しているかもしれない
復習
新しい
アルゴリズムを
知ろう
13.
<algorithm> ヘッダの新しいアルゴリズム
関数を知ろう
ちょっとした操作やループを、これまでよ
り短く、早いコードで書けるようになる
要約
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...
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,...
int a = 25, b = 30;
const int smaller = min(a,b); // 25
const int larger = max(a,b); // 30
最小/最大値を同時に取得
min() と max() で比較演...
int a = 25, b = 30;
// results は pair<int,int> 型
const auto results = minmax(a,b);
const int smaller = results.first; // 2...
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...
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);
...
const int maxVal = 500; // 500円まで
bool ruleKept = true;
for (size_t i=0; i<v.size(); ++i) {
if (v[i] > maxVal) {
ruleKept ...
const int maxVal = 500;
const bool ruleKept
= all_of(v.begin(),v.end(),
[=](int n){ return n<=maxVal; });
全要素の条件チェック
all_o...
const int maxVal = 500;
const bool ruleBroken
= any_of(v.begin(),v.end(),
[=](int n){ return n>maxVal; });
const bool rule...
vector<int> v { 1, 2, 3, 4, 5, 6, 7 };
shuffle(v.begin(), v.end(),
mt19937(random_device()()));
要素をランダムに並び替え
shuffle() アルゴ...
<algorithm> ヘッダの新しいアルゴリズム
関数を知ろう
ちょっとした操作やループを、これまでよ
り短く、早いコードで書けるようになる
復習
新しいライブラリを
知ろう
14.
新しく追加されたライブラリによって、こ
れまで難しかった処理や高速なデータ管理
が可能になる
要約
const auto start = chrono::system_clock::now();
// 何らかの処理
const auto end = chrono::system_clock::now();
const chrono::dura...
const chrono::minutes min(5);
const chrono::seconds sec(15);
// 型は std::chrono::seconds
const auto result = min + sec;
cou...
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)) {
c...
const string s = "C++11, C++14 and C++1y";
const regex e("¥¥d");
cout << regex_replace(s,e,"[$&]") << '¥n';
// C++[1][1], ...
tuple<string,int,char> GetStudent()
{
return make_tuple("John", 86, 'B');
}
const auto student = GetStudent();
cout << get...
unordered_set<string> s = {
"C++", "Java", "Ruby", "PHP"
};
s.emplace("Haskell");
if (s.find("C#") == s.end())
cout << "no...
unordered_map<string,int> m {
{ "C++98", 1998 },
{ "C++11", 2011 }
};
m.emplace("C++14",2014);
cout << m["C++11"] << '¥n';...
新しく追加されたライブラリによって、こ
れまで難しかった処理や高速なデータ管理
が可能になる
復習
今日紹介したのは、
新しい C++ の一部分
追加資料 1
Visual C++ で使える C++11
by @nekko1119 さん
http://www.slideshare.n
et/nekko1119/c11-in-
visual-c
追加資料 2
C++14 Overview
by @cpp_akira さん
http://www.slideshare.n
et/faithandbrave/c14-
overview
追加資料 3
cpprefjp (日本語)
http://cpprefjp.github.io/
cppreference.com (英語)
http://en.cppreference.com/w/
cplusplus.com (英語)
ht...
Question?
1. 新しい乱数ライブラリを使おう
2. 型の宣言は auto に任せよう
3. 範囲ベースのループを使おう
4. ラムダ式を使おう
5. Emplacement の使い所を知ろう
6. 強く型付けされた enum を使おう...
2013.9.14
Ryo Suzuki
@Reputeless
reputeless@gmail.com
最新の C++ で設計された
ゲームとメディアアートの
ための C++ ライブラリ Siv3D
http://play-siv3d.ha...
更新履歴
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 変...
ゲーム開発者のための C++11/C++14
Prochain SlideShare
Chargement dans…5
×
Prochain SlideShare
C++の黒魔術
Suivant
Télécharger pour lire hors ligne et voir en mode plein écran

367

Partager

Télécharger pour lire hors ligne

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

Télécharger pour lire hors ligne

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

Livres associés

Gratuit avec un essai de 30 jours de Scribd

Tout voir

Livres audio associés

Gratuit avec un essai de 30 jours de Scribd

Tout voir

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

    Jun. 19, 2021
  • ssuserd8f1251

    Jun. 15, 2021
  • kimitsugu_nakao

    Jun. 9, 2021
  • harukiakiba

    Nov. 3, 2020
  • m0tchy1

    Sep. 2, 2020
  • whojinn

    Aug. 1, 2020
  • shosukeminakawa

    Mar. 10, 2020
  • satodelu

    Dec. 8, 2019
  • reiyafukuta

    Jun. 21, 2019
  • c17ru5

    Feb. 23, 2019
  • ssuserad9d00

    Feb. 3, 2019
  • ichiroh

    Jan. 12, 2019
  • ItonagaMasaya

    Jan. 10, 2019
  • tchofu

    Dec. 22, 2018
  • YoshitadaKurozumi

    Oct. 17, 2018
  • daisuketakeuchi96

    Oct. 15, 2018
  • pitray1

    Jun. 26, 2018
  • KOba4

    Jun. 17, 2018
  • Iseya

    Jun. 5, 2018
  • slidekufuup

    May. 31, 2018

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

Vues

Nombre de vues

94 753

Sur Slideshare

0

À partir des intégrations

0

Nombre d'intégrations

8 803

Actions

Téléchargements

640

Partages

0

Commentaires

0

Mentions J'aime

367

×