Share
Embed
C++17の新機能 落穂拾い / new features of C++17 - gleaner
C++17 で追加されたライブラリ機能の紹介です。
一応調べながら書いてはいますが、力量の問題でいろいろ間違ってるかもです。
相変らず使用例が無いのは単なる力不足です…
Miutsuru kariya
March 28, 2019
Transcript
122 slides
-
*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 -
*this のコピーキャプチャ 導入の背景 6 今までの問題点 • デフォルトコピーキャプチャを使うと、さもコピーキャプ チャされてる風に(?)メンバ変数名だけでアクセス可能 になるが、実際には this
ポインタがコピーされてるだけな ので、メンバ変数は実質参照キャプチャになっている。 • *this をコピーキャプチャするには初期化キャプチャを使 用して別の変数を導入する必要がある。 • デフォルトコピーキャプチャと *this からの初期化キャプ チャを両方使用しても、間違ってメンバ変数名単体でアク セスすると参照アクセスになってしまう。 -
*this のコピーキャプチャ 導入の背景 7 #include <iostream> 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 経由でのアクセス なので、実質参照キャプチャ -
*this のコピーキャプチャ 導入の背景 8 #include <iostream> 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 を導入して、 無理やりコピーキャプチャに。 でもアクセスが面倒… -
*this のコピーキャプチャ 導入の背景 9 #include <iostream> 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 経由でアクセスできちゃう… -
*this のコピーキャプチャ 対応 12 #include <iostream> 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 がコピーキャプチャされる。 アクセスも簡単! -
*this のコピーキャプチャ 対応 13 #include <iostream> 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 のコピーキャプチャ 対応 14 #include <iostream> 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 のコピーキャプチャ 悲報 16 • デフォルトコピーキャプチャでメンバ変数が実質 参照キャプチャになるのは変わってない。 • C++20 でデフォルトコピーキャプチャで
this をコ ピーキャプチャする挙動が非推奨になるが、 C++17 ではまだデフォルトコピーキャプチャ指定 時に this を指定できない。 -
*this のコピーキャプチャ 悲報 17 #include <iostream> 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 のコピーキャプチャ 悲報 18 #include <iostream> 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 にアクセスするのは非推奨… -
*this のコピーキャプチャ 悲報 19 #include <iostream> 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 ではこの書き方はエラー -
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 -
emplace の戻り値型変更 導入の背景 25 emplace_front や emplace_back の直後にその 要素アクセスすることが多い んだが、こいつらの戻り値型
が void でまんどくさい… 普通の emplace は iterator とか返ってくるのにね… -
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); -
emplace の戻り値型 対応 29 対象 1.シーケンスコンテナの emplace_front、emplace_backという 名のメンバ関数 2.コンテナアダプタの queue::emplace、
stack::emplace priority_queue::emplace は入らないのね… -
emplace の戻り値型変更 対応 30 ペーパーに載ってた例(改) // ① 格納してすぐにメンバ関数呼び出し my_container.emplace_back(…).do_something(…); //
② 格納してすぐに関数に引き渡し do_something_else(my_container.emplace_back(…)); // ➂ デフォルト構築してすぐにファイルから読み込み my_container.emplace_back().read(file_stream); -
emplace の戻り値型変更 対応 31 push 系はやらないの? ⇓ push するって事は既にオブジェクト持ってる から不要なことが多いし、どうしても格納後オ
ブジェクトにアクセスしたければ emplace 使 えばいいっしょ(ペーパーより超訳) -
emplace の戻り値型変更 対応 32 下記の2点がよくわかりませんでした… • 他の emplace 系の戻り値型は iterator
な のに何で参照なの? • 何で std::priority_queue::emplace は対象 外なの? 教えて!エロい人!!! -
単純な文字列変換 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 -
単純な文字列変換 導入の背景 37 既存ライブラリの問題点 • 書式指定文字列うぜぇ • 動的メモリ割当強制うぜぇ • ロケールうぜぇ
• 仮想関数呼び出しうぜぇ • バッファオーバーラン怖ぇ • 入力文字列のエラー分かんねぇのうぜぇ • 入力文字列のスペース勝手に無視すんのうぜぇ • 頭の0x勝手に解釈すんのうぜぇ -
単純な文字列変換 導入の背景 39 既存機能 うぜぇとこ sprintf ロケール、書式指定文字列、バッファオーバーラン snprintf ロケール、書式指定文字列 sscanf
ロケール、書式指定文字列 atol ロケール、エラー発生不明 strtol ロケール、空白無視、0x勝手に解釈 strstream ロケール、空白無視 stringstream ロケール、空白無視、動的メモリ割当 num_put / num_get facets ロケール、仮想関数呼び出し to_string ロケール、動的メモリ割当 stoi etc. ロケール、動的メモリ割当、空白無視、0x勝手に解釈、 エラー時例外 -
単純な文字列変換 対応 43 新規ライブラリの特徴 • 書式指定は文字列じゃない • 動的メモリ割当しない • ロケール無視
• 仮想関数呼び出ししない • バッファオーバーランしない • 戻り値でエラー返す • 入力文字列のスペース無視しない • 頭の0x解釈しない -
単純な文字列変換 対応 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 任意の浮動小数点型。 -
単純な文字列変換 対応 45 文字列から数値への変換 struct from_chars_result { const char* ptr;
//数値として解釈できない文字へのポインタ errc ec; //変換失敗した場合のエラーコード }; enum class chars_format { scientific = 値は未規定, // %e と同じ fixed = 値は未規定, // %f と同じ hex = 値は未規定, // %a とだいたい同じ general = fixed | scientific // %g と同じ }; -
単純な文字列変換 対応 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); -
単純な文字列変換 対応 47 数値から文字列への変換 struct to_chars_result { char* ptr; //
出力された最後の文字の次へのポインタ errc ec; // 変換失敗した場合のエラーコード }; -
単純な文字列変換 使い方 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 で受けてるけど普通は構造化束縛使うよね… -
単純な文字列変換 使い方 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{}); -
単純な文字列変換 使い方 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 は数値として解釈できない文 字(この場合は"+")を指す。 -
単純な文字列変換 使い方 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 は数値として解釈できない文字を指すので、最 後の数字の次の文字(つまり終端)を指している。 (変換対象の文字の次ではない) -
単純な文字列変換 使い方 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{}); -
単純な文字列変換 使い方 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だけ変換されてる。(わりとワナ) -
単純な文字列変換 使い方 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{}); -
単純な文字列変換 使い方 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{}); -
単純な文字列変換 使い方 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); -
単純な文字列変換 使い方 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{}); -
単純な文字列変換 使い方 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 は先頭を指すらしい。(たぶん使わない) -
単純な文字列変換 使い方 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{}); -
単純な文字列変換 使い方 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' で終端されるわけではないので注意! -
単純な文字列変換 使い方 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"は付かない。(付ける方法は無い) 英文字の出力は小文字。(大文字バージョンは無い) -
単純な文字列変換 使い方 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{}); -
単純な文字列変換 使い方 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 は最後を指すらしい。(たぶん使わない) 変換エラーの場合、バッファの中身は未規定 -
単純な文字列変換 使い方 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 とは違うので注意。 -
単純な文字列変換 使い方 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 と違う) -
単純な文字列変換 使い方 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 の対応する書式と同じ。 (精度の指定はできるけど幅の指定はできないよ) -
単純な文字列変換 使い方 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は付かない。 -
単純な文字列変換 悲報 72 何と VC++ 14.16 は 浮動小数点数も それなりに 対応してる!
すごいぞ VC++! まだ不完全ではあるけど、ちょっと見直した… -
検索アルゴリズム 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 -
検索アルゴリズム 導入の背景 82 template<class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search(ForwardIterator1 first1,
ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); ※ [first1, last1) が検索される範囲、[first2, last2) が検索パ ターン範囲なので、前処理結果を保存できる余地が無さそう… -
検索アルゴリズム 対応 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'; -
検索アルゴリズム 対応 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 アルゴリズム -
検索アルゴリズム 対応 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'; 検索対象範囲をッ、関数呼び出し演算子の引数に してッ、実際に検索するッ!!! 同じオブジェクトで何度でも検索できるぞッ!!! -
検索アルゴリズム 対応 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) がッ、イテレータのペアで返ってくるッ!!! ※ 見つからなかったらどっちも検索対象範囲の最後 -
検索アルゴリズム 対応 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バイトである事に注意!) -
検索アルゴリズム 対応 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バイトである事に注意!) あ、「柿」(かき)はこの文字だけで、あとは「杮」(こけら)です。 見ればわかると思うけど(?)、念のため。 -
検索アルゴリズム 検索オブジェクトの種類 95 デフォルト 愚直に検索。(今までの std::search と同じ※) 前処理しないので、検索パターンや検索対象範囲 が短い場合、検索を1回しかしない場合等ではわり と有利。
余計なメモリを食わない。 イテレータが前方イテレータでOK。 名前が簡単なのでとても良い。(個人の感想です) ※ std::search と同じと書いたけど、実は規格書には何 も書いてない… -
検索アルゴリズム 検索オブジェクトの種類 96 template<class ForwardIterator1, class BinaryPredicate = equal_to<>> class
default_searcher { public: default_searcher( ForwardIterator1 pat_first, ForwardIterator1 pat_last, BinaryPredicate pred = BinaryPredicate()); template<class ForwardIterator2> pair<ForwardIterator2, ForwardIterator2> operator()(ForwardIterator2 first, ForwardIterator2 last) const; }; -
検索アルゴリズム 検索オブジェクトの種類 97 Boyer-Moore Boyer-Moore法で検索。 ワーストケースがO(n)。(nは検索対象範囲の長さ) 前処理時にテーブルを2つ作るので、前処理時間 がかかるし、結構メモリも食う。 検索パターンや検索対象範囲が長い場合、あるい は、同じ検索パターンで何度も検索する場合には
有利。 ランダムアクセスイテレータが必要。 名前が難しいので辛い。(個人の(ry -
検索アルゴリズム 検索オブジェクトの種類 98 template<class RandomAccessIterator1, class Hash = hash<typename iterator_traits<RandomAccessIterator1>::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<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; }; -
検索アルゴリズム 検索オブジェクトの種類 99 Boyer-Moore-Horspool Boyer-Moore-Horspool法で検索。 ワーストケースは愚直なのと一緒だが、大抵は O(n)でいける。 前処理時に作るテーブルは1つだけなので、Boyer- Moore法よりは前処理時間もメモリ食わない。 なので、わりとバランスがいいのかな?
ランダムアクセスイテレータが必要。 名前がとても難しいのでとても辛い。(個人の(ry -
検索アルゴリズム 検索オブジェクトの種類 100 template<class RandomAccessIterator1, class Hash = hash<typename iterator_traits<RandomAccessIterator1>::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<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; }; -
検索アルゴリズム 107 template<class ForwardIterator, class Searcher> ForwardIterator search(ForwardIterator first, ForwardIterator
last, const Searcher& searcher); 以下と一緒 return searcher(first, last).first; second 棄てられとる… -
コンテナの不完全型サポート 111 N3890 Container<Incomplete Type> 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 -
コンテナの不完全型サポート 導入の背景 115 こんなの出来たらうれしいよね? by 提案ペーパー struct Entry { std::list<Entry>
messages; // ここではまだ ... // Entry が不完全型 }; 要は、要素型の定義がまだ不完全な状態でもコンテ ナを使いたい。 それ、Boost.Container で出来るよ -
コンテナの不完全型サポート 対応 119 条件② アロケータが以下を満たす 1. アロケータが完全型 2. 対応する allocator_traits
のメン バ型は value_type 以外完全型 アロケータ完全性、と言うらしい…