Slide 1

Slide 1 text

0

Slide 2

Slide 2 text

C++17 の新機能 落穂拾い 2019/3/28 鳥頭かりやマン 1

Slide 3

Slide 3 text

*this のコピーキャプチャ 2

Slide 4

Slide 4 text

*this のコピーキャプチャ 3 P0018R0 : Lambda Capture of *this by Value http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0018r0.html P0018R1 : Lambda Capture of *this by Value http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0018r1.html P0018R2 : Lambda Capture of *this by Value as [=,*this] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0018r2.html P0018R3 : Lambda Capture of *this by Value as [=,*this] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0018r3.html

Slide 5

Slide 5 text

*this のコピーキャプチャ 4 導入の背景

Slide 6

Slide 6 text

*this のコピーキャプチャ 導入の背景 5 *this だって コピーキャプチャ したい! まんまやん…

Slide 7

Slide 7 text

*this のコピーキャプチャ 導入の背景 6 今までの問題点 • デフォルトコピーキャプチャを使うと、さもコピーキャプ チャされてる風に(?)メンバ変数名だけでアクセス可能 になるが、実際には this ポインタがコピーされてるだけな ので、メンバ変数は実質参照キャプチャになっている。 • *this をコピーキャプチャするには初期化キャプチャを使 用して別の変数を導入する必要がある。 • デフォルトコピーキャプチャと *this からの初期化キャプ チャを両方使用しても、間違ってメンバ変数名単体でアク セスすると参照アクセスになってしまう。

Slide 8

Slide 8 text

*this のコピーキャプチャ 導入の背景 7 #include struct S { S(int i) : i(i) {} int i; auto f() { return [=]{ return i; }; } }; int main() { auto l = S(42).f(); std::cout << l() << '¥n'; } デフォルトコピーキャプチャでも、 メンバ変数は this 経由でのアクセス なので、実質参照キャプチャ UB!!! デフォルトコピーキャプチャでも、 メンバ変数は this 経由でのアクセス なので、実質参照キャプチャ

Slide 9

Slide 9 text

*this のコピーキャプチャ 導入の背景 8 #include struct S { S(int i) : i(i) {} int i; auto f() { return [self = *this]{ return self.i; }; } }; int main() { auto l = S(42).f(); std::cout << l() << '¥n'; } ナゾの変数 self を導入して、 無理やりコピーキャプチャに。 でもアクセスが面倒… ナゾの変数 self を導入して、 無理やりコピーキャプチャに。 でもアクセスが面倒…

Slide 10

Slide 10 text

*this のコピーキャプチャ 導入の背景 9 #include struct S { S(int i) : i(i) {} int i; auto f() { return [=, self = *this]{ return i; }; } }; int main() { auto l = S(42).f(); std::cout << l() << '¥n'; } デフォルトコピーキャプチャでも、 メンバ変数は this 経由でのアクセス なので、実質参照キャプチャ UB!!! デフォルトコピーキャプチャでも、 メンバ変数は this 経由でのアクセス なので、実質参照キャプチャ せっかくナゾの変数 self を導入して も、デフォルトコピーキャプチャしてい ると this 経由でアクセスできちゃう…

Slide 11

Slide 11 text

*this のコピーキャプチャ 10 対応

Slide 12

Slide 12 text

*this のコピーキャプチャ 対応 11 シンプルキャプチャに *this も指定できる ようにしよう! さすがにデフォルトの挙動は変えられなかったよ…

Slide 13

Slide 13 text

*this のコピーキャプチャ 対応 12 #include struct S { S(int i) : i(i) {} int i; auto f() { return [*this]{ return i; }; } }; int main() { auto l = S(42).f(); std::cout << l() << '¥n'; } ナゾの変数 self を導入して、 無理やりコピーキャプチャに。 でもアクセスが面倒… ラムダキャプチャに *this を指定すると *this がコピーキャプチャされる。 アクセスも簡単!

Slide 14

Slide 14 text

*this のコピーキャプチャ 対応 13 #include struct S { S(int i) : i(i) {} int i; auto f() { return [=, *this]{ return i; }; } }; int main() { auto l = S(42).f(); std::cout << l() << '¥n'; } ナゾの変数 self を導入して、 無理やりコピーキャプチャに。 でもアクセスが面倒… デフォルトコピーキャプチャと一緒に 使っても大丈夫!

Slide 15

Slide 15 text

