Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」

1,278 views

Published on

C++1zに導入される見込みの高くなったライブラリ string_view についてお話しします。

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,278
On SlideShare
0
From Embeds
0
Number of Embeds
899
Actions
Shares
0
Downloads
1
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」

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

×