boost.勉強会 #21...

71
C++1zstring_view導入されてうれしいので 紹介します H.Hiro (@h_hiro_)

Upload: hiro-h

Post on 21-Mar-2017

1.609 views

Category:

Technology


0 download

TRANSCRIPT

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

C++1zにstring_viewが 導入されてうれしいので

紹介します

H.Hiro (@h_hiro_)

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

お久しぶりです H.Hiroです

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

•名古屋で研究の仕事しています •C++はかなり使います (新しいアルゴリズムを考えて試す) •Boostは最近ちょっとご無沙汰… •最近、開発したいプログラムのネタが 思い浮かぶも時間が取れず停滞中

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

今回のテーマ

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

部分文字列

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

みんな 使いますよね

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

std::string foo = "Boost C++ Library"; std::string bar = foo.substr(6, 3); std::cout << bar << std::endl; // prints "C++"

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

ただ、これ C++を使っている人だと

「使いたくない」 ってときもありませんか

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

ただ、これ C++を実行効率重視の ために使っている人だと

「使いたくない」 ってときもありませんか

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

std::string foo = "Boost C++ Library"; std::string bar = foo.substr(6, 3);

ヒープ領域 (newとかで確保されたメモリ領域に利用する)

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

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

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

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 + +

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

std::string foo = "Boost C++ Library"; std::string bar = foo.substr(6, 3); std::cout << bar << std::endl; // prints "C++"

substrする 文字数ぶんの

メモリを 確保する必要

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

そこで、 考えられる方法

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

そもそも、文字列って 連続したメモリ領域に 確保されてるんだから

B o o s t C + + L i b r a r y

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

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

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

これが 今回紹介する string_viewの 大枠です

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

std::string foo = "Boost C++ Library"; std::pair<const char*, std::size_t> bar = std::make_pair( , );

string_viewとは 単に「 と を組にして保持する クラス」です

&foo[6] 3

始点のポインタ 長さ

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

ちなみに

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

実装の説明は これでほとんど 終わりです

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

が、もちろん、 これで

終わるわけは ありません

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

「実際の使い方」 「どんな場面で使われているのか」 「私が何でこれを時間をかけて紹介 しようと思ったのか」 なども紹介します

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

使ってみる

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

string_viewの実装状況 gccの場合:gcc7で対応予定 https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html

clangの場合:? Visual Studioの場合:?

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

標準で入ること 前提でコードを

書くのは もう少し待つとして

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

Boost.string_view を使います

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

•もともと、Boostでは 「boost::string_ref」という クラス名でした •Boost 1.61.0以降 「boost::string_view」が追加され 若干機能が増えています ※C++標準として当初提案されたもの(N3442) のみならず、より新しいもの(N4480)を 反映させているようです

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

boost.string_viewにあって boost.string_refにないもの traits対応 move対応(?) noexcept対応

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

使う

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

ヘッダファイル だけで利用できる

Boost ライブラリなので

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

Boostのサイトで ダウンロードして

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

そのパスを読み込む ようにすればいいだけ

$ g++ sample.cpp -I ダウンロードしたパス

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

コード例

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

#include <boost/utility/string_view.hpp> // "utility"必要です!

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

// さっきのコードを // boost.string_viewで // 書き換えてみる std::string foo = "Boost C++ Library"; boost::string_view bar(&foo[6], 3); std::cout << bar << std::endl;

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

// 元の文字列が変わると、 // string_view側も変わる // (あくまで、元の文字列の // 一部を参照しているだけ) (前ページに続いて) foo[7] = 'P'; foo[8] = 'P'; std::cout << bar << std::endl;

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

// 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);

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

// 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になる

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

APIがstd::stringと 一貫性を持たせて

あるので

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

std::stringを 使い慣れていれば そんなに手間は 感じないだろうし

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

今まで引数を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から暗黙に変換可

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

「本当はstd::stringじゃないんだけど std::stringみたいな性質を持ってる から、似た扱いができるようにしよう」 と設計されてるのがポイントです (デザインパターンでは 「Proxy(代理)パターン」といいます)

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

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

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

string_viewは どんな場面で

使われているのか

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

最初に 言いたかったこと

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

私も、ほぼ同じ 機能のライブラリが 欲しくて、作った ことがあった

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

fundoshi.hpp (2011年初版公開) https://github.com/maraigue/fundoshi.hpp

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

fundoshi.hpp (2011年初版公開) https://github.com/maraigue/fundoshi.hpp

参照:

2012.11.17 CLR/H&札幌C++勉強会 発表資料

http://www.slideshare.net/maraigue/20121117-clrhc-fundoshihpp

このときは、 文字列検索アルゴリズムのために

利用していた

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

かなり後になって 同じようなことを している人が

多数いると知った

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

汎用的なライブラリ •StringPiece (Google)

ライブラリの一機能として提供 •Qtの "QStringRef" •Swiftの "CFStringRef" •JUCEの "StringRef"

内部処理のために?利用 •LLVMの "StringRef" •gRPCの "string_ref"

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

だから、 Boostにも入ったし のちに標準化も されたといえる

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

実際、 どんな場面で

使われているのか

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

利用例: Qtの "QStringRef" がある箇所 •QRegularExpressionMatch (正規表現のマッチング結果) •XMLパーサーの解析結果

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

QString foo("boost C++ library"); QRegularExpression pat("C.."); QRegularExpressionMatch mat = pat.match(foo); mat.capturedRef(); // ↑マッチした部分をQStringRefで返す

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

Boost.String_Refのドキュメントに 書かれていた、利用が見込まれる ケース •HTTPレスポンスから、必要な 部分だけを返す

さっきの「XMLパーサーの解析結果」 と似た用法ですね

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

利用例: LLVMの "StringRef" がある箇所 •(おそらく) メソッド名等を保持する部分 (完全に読めているわけではなくて、 コード中にStringRefが見つかった場所 近辺を読んだだけですが、そんな雰囲気 だった)

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

string_refを標準化しようという 提案文書(N3442)にて 利用を想定していたケース

(1/3)

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

引数の型はstd::stringであるが、 「std::string以外の値を引数として 渡す場合」は呼び出す側でコピーを 取っておく必要がある場合

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

string_refを標準化しようという 提案文書(N3442)にて 利用を想定していたケース

(2/3)

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

char*ポインタと文字列長を 組にした引数を受け取っているような 箇所の置き換え •パフォーマンスを理由にそうする ことを想定? •内部的にC言語のAPIを呼ぶ場合 とか?

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

string_refを標準化しようという 提案文書(N3442)にて 利用を想定していたケース

(3/3)

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

•連続したメモリ上に確保されている ものであれば何でも扱える、という 型が必要な場合

std::stringもstd::vector<char>も 統一的に扱いたいとか?

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

部分文字列を 取る操作が あるならば、

これが使えないか 考えてみよう

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

といえるくらい 汎用的な

ライブラリです

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

おわりに

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

部分文字列を 取るときに

付きまとう問題 「余計なメモリ確保」

B o o s t C + + L i b r a r y

C + +

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

それをスマートに 解決してくれる string_view

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

祝・ 標準化が有力に!

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

ありがとう ございました