*this のコピーキャプチャ 対応 14 #include struct S { S(int i) : i(i) {} int i; auto f() { return [&, *this]{ return i; }; } }; int main() { auto l = S(42).f(); std::cout << l() << '¥n'; } ナゾの変数 self を導入して、 無理やりコピーキャプチャに。 でもアクセスが面倒… もちろん、デフォルト参照キャプチャと 一緒に使っても大丈夫!

Slide 16

Slide 16 text

*this のコピーキャプチャ 15 悲報

Slide 17

Slide 17 text

*this のコピーキャプチャ 悲報 16 • デフォルトコピーキャプチャでメンバ変数が実質 参照キャプチャになるのは変わってない。 • C++20 でデフォルトコピーキャプチャで this をコ ピーキャプチャする挙動が非推奨になるが、 C++17 ではまだデフォルトコピーキャプチャ指定 時に this を指定できない。

Slide 18

Slide 18 text

*this のコピーキャプチャ 悲報 17 #include struct S { S(int i) : i(i) {} int i; auto f() { return [=]{ return i; }; } }; int main() { auto l = S(42).f(); std::cout << l() << '¥n'; } デフォルトコピーキャプチャでも、 メンバ変数は this 経由でのアクセス なので、実質参照キャプチャ UB!!! デフォルトコピーキャプチャだけだと、 今までと何も変わってない…

Slide 19

Slide 19 text

*this のコピーキャプチャ 悲報 18 #include struct S { S(int i) : i(i) {} int i; auto f() { return [=]{ return i; }; } }; int main() { auto s = S(42); auto l = s.f(); std::cout << l() << '¥n'; } デフォルトコピーキャプチャでも、 メンバ変数は this 経由でのアクセス なので、実質参照キャプチャ C++20 だと デフォルトコピーキャプチャだけで this にアクセスするのは非推奨…

Slide 20

Slide 20 text

*this のコピーキャプチャ 悲報 19 #include struct S { S(int i) : i(i) {} int i; auto f() { return [=, this]{ return i; }; } }; int main() { auto s = S(42); auto l = s.f(); std::cout << l() << '¥n'; } デフォルトコピーキャプチャでも、 メンバ変数は this 経由でのアクセス なので、実質参照キャプチャ C++20 からは このように書くのが良いが、 C++17 ではこの書き方はエラー

Slide 21

Slide 21 text

*this のコピーキャプチャ 悲報 20 結論 デフォルトキャプチャ 使うのは避けよう!

Slide 22

Slide 22 text

*this のコピーキャプチャ 21 完 終 制作・著作 ━━━━━ ⓃⒽⓀ

Slide 23

Slide 23 text

emplace の戻り値型変更 22

Slide 24

Slide 24 text

emplace の戻り値型変更 23 P0084R0 Emplace Return Type http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0084r0.pdf P0084R1 Emplace Return Type (Revision 1) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0084r1.pdf P0084R2 Emplace Return Type (Revision 2) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0084r2.pdf

Slide 25

Slide 25 text

emplace の戻り値型変更 24 導入の背景

Slide 26

Slide 26 text

emplace の戻り値型変更 導入の背景 25 emplace_front や emplace_back の直後にその 要素アクセスすることが多い んだが、こいつらの戻り値型 が void でまんどくさい… 普通の emplace は iterator とか返ってくるのにね…

Slide 27

Slide 27 text

emplace の戻り値型変更 導入の背景 26 ペーパーに載ってた例 // ① 格納してすぐにメンバ関数呼び出し my_container.emplace_back(…); my_container.back().do_something(…); // ② 格納してすぐに関数に引き渡し(バンドじゃないよ(分かったらおっさん my_container.emplace_back(…); do_something_else(my_container.back()); // ➂ デフォルト構築してすぐにファイルから読み込み my_container.emplace_back(); my_container.back().read(file_stream);

Slide 28

Slide 28 text

emplace の戻り値型変更 27 対応

Slide 29

Slide 29 text

