狠狠撸
Submit Search
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
?
5 likes
?
9,030 views
Hiro H.
C++1zに導入される見込みの高くなったライブラリ string_view についてお話しします。
Read less
Read more
1 of 71
Download now
Downloaded 10 times
More Related Content
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
1.
C++1zにstring_viewが 導入されてうれしいので 紹介します H.Hiro (@h_hiro_)
2.
お久しぶりです H.Hiroです
3.
?名古屋で研究の仕事しています ?C++はかなり使います (新しいアルゴリズムを考えて試す) ?Boostは最近ちょっとご無沙汰… ?最近、開発したいプログラムのネタが 思い浮かぶも時間が取れず停滞中
4.
今回のテーマ
5.
部分文字列
6.
みんな 使いますよね
7.
std::string foo = "Boost
C++ Library"; std::string bar = foo.substr(6, 3); std::cout << bar << std::endl; // prints "C++"
8.
ただ、これ C++を使っている人だと 「使いたくない」 ってときもありませんか
9.
ただ、これ C++を実行効率重視の ために使っている人だと 「使いたくない」 ってときもありませんか
10.
std::string foo = "Boost
C++ Library"; std::string bar = foo.substr(6, 3); ヒープ領域 (newとかで確保されたメモリ領域に利用する)
11.
std::string foo = "Boost
C++ Library"; std::string bar = foo.substr(6, 3); ヒープ領域 (newとかで確保されたメモリ領域に利用する) B o o s t C + + L i b r a r y
12.
std::string foo = "Boost
C++ Library"; std::string bar = foo.substr(6, 3); ヒープ領域 (newとかで確保されたメモリ領域に利用する) B o o s t C + + L i b r a r y C + +
13.
std::string foo = "Boost
C++ Library"; std::string bar = foo.substr(6, 3); std::cout << bar << std::endl; // prints "C++" substrする 文字数ぶんの メモリを 確保する必要
14.
そこで、 考えられる方法
15.
そもそも、文字列って 連続したメモリ領域に 確保されてるんだから B o o
s t C + + L i b r a r y
16.
B o o
s t C + + L i b r a r y std::string foo = "Boost C++ Library"; std::pair<const char*, std::size_t> bar = std::make_pair( , ); 別にこれで いいじゃないか 長ささえわかればよい始点のポインタと &foo[6] 3
17.
これが 今回紹介する string_viewの 大枠です
18.
std::string foo =
"Boost C++ Library"; std::pair<const char*, std::size_t> bar = std::make_pair( , ); string_viewとは 単に「 と を組にして保持する クラス」です &foo[6] 3 始点のポインタ 長さ
19.
ちなみに
20.
実装の説明は これでほとんど 終わりです
21.
が、もちろん、 これで 終わるわけは ありません
22.
「実際の使い方」 「どんな場面で使われているのか」 「私が何でこれを時間をかけて紹介 しようと思ったのか」 なども紹介します
23.
使ってみる
24.
string_viewの実装状況 gccの場合:gcc7で対応予定 https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html clangの場合:? Visual Studioの場合:?
25.
標準で入ること 前提でコードを 書くのは もう少し待つとして
26.
Boost.string_view を使います
27.
?もともと、Boostでは 「boost::string_ref」という クラス名でした ?Boost 1.61.0以降 「boost::string_view」が追加され 若干機能が増えています ※C++標準として当初提案されたもの(N3442) のみならず、より新しいもの(N4480)を 反映させているようです
29.
boost.string_viewにあって boost.string_refにないもの traits対応 move対応(?) noexcept対応
30.
使う
31.
ヘッダファイル だけで利用できる Boost ライブラリなので
32.
Boostのサイトで ダウンロードして
33.
そのパスを読み込む ようにすればいいだけ $ g++ sample.cpp -I
ダウンロードしたパス
34.
コード例
35.
#include <boost/utility/string_view.hpp> // "utility"必要です!
36.
// さっきのコードを // boost.string_viewで //
書き換えてみる std::string foo = "Boost C++ Library"; boost::string_view bar(&foo[6], 3); std::cout << bar << std::endl;
37.
// 元の文字列が変わると、 // string_view側も変わる //
(あくまで、元の文字列の // 一部を参照しているだけ) (前ページに続いて) foo[7] = 'P'; foo[8] = 'P'; std::cout << bar << std::endl;
38.
// string_viewのコンストラクタ // 引数1つ boost::string_view
sv1("foo"); // const char* std::string b("bar"); boost::string_view sv2(b); // std::string boost::string_view sv3(sv2); // string_view // 引数2つ // 「const char* ポインタ, 長さ」。 // 「std::string, 長さ」などはできない。 boost::string_view sv4(sv1.data(), 3); boost::string_view sv4(b.data(), 3);
39.
// string_viewのAPI // std::stringと似たものが揃っている //
※内容を変更するAPIはない boost::string_view sv1("boost"); std::cout << sv1[2] << std::endl; // 'o' boost::string_view sv6 = sv1.substr(1, 3); std::cout << sv6 << std::endl; // "oos" std::cout << sv1.find("oo") << std::endl; // 見つけられる。この場合1になる
40.
APIがstd::stringと 一貫性を持たせて あるので
41.
std::stringを 使い慣れていれば そんなに手間は 感じないだろうし
42.
今まで引数をstd::stringに していたものを、string_viewに 置き換えるのも楽 char foo(const std::string
& bar) { return bar[0]; } ↓ char foo(boost::string_view bar) { return bar[0]; } ※string_viewはstd::stringから暗黙に変換可
43.
「本当はstd::stringじゃないんだけど std::stringみたいな性質を持ってる から、似た扱いができるようにしよう」 と設計されてるのがポイントです (デザインパターンでは 「Proxy(代理)パターン」といいます)
44.
boost::string_viewで利用できるメソッド <std::stringと共通> size length max_size
empty begin end (c, r付き含む) front back at data clear operator[] compare (各種比較演算子を含む) find (rfindなども含む) substr <独自のもの> remove_prefix remove_suffix
45.
string_viewは どんな場面で 使われているのか
46.
最初に 言いたかったこと
47.
私も、ほぼ同じ 機能のライブラリが 欲しくて、作った ことがあった
48.
fundoshi.hpp (2011年初版公開) https://github.com/maraigue/fundoshi.hpp
49.
fundoshi.hpp (2011年初版公開) https://github.com/maraigue/fundoshi.hpp 参照: 2012.11.17 CLR/H&札幌C++勉強会 発表資料 http://www.slideshare.net/maraigue/20121117-clrhc-fundoshihpp このときは、 文字列検索アルゴリズムのために 利用していた
50.
かなり後になって 同じようなことを している人が 多数いると知った
51.
汎用的なライブラリ ?StringPiece (Google) ライブラリの一機能として提供 ?Qtの "QStringRef" ?Swiftの
"CFStringRef" ?JUCEの "StringRef" 内部処理のために?利用 ?LLVMの "StringRef" ?gRPCの "string_ref"
52.
だから、 Boostにも入ったし のちに標準化も されたといえる
53.
実際、 どんな場面で 使われているのか
54.
利用例: Qtの "QStringRef" がある箇所 ?QRegularExpressionMatch (正規表現のマッチング結果) ?XMLパーサーの解析結果
55.
QString foo("boost C++
library"); QRegularExpression pat("C.."); QRegularExpressionMatch mat = pat.match(foo); mat.capturedRef(); // ↑マッチした部分をQStringRefで返す
56.
Boost.String_Refのドキュメントに 書かれていた、利用が見込まれる ケース ?HTTPレスポンスから、必要な 部分だけを返す さっきの「XMLパーサーの解析結果」 と似た用法ですね
57.
利用例: LLVMの "StringRef" がある箇所 ?(おそらく) メソッド名等を保持する部分 (完全に読めているわけではなくて、 コード中にStringRefが見つかった場所 近辺を読んだだけですが、そんな雰囲気 だった)
58.
string_refを標準化しようという 提案文書(N3442)にて 利用を想定していたケース (1/3)
59.
引数の型はstd::stringであるが、 「std::string以外の値を引数として 渡す場合」は呼び出す側でコピーを 取っておく必要がある場合
60.
string_refを標準化しようという 提案文書(N3442)にて 利用を想定していたケース (2/3)
61.
char*ポインタと文字列長を 組にした引数を受け取っているような 箇所の置き換え ?パフォーマンスを理由にそうする ことを想定? ?内部的にC言語のAPIを呼ぶ場合 とか?
62.
string_refを標準化しようという 提案文書(N3442)にて 利用を想定していたケース (3/3)
63.
?連続したメモリ上に確保されている ものであれば何でも扱える、という 型が必要な場合 std::stringもstd::vector<char>も 統一的に扱いたいとか?
64.
部分文字列を 取る操作が あるならば、 これが使えないか 考えてみよう
65.
といえるくらい 汎用的な ライブラリです
66.
おわりに
67.
部分文字列を 取るときに 付きまとう問題 「余計なメモリ確保」 B o o
s t C + + L i b r a r y C + +
68.
それをスマートに 解決してくれる string_view
69.
祝? 標準化が有力に!
70.
参考資料 C++標準化提案 ? N3442(string_refの提案) http://www.open-std.org/jtc1/sc22/wg21/docs/ papers/2012/n3442.html ? N4606(C++1zのドラフト) http://www.open-std.org/JTC1/SC22/WG21/docs/ papers/2016/n4606.pdf 実装(本資料中で示したもの関連) ?
Boost http://www.boost.org/ ? Qt https://www.qt.io/ ? LLVM http://www.llvm.org/
71.
ありがとう ございました
Download