Upload
ryo-suzuki
View
47.823
Download
6
Embed Size (px)
DESCRIPTION
第14回 全ゲ連での講演資料です。 Twitter: @Reputeless
Citation preview
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/sc22/wg21/docs/papers/2003/n1452.html
ゲーム開発者にとって優しく便利になった最新の C++
最新の C++ でゲーム開発をするための 14 のガイドライン
C++の進化
C++98major
C++03bug fix only
C++11major
C++14minor
C++17major
C++11 は13年ぶりのアップデート
C++11/14での進化
• コードを短く簡単にする
• 間違いやすさを減らす
• 実行時性能を向上させる
• 機能を増やす
Visual Studioは着実にC++11/14に対応
2010. 4 2010auto, move, nullptrlamdas, <random>
2012. 9 2012Range-based for, enum class
<chrono> , <ratio>. <thread>
2013. 6 2013 PreviewVariadic templates
initializer_lists, C++14 libs
2013. 9 2013 RCNon-static data member init
defaulted / deleted functions2013. 11 2013
2013 Q4 2013 + CTPconstexpr, noexcept
C++14 generic lamdas
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';
// 62.9447 -72.90463 81.15846 ...
実数の一様分布指定した範囲の実数が等確率で出現
ベルヌーイ分布指定した確率で 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)
cout << dist(rng) << '¥n';
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 [2/4]
長い型名を省略する
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>&
const auto& c = vv[0]; // const vector<int>&
auto [4/4]
const 修飾や参照の宣言
長い型名や、わかりにくい型名は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 << '¥n';
// 50 90 100 70 110
範囲ベースforループ [1/5]
単純な for ループを短くできる
範囲ベース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';
vector<Widget> widgets;
for (auto& widget : widgets)
widget.update();
for (const auto& widget : widgets)
widget.draw();
範囲ベースforループ [3/5]
コピーを避けたい場合は参照で
範囲ベース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';
}
double matrix[4][4] = { ... };
for (const auto& row : matrix)
{
for (const auto elem : row)
cout << elem << ',';
cout << '¥n';
}
範囲ベースforループ [5/5]
二重ループの改善例
範囲ベースのループを使うと、単純なループを短く記述できる
ループカウンタのような不必要な変数を減らし、コードの意図をより明確にしよう
復習
ラムダ式を使おう
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);
アルゴリズムは便利だ [2/3]
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]
述語関数が面倒だ
使う場所と定義する場所が離れている
関数オブジェクトは記述が長い
これを解決するのがラムダ式
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 << ' '; });
// [=] により、ラムダ式内の x は
// 外部からコピーキャプチャ
// 10 20 30 40
ラムダ式で遊ぼう [4/7]
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]
vector<Vec2> pts;
// 原点に近い順にソート
sort(pts.begin(),pts.end(),
[](const Vec2& a, const Vec2& b)
{ return a.lengthSq()<b.lengthSq(); }
);
ラムダ式で遊ぼう [6/7]
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]
ラムダ式で関数オブジェクトをローカルに定義し、アルゴリズムを読みやすくしよう
キャプチャを使うと外部の変数をラムダ式の中で使用できる
復習
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()
insert() → emplace()
要素追加の使い分け [1/2]
vector<T> などに対して
push_back()T 型の値 (lvalue / rvalue),{ initializer-lists }
emplace_back()それ以外の型,0 個 もしくは 2 個以上の引数
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]
オブジェクトの構築とコンテナへの追加を同時に行う場合は 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); // ?
従来のenumの問題点 [1/2]
整数型に暗黙的に変換できるため、意図しない振る舞いが可能
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 = constexpr,enumerator = constexpr, ...
};
enum class [1/4]
強い型付けとスコープを持つ列挙型
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]
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]
列挙型名のスコープを持つ
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]
整数型へ暗黙的に変換されない
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] = 0;
for (const auto n : a)
cout << n << '¥n';
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
右辺値参照と Move [1/5]
むかーしむかし、大きなオブジェクトを返す関数は御法度だった
vector<int> GetVector();
void GetVector(vector<int>& v);
vector<int> v = GetVector(); // ok
GetVector(v); // ok
右辺値参照と Move [2/5]
今はそんなことはない
右辺値参照と 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_size) {
data.m_p = nullptr;
data.m_size = 0;
}
~BigData();
int* m_p;
int m_size;
};
右辺値参照 実装例 2
struct BigData {
BigData();
BigData(const BigData&);
BigData(BigData && data)
: m_data(move(data.m_data)) { }
vector<int> 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, 20, 30 };
sort(v.begin(),v.end(),
greater<unsigned>()); // oops!
Transparent operator functors
vector<unsigned> v { 10, 50, 20, 30 };
sort(v.begin(),v.end(),greater<>());
比較・算術用クラステンプレート[less, greater, plus, multiplies …] をテンプレート実引数なしで使える
<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 };
sort(begin(a),end(a));
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) ¥
enum{ASSERT_CONCAT(static_assert_,__COUNTER__)=1/(!!(e))}
STATIC_ASSERT(sizeof(int)==4,"xxxx");
static_assert(sizeof(int)==4,"xxxx");
これまでのイディオムを新しい 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(a,b),c),d); // 50
最小/最大値の取得3 つ以上の変数に対しては何重もの min() / 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, d }); // 50
最小/最大値の取得initializer-list で複数の値を渡す
int a = 25, b = 30;
const int smaller = min(a,b); // 25
const int larger = max(a,b); // 30
最小/最大値を同時に取得min() と max() で比較演算が 2 回必要
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 回に
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;
配列に連続した値を代入ループが必要
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() アルゴリズムを使おう
const int maxVal = 500; // 500円まで
bool ruleKept = true;
for (size_t i=0; i<v.size(); ++i) {
if (v[i] > maxVal) {
ruleKept = false;
break;
}
}
全要素の条件チェックループが必要
const int maxVal = 500;
const bool ruleKept
= all_of(v.begin(),v.end(),
[=](int n){ return n<=maxVal; });
全要素の条件チェックall_of() アルゴリズムを使おう
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 アルゴリズムも使おう
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::duration<double> elapsed
= end - start;
cout << "経過時間: " << elapsed.count() << "秒¥n";
<chrono> [1/2]
時間の測定
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]
時間の計算と単位の変換
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]
正規表現にマッチする文字列の検索
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]
正規表現を使った文字列の置換
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 つの型を作る
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
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
新しく追加されたライブラリによって、これまで難しかった処理や高速なデータ管理が可能になる
復習
今日紹介したのは、新しい C++ の一部分
追加資料 1Visual C++ で使える C++11by @nekko1119 さん
http://www.slideshare.net/nekko1119/c11-in-visual-c
追加資料 2C++14 Overviewby @cpp_akira さん
http://www.slideshare.net/faithandbrave/c14-overview
追加資料 3
cpprefjp (日本語)http://cpprefjp.github.io/
cppreference.com (英語)http://en.cppreference.com/w/
cplusplus.com (英語)http://www.cplusplus.com/reference/
Question?
1. 新しい乱数ライブラリを使おう
2. 型の宣言は auto に任せよう
3. 範囲ベースのループを使おう
4. ラムダ式を使おう
5. Emplacement の使い所を知ろう
6. 強く型付けされた enum を使おう
7. array を活用しよう
8. NULL を nullptr に置き換えよう
9. 右辺値参照を理解しよう
10. スマートポインタは補助関数で作ろう
11. Transparent operator functors を使おう
12. 古いイディオムを捨てよう
13. 新しいアルゴリズムを知ろう
14. 新しいライブラリを知ろう
2013.9.14
Ryo Suzuki@Reputeless
最新のC++で設計されたゲームとメディアアートのためのC++ライブラリ Siv3D
http://play-siv3d.hateblo.jp/
更新履歴
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 つ多かった誤植を修正