emplace の戻り値型変更 対応 28 要素への 参照返す ようにしよ 575(無理やり iterator じゃないんだ…

Slide 30

Slide 30 text

emplace の戻り値型 対応 29 対象 1.シーケンスコンテナの emplace_front、emplace_backという 名のメンバ関数 2.コンテナアダプタの queue::emplace、 stack::emplace priority_queue::emplace は入らないのね…

Slide 31

Slide 31 text

emplace の戻り値型変更 対応 30 ペーパーに載ってた例(改) // ① 格納してすぐにメンバ関数呼び出し my_container.emplace_back(…).do_something(…); // ② 格納してすぐに関数に引き渡し do_something_else(my_container.emplace_back(…)); // ➂ デフォルト構築してすぐにファイルから読み込み my_container.emplace_back().read(file_stream);

Slide 32

Slide 32 text

emplace の戻り値型変更 対応 31 push 系はやらないの? ⇓ push するって事は既にオブジェクト持ってる から不要なことが多いし、どうしても格納後オ ブジェクトにアクセスしたければ emplace 使 えばいいっしょ(ペーパーより超訳)

Slide 33

Slide 33 text

emplace の戻り値型変更 対応 32 下記の2点がよくわかりませんでした… • 他の emplace 系の戻り値型は iterator な のに何で参照なの? • 何で std::priority_queue::emplace は対象 外なの? 教えて!エロい人!!!

Slide 34

Slide 34 text

emplace の戻り値型変更 33 完 終 制作・著作 ━━━━━ ⓃⒽⓀ

Slide 35

Slide 35 text

単純な文字列変換 34

Slide 36

Slide 36 text

単純な文字列変換 35 N4412: Shortcomings of iostreams http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4412.html P0067R0: Elementary string conversions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0067r0.html P0067R1: Elementary string conversions, revision 1 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0067r1.html P0067R2: Elementary string conversions, revision 2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0067r2.html P0067R3: Elementary string conversions, revision 2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0067r3.html P0067R4: Elementary string conversions, revision 4 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0067r4.html P0067R5: Elementary string conversions, revision 5 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0067r5.html

Slide 37

Slide 37 text

単純な文字列変換 36 導入の背景

Slide 38

Slide 38 text

単純な文字列変換 導入の背景 37 既存ライブラリの問題点 • 書式指定文字列うぜぇ • 動的メモリ割当強制うぜぇ • ロケールうぜぇ • 仮想関数呼び出しうぜぇ • バッファオーバーラン怖ぇ • 入力文字列のエラー分かんねぇのうぜぇ • 入力文字列のスペース勝手に無視すんのうぜぇ • 頭の0x勝手に解釈すんのうぜぇ

Slide 39

Slide 39 text

単純な文字列変換 導入の背景 38 既存ライブラリの問題点 結論 うぜぇ ちょっと怖ぇ

Slide 40

Slide 40 text

単純な文字列変換 導入の背景 39 既存機能 うぜぇとこ sprintf ロケール、書式指定文字列、バッファオーバーラン snprintf ロケール、書式指定文字列 sscanf ロケール、書式指定文字列 atol ロケール、エラー発生不明 strtol ロケール、空白無視、0x勝手に解釈 strstream ロケール、空白無視 stringstream ロケール、空白無視、動的メモリ割当 num_put / num_get facets ロケール、仮想関数呼び出し to_string ロケール、動的メモリ割当 stoi etc. ロケール、動的メモリ割当、空白無視、0x勝手に解釈、 エラー時例外

Slide 41

Slide 41 text

単純な文字列変換 導入の背景 40 オレはただ単純に 数値と文字列とを 変換したいだけ なんだ!!!1!

Slide 42

Slide 42 text

単純な文字列変換 41 対応

Slide 43

Slide 43 text

単純な文字列変換 対応 42 単純な 文字列変換 追加しよ 575(無理やり まんま…

Slide 44

Slide 44 text

単純な文字列変換 対応 43 新規ライブラリの特徴 • 書式指定は文字列じゃない • 動的メモリ割当しない • ロケール無視 • 仮想関数呼び出ししない • バッファオーバーランしない • 戻り値でエラー返す • 入力文字列のスペース無視しない • 頭の0x解釈しない

Slide 45

Slide 45 text

単純な文字列変換 対応 44 文字列から数値への変換 from_chars_result from_chars(const char* first, const char* last, INT※1& value, int base = 10); from_chars_result from_chars(const char* first, const char* last, FLOAT※2& value, chars_format fmt = chars_format::general); ※1 符号付き整数型、符号無し整数型、charのいずれか。 整数型全部じゃないよ。(bool とか char32_t とかは無い) ※2 任意の浮動小数点型。

Slide 46

Slide 46 text

単純な文字列変換 対応 45 文字列から数値への変換 struct from_chars_result { const char* ptr; //数値として解釈できない文字へのポインタ errc ec; //変換失敗した場合のエラーコード }; enum class chars_format { scientific = 値は未規定, // %e と同じ fixed = 値は未規定, // %f と同じ hex = 値は未規定, // %a とだいたい同じ general = fixed | scientific // %g と同じ };

Slide 47

Slide 47 text

単純な文字列変換 対応 46 数値から文字列への変換 to_chars_result to_chars(char* first, char* last, INT※1 value, int base = 10); to_chars_result to_chars(char* first, char* last, FLOAT※2 value); to_chars_result to_chars(char* first, char* last, FLOAT※2 value, chars_format fmt); to_chars_result to_chars(char* first, char* last, FLOAT※2 value, chars_format fmt, int precision);

Slide 48

Slide 48 text

単純な文字列変換 対応 47 数値から文字列への変換 struct to_chars_result { char* ptr; // 出力された最後の文字の次へのポインタ errc ec; // 変換失敗した場合のエラーコード };

Slide 49

Slide 49 text

単純な文字列変換 対応 48 重要 なんと新規ヘッダ

Slide 50

Slide 50 text

単純な文字列変換 49 使い方

Slide 51

Slide 51 text

単純な文字列変換 使い方 50 // 文字⇒数値変換 const char s[] = "42kg"; int i = 0; auto r = std::from_chars(s, s + sizeof(s) - 1, i); assert(i == 42); assert(r.ptr == s + 2); assert(r.ec == std::errc{}); ※ r.ptr は数値として解釈できない文字(この場合は"k")を指す。 (エラーではない) ちなみに、ここでは説明のため敢えて r で受けてるけど普通は構造化束縛使うよね…

Slide 52

Slide 52 text

単純な文字列変換 使い方 51 // マイナス符号 const char s[] = "-42g"; int i = 0; auto r = std::from_chars(s, s + sizeof(s) - 1, i); assert(i == -42); assert(r.ptr == s + 3); assert(r.ec == std::errc{});

Slide 53

Slide 53 text

単純な文字列変換 使い方 52 // プラス符号はNG const char s[] = "+42"; int i = 114'514; auto r = std::from_chars(s, s + sizeof(s) - 1, i); assert(i == 114'514); assert(r.ptr == s); assert(r.ec == std::errc::invalid_argument); ※ エラーの時は i は変わらず、r.ptr は数値として解釈できない文 字(この場合は"+")を指す。

Slide 54

Slide 54 text

単純な文字列変換 使い方 53 // 数値がデカすぎる場合もNG const char s[] = "12345678901234567890"; int i = 42; auto r = std::from_chars(s, s + sizeof(s) - 1, i); assert(i == 42); assert(r.ptr == s + sizeof(s) - 1); assert(r.ec == std::errc::result_out_of_range); ※ この場合も、r.ptr は数値として解釈できない文字を指すので、最 後の数字の次の文字(つまり終端)を指している。 (変換対象の文字の次ではない)

Slide 55

Slide 55 text

単純な文字列変換 使い方 54 // もちろん16進数はOK const char s[] = "DEADBEEF"; int i = 42; auto r = std::from_chars(s, s + sizeof(s) - 1, i, 16); assert(i == 0xDEAD'BEEF); assert(r.ptr == s + 8); assert(r.ec == std::errc{});

Slide 56

Slide 56 text

単純な文字列変換 使い方 55 // 16進数でも頭の"0x"はNG const char s[] = "0xDEADBEEF"; int i = 42; auto r = std::from_chars(s, s + sizeof(s) - 1, i, 16); assert(i == 0); assert(r.ptr == s + 1); assert(r.ec == std::errc{}); ※ エラーじゃなくて、先頭の0だけ変換されてる。(わりとワナ)

Slide 57

Slide 57 text

単純な文字列変換 使い方 56 // ナゾの36進数までOK const char s[] = "1Z1z"; int i = 42; auto r = std::from_chars(s, s + sizeof(s) - 1, i, 36); assert(i == 92'087); assert(r.ptr == s + 4); assert(r.ec == std::errc{});

Slide 58

Slide 58 text

単純な文字列変換 使い方 57 // 浮動小数点型 const char s[] = "42.195km"; double d = 0; auto r = std::from_chars(s, s + sizeof(s) - 1, d); assert(d == 42.195); assert(r.ptr == s + 6); assert(r.ec == std::errc{});

Slide 59

Slide 59 text

単純な文字列変換 使い方 58 // 浮動小数点型もプラス符号はNG const char s[] = "+42.195km"; double d = 114'514; auto r = std::from_chars(s, s + sizeof(s) - 1, d); assert(d == 114'514); assert(r.ptr == s); assert(r.ec == std::errc::invalid_argument);

Slide 60

Slide 60 text

単純な文字列変換 使い方 59 // 指数部のプラス符号はOK(もちろんなくてもOK) const char s[] = "2.99792458e+8m/s"; double d = 0; auto r = std::from_chars(s, s + sizeof(s) - 1, d); assert(d == 2.997'924'58e+8); assert(r.ptr == s + 13); assert(r.ec == std::errc{});

Slide 61

Slide 61 text

単純な文字列変換 使い方 60 // fmtがscientificの場合は指数部が無いとNG const char s[] = "299792458m/s"; double d = 0; auto r = std::from_chars(s, s + sizeof(s) - 1, d, std::chars_format::scientific); assert(d == 0); assert(r.ptr == s); assert(r.ec == std::errc::invalid_argument); ※ 形式エラーの場合は ptr は先頭を指すらしい。(たぶん使わない)

Slide 62

Slide 62 text

単純な文字列変換 使い方 61 // fmtがhexならみんな大好き16進浮動小数点も行けるけど、 // こちらも先頭の0xはNG const char s[] = "CAFE.BABEp+15Java"; double d = 0; auto r = std::from_chars(s, s + sizeof(s) - 1, d, std::chars_format::hex); assert(d == 0xCAFE.BABEp+15); //つまり、1.702'845'791e+9 assert(r.ptr == s + 13); assert(r.ec == std::errc{});

Slide 63

Slide 63 text

単純な文字列変換 使い方 62 // 数値⇒文字変換 int i = 42; char s[10]; auto r = std::to_chars(s, s + sizeof(s), i); assert("42"sv == std::string_view(s, r.ptr - s)); assert(r.ec == std::errc{}); ※ プラス符号は付かない。(付ける方法は無い) 出力は '¥0' で終端されるわけではないので注意!

Slide 64

Slide 64 text

単純な文字列変換 使い方 63 // もちろん16進数もOK int i = 42; char s[10]; auto r = std::to_chars(s, s + sizeof(s), i, 16); assert("2a"sv == std::string_view(s, r.ptr - s)); assert(r.ec == std::errc{}); ※ 頭に"0x"は付かない。(付ける方法は無い) 英文字の出力は小文字。(大文字バージョンは無い)

Slide 65

Slide 65 text

単純な文字列変換 使い方 64 // もちろん(?)ナゾの36進数まで行ける int i = 92'087; char s[10]; auto r = std::to_chars(s, s + sizeof(s), i, 36); assert("1z1z"sv == std::string_view(s, r.ptr - s)); assert(r.ec == std::errc{});

Slide 66

Slide 66 text

単純な文字列変換 使い方 65 // バッファが足りないとエラー int i = 114'514; char s[5]; auto r = std::to_chars(s, s + sizeof(s), i); assert(r.ptr == s + sizeof(s)); assert(r.ec == std::errc::value_too_large); ※ 変換エラーの場合は ptr は最後を指すらしい。(たぶん使わない) 変換エラーの場合、バッファの中身は未規定

Slide 67

Slide 67 text

単純な文字列変換 使い方 66 // 浮動小数点 double d = 100'000; char s[10]; auto r = std::to_chars(s, s + sizeof(s), d); assert(r.ec == std::errc{}); assert("1e+05"sv == std::string_view(s, r.ptr - s)); ※ フォーマットを指定しないと、ロケール C の printf で %f と %e で変換した場合に文字列が短くなる方になる。 同じ長さの場合には %f 優先。 printf の %g とは違うので注意。

Slide 68

Slide 68 text

単純な文字列変換 使い方 67 // 浮動小数点 double d1 = 3.141592653589793238462643383279; char s[50]; auto r1 = std::to_chars(s, s + sizeof(s), d1); assert(r1.ec == std::errc{}); double d2 = 0; auto r2 = std::from_chars(s, r1.ptr, d2); assert(d1 == d2); assert(r2.ec == std::errc{}); ※ 浮動小数点数は、文字列化の際に精度を指定しない場合、ラウンド トリップして結果が等しくなるように処理される。 フォーマットを指定した場合でも同じ。(ここも printf と違う)

Slide 69

Slide 69 text

単純な文字列変換 使い方 68 // 浮動小数点 double d = 3.141592653589793238462643383279; char s[100]; auto r = std::to_chars(s, s + sizeof(s), d, std::chars_format::general, 3); assert(r.ec == std::errc{}); assert("3.14"sv == std::string_view(s, r.ptr - s)); ※ 精度の指定内容は printf の対応する書式と同じ。 (精度の指定はできるけど幅の指定はできないよ)

Slide 70

Slide 70 text

単純な文字列変換 使い方 69 // みんな大好き16進浮動小数点もOK double d = 0.0625; char s[10]; auto r = std::to_chars(s, s + sizeof(s), d, std::chars_format::hex); assert(r.ec == std::errc{}); assert("1p-04"sv == std::string_view(s, r.ptr - s)); ※ 頭に0xは付かない。

Slide 71

Slide 71 text

単純な文字列変換 70 悲報

Slide 72

Slide 72 text

単純な文字列変換 悲報 71 GCC も Clang も 整数しか対応して ない…

Slide 73

Slide 73 text

単純な文字列変換 悲報 72 何と VC++ 14.16 は 浮動小数点数も それなりに 対応してる! すごいぞ VC++! まだ不完全ではあるけど、ちょっと見直した…

Slide 74

Slide 74 text

単純な文字列変換 73 完 終 制作・著作 ━━━━━ ⓃⒽⓀ

Slide 75

Slide 75 text

検索アルゴリズム 74

Slide 76

Slide 76 text

検索アルゴリズム 75 N3411: Additional Searching Algorithms http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3411.pdf N3606: Extending std::search to use Additional Searching Algorithms http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3606.html N3703: Extending std::search to use Additional Searching Algorithms (Version 3) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3703.html P0253R0: Fixing a design mistake in the searchers interface in Library Fundamentals http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0253r0.pdf P0253R1: Fixing a design mistake in the searchers interface in Library Fundamentals http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0253r1.pdf

Slide 77

Slide 77 text

検索アルゴリズム 76 導入の背景

Slide 78

Slide 78 text

検索アルゴリズム 導入の背景 77 std::search ってとって も便利だけど、もっと いいアルゴリズムも アルゴリズム

Slide 79

Slide 79 text

検索アルゴリズム 導入の背景 78 もっといい アルゴリズム ???

Slide 80

Slide 80 text

検索アルゴリズム 導入の背景 79 もっといいアルゴリズムの例 • Boyer-Moore • Boyer-Moore-Horspool 結構有名らしい…(小並感 アルゴリズムの中身については聞かないでください…

Slide 81

Slide 81 text

検索アルゴリズム 導入の背景 80 導入にあたっての懸念点 もっといいアルゴリズム達は、 検索パータンに対する前処理を 必要とするので、前処理結果を 保存できないともったいない。

Slide 82

Slide 82 text

検索アルゴリズム 導入の背景 81 でも現在の std::searchのインタ フェースは…

Slide 83

Slide 83 text

検索アルゴリズム 導入の背景 82 template ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); ※ [first1, last1) が検索される範囲、[first2, last2) が検索パ ターン範囲なので、前処理結果を保存できる余地が無さそう…

Slide 84

Slide 84 text

検索アルゴリズム 83 対応

Slide 85

Slide 85 text

検索アルゴリズム 対応 84 • さっきの2つのアルゴリズムは 標準でサポートしよう! • std::search のオーバーロードだ けじゃなくて、オブジェクトイン タフェースも追加しよう!

Slide 86

Slide 86 text

検索アルゴリズム 対応 85 オブジェクト インタフェース ???

Slide 87

Slide 87 text

検索アルゴリズム 対応 86 1. 検索パターン範囲を、コン ストラクタの引数にして、検 索オブジェクトを作る 2. 検索対象範囲を、関数呼び 出し演算子の引数にして、 実際に検索する

Slide 88

Slide 88 text

検索アルゴリズム 対応 87 使い方イメージ auto s = u8"柿"sv; auto bm = std::boyer_moore_searcher(begin(s), end(s)); auto t = u8"杮杮杮杮杮杮杮杮杮杮柿杮杮杮杮杮杮杮杮杮杮"sv; auto p = bm(begin(t), end(t)); std::cout << p.first - begin(t) << ", " << p.second - begin(t) << '¥n';

Slide 89

Slide 89 text

検索アルゴリズム 対応 88 使い方イメージ auto s = u8"柿"sv; auto bm = std::boyer_moore_searcher(begin(s), end(s)); auto t = u8"杮杮杮杮杮杮杮杮杮杮柿杮杮杮杮杮杮杮杮杮杮"sv; auto p = bm(begin(t), end(t)); std::cout << p.first - begin(t) << ", " << p.second - begin(t) << '¥n'; 検索パターン範囲をッ、コンストラクタの引数 にしてッ、検索オブジェクトを作るッ!!! ※ ここでは Boyer-Moore アルゴリズム

Slide 90

Slide 90 text

検索アルゴリズム 対応 89 使い方イメージ auto s = u8"柿"sv; auto bm = std::boyer_moore_searcher(begin(s), end(s)); auto t = u8"杮杮杮杮杮杮杮杮杮杮柿杮杮杮杮杮杮杮杮杮杮"sv; auto p = bm(begin(t), end(t)); std::cout << p.first - begin(t) << ", " << p.second - begin(t) << '¥n'; 検索対象範囲をッ、関数呼び出し演算子の引数に してッ、実際に検索するッ!!! 同じオブジェクトで何度でも検索できるぞッ!!!

Slide 91

Slide 91 text

検索アルゴリズム 対応 90 使い方イメージ auto s = u8"柿"sv; auto bm = std::boyer_moore_searcher(begin(s), end(s)); auto t = u8"杮杮杮杮杮杮杮杮杮杮柿杮杮杮杮杮杮杮杮杮杮"sv; auto p = bm(begin(t), end(t)); std::cout << p.first - begin(t) << ", " << p.second - begin(t) << '¥n'; 検索結果はッ、見つかった場所の最初と最後(+1) がッ、イテレータのペアで返ってくるッ!!! ※ 見つからなかったらどっちも検索対象範囲の最後

Slide 92

Slide 92 text

検索アルゴリズム 対応 91 使い方イメージ auto s = u8"柿"sv; auto bm = std::boyer_moore_searcher(begin(s), end(s)); auto t = u8"杮杮杮杮杮杮杮杮杮杮柿杮杮杮杮杮杮杮杮杮杮"sv; auto p = bm(begin(t), end(t)); std::cout << p.first - begin(t) << ", " << p.second - begin(t) << '¥n'; 上記の場合、「柿」は10文字目なので、出力は「30, 33」になる。 (文字列リテラルがUTF-8なので1文字3バイトである事に注意!)

Slide 93

Slide 93 text

検索アルゴリズム 対応 92 使い方イメージ auto s = u8"柿"sv; auto bm = std::boyer_moore_searcher(begin(s), end(s)); auto t = u8"杮杮杮杮杮杮杮杮杮杮柿杮杮杮杮杮杮杮杮杮杮"sv; auto p = bm(begin(t), end(t)); std::cout << p.first - begin(t) << ", " << p.second - begin(t) << '¥n'; 上記の場合、「柿」は10文字目なので、出力は「30, 33」になる。 (文字列リテラルがUTF-8なので1文字3バイトである事に注意!) あ、「柿」(かき)はこの文字だけで、あとは「杮」(こけら)です。 見ればわかると思うけど(?)、念のため。

Slide 94

Slide 94 text

検索アルゴリズム 93 検索オブジェクトの 種類

Slide 95

Slide 95 text

検索アルゴリズム 検索オブジェクトの種類 94 標準では以下の3つをサポート • デフォルト • Boyer-Moore • Boyer-Moore-Horspool

Slide 96

Slide 96 text

検索アルゴリズム 検索オブジェクトの種類 95 デフォルト 愚直に検索。(今までの std::search と同じ※) 前処理しないので、検索パターンや検索対象範囲 が短い場合、検索を1回しかしない場合等ではわり と有利。 余計なメモリを食わない。 イテレータが前方イテレータでOK。 名前が簡単なのでとても良い。(個人の感想です) ※ std::search と同じと書いたけど、実は規格書には何 も書いてない…

Slide 97

Slide 97 text

検索アルゴリズム 検索オブジェクトの種類 96 template> class default_searcher { public: default_searcher( ForwardIterator1 pat_first, ForwardIterator1 pat_last, BinaryPredicate pred = BinaryPredicate()); template pair operator()(ForwardIterator2 first, ForwardIterator2 last) const; };

Slide 98

Slide 98 text

検索アルゴリズム 検索オブジェクトの種類 97 Boyer-Moore Boyer-Moore法で検索。 ワーストケースがO(n)。(nは検索対象範囲の長さ) 前処理時にテーブルを2つ作るので、前処理時間 がかかるし、結構メモリも食う。 検索パターンや検索対象範囲が長い場合、あるい は、同じ検索パターンで何度も検索する場合には 有利。 ランダムアクセスイテレータが必要。 名前が難しいので辛い。(個人の(ry

Slide 99

Slide 99 text

検索アルゴリズム 検索オブジェクトの種類 98 template::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_searcher { public: boyer_moore_searcher( RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); template pair operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; };

Slide 100

Slide 100 text

検索アルゴリズム 検索オブジェクトの種類 99 Boyer-Moore-Horspool Boyer-Moore-Horspool法で検索。 ワーストケースは愚直なのと一緒だが、大抵は O(n)でいける。 前処理時に作るテーブルは1つだけなので、Boyer- Moore法よりは前処理時間もメモリ食わない。 なので、わりとバランスがいいのかな? ランダムアクセスイテレータが必要。 名前がとても難しいのでとても辛い。(個人の(ry

Slide 101

Slide 101 text

検索アルゴリズム 検索オブジェクトの種類 100 template::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_horspool_searcher { public: boyer_moore_horspool_searcher( RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); template pair operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; };

Slide 102

Slide 102 text

検索アルゴリズム 検索オブジェクトの種類 101 重要 イテレータの参照先はオブ ジェクト作る時と検索する時 で変わったらダメ!!! 変えちゃうと検索が発狂しちゃう…

Slide 103

Slide 103 text

検索アルゴリズム 検索オブジェクトの種類 102 重要その2 じゃなくて

Slide 104

Slide 104 text

検索アルゴリズム 103 悲報

Slide 105

Slide 105 text

検索アルゴリズム 悲報 104 Clang はまだ(?) default_searcher しか対応してない… VC++は対応してるぞ!すごいぞ!

Slide 106

Slide 106 text

検索アルゴリズム 105 完 終 制作・著作 ━━━━━ ⓃⒽⓀ

Slide 107

Slide 107 text

検索アルゴリズム 106 あれ? std::search の オーバーロード は?

Slide 108

Slide 108 text

検索アルゴリズム 107 template ForwardIterator search(ForwardIterator first, ForwardIterator last, const Searcher& searcher); 以下と一緒 return searcher(first, last).first; second 棄てられとる…

Slide 109

Slide 109 text

検索アルゴリズム 108 std::search は 要らない子… ※ 実行ポリシー指定できるヤツを除く

Slide 110

Slide 110 text

検索アルゴリズム 109 完 終 制作・著作 ━━━━━ ⓃⒽⓀ

Slide 111

Slide 111 text

コンテナの不完全型 サポート 110

Slide 112

Slide 112 text

コンテナの不完全型サポート 111 N3890 Container http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3890.html N4056 Minimal incomplete type support for standard containers http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4056.html N4371 Minimal incomplete type support for standard containers, revision 2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4371.html N4390 Minimal incomplete type support for standard containers, revision 3 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4390.html N4510 Minimal incomplete type support for standard containers, revision 4 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4510.html

Slide 113

Slide 113 text

コンテナの不完全型サポート 112 導入の背景

Slide 114

Slide 114 text

コンテナの不完全型サポート 導入の背景 113 不完全型の コンテナが 使いたい!

Slide 115

Slide 115 text

コンテナの不完全型サポート 導入の背景 114 ???

Slide 116

Slide 116 text

コンテナの不完全型サポート 導入の背景 115 こんなの出来たらうれしいよね? by 提案ペーパー struct Entry { std::list messages; // ここではまだ ... // Entry が不完全型 }; 要は、要素型の定義がまだ不完全な状態でもコンテ ナを使いたい。 それ、Boost.Container で出来るよ

Slide 117

Slide 117 text

コンテナの不完全型サポート 116 対応

Slide 118

Slide 118 text

コンテナの不完全型サポート 対応 117 ただし、条件付き…

Slide 119

Slide 119 text

コンテナの不完全型サポート 対応 118 条件① 対応コンテナは以下の3つだけ vector list forward_list 何で絞ったのかな…

Slide 120

Slide 120 text

コンテナの不完全型サポート 対応 119 条件② アロケータが以下を満たす 1. アロケータが完全型 2. 対応する allocator_traits のメン バ型は value_type 以外完全型 アロケータ完全性、と言うらしい…

Slide 121

Slide 121 text

コンテナの不完全型サポート 対応 120 条件➂ コンテナの、特殊化されたいず れかのメンバが、参照される前 には完全型になっている まぁそりゃあ使うときに完全型じゃないと困るよね…

Slide 122

Slide 122 text

コンテナの不完全型サポート 121 完 終 制作・著作 ━━━━━ ⓃⒽⓀ