今日はBoost C++ Librariesを遊び倒す会(ATND)に参加しています。ustreamもあるそうです。
C++は新卒の頃に数ヶ月触ったキリで、先月勉強再開し始めたばかりなので、正直心配です(ぉ。Hello Worldだけは今朝実行しました!
Boostライブラリ一周の旅 - faith_and_braveさん
- 1.40.0のライブラリの概要
- テンプレートメタプログラミング
- テンプレートのインスタンスかを利用
- メタ関数: テンプレートパラメータ + typedef
- 分岐は特殊化、呼び出しは適用
- メタ関数の例を紹介
- Accumulators: 統計計算
- Any: あらゆる型の保持
- Array: 組み込み配列にコンテナインタフェースを付加
ここでマシントラブルで再起動中断w
- Asio: 非同期ネットワーク
- Assign: コンテナの構築を簡単にかける(v += 3, 1, 4とか)
- Bimap: キー←→バリュー の相互呼び出しが機能なmap( left と right )
- Bind: 部分評価( 例えば、thisをbindすると便利 )
- Circular Buffer: 循環バッファ
- Compressed Pair: 最適化がされやすいpair
- Concept Check: テンプレートパラメータに制約を加える
- コンパイルエラーをわかりやすくするため
- Conversion: 型変換
- lexical_cast: 数値と文字列
- polymorphic_downcast: デバグ時のみdynamic_cast的なstatic_cast
- polymorphic_cast: 例外を投げる dynamic_cast
- CRC: チェックサムとか
- Date Time: 日付計算
- Dynamic Bitset: Static bitsetの動的版
- Enable If: 型特性でオーバロード(整数型(is_integral)と整数型以外でわける、など)
- Exception: catchの度にエラー情報を足せる例外
- Filesystem: OS非依存のパス、ファイル、ディレクトリ操作
- Flyweight: デザパタ(同じオブジェクトであればリソースを共有する)
- Foreach: BOOST_FOREACH
- Format: sprintf を std::string に対応させたもの
- Function: 関数ポインタと関数オブジェクトを同じ形式で使えるようにする
- Function Types: 関数のメタ情報
- Fusion: タプルのライブラリ (Fusionはコンパイル時と実行時の融合の意)
- コンパイル時にタプルの定義を操作(pop_backなど)、実行時にタプルの操作(for_eachなど)
- GIL: 画像処理
- Graph: グラフ構造
- Interprocess: 共有メモリ
- Interval: 区間計算 (in 区間 とか 区間の合成とか)
- Intrusive: オブジェクトの参照を持つコンテナ(侵入コンテナ)
- IO State Server: IO Streamの状態管理
- 例えば、スコープを抜けたら、Streamの状態が戻るようにする
- Iostreams: IO Streamの拡張
- 例えば、StreamへのUNIXライクなfilterの実装
- Iterators: イテレータの定義を簡単にする
- Lambda: 動的に関数オブジェクトを作る( _1 のようなプレースフォルダによる )
- Math: 数学系
- Member Function: mem_funとmem_fun_ref を一般化
- MPL: テンプレートメタプログラミング用のライブラリ
- MultiArray: 多次元配列。サイズがとれたりする。
- Multi Index: ソート順やアクセサ順を複数持つコンテナ
- Numeric Conversion: 数値型を変換 (DoubleToInt等)
- Operators: 演算子の自動生成( > を定義すれば <= や >= が自動生成 )
- Optional: 無効値( boost::none )の定義
- Parameter: 名前つき引数(f( _name="hoge" ) を args[_name] で受ける感じ)
- Pointer Container: ヒープオブジェクトを格納するコンテナ。メモリの節約。
- Pool: メモリのプール
- Preprocessor: プリプロセッサによるメタプログラミングのライブラリ
- 例えば、コード自動生成とか
- Property Map: iterator_traitsの拡張版
- Proto: Expression Template 用のライブラリ。評価を後でできる。
- Python: C++とPythonの相互利用のライブラリ (BOOS_PYTHON_MODULE とか def() とか)
- Random: 乱数生成エンジンと分布を分けて指定可能
- Range: ベクターや配列を同じ感じ(begin, end)で使う
- Ref: テンプレートパラメータを明示的に参照とする
- Scope Exit: 関数を抜ける時に実行されるブロック
- Serialization: シリアライズとデシリアライズ(serializeメソッドを定義)
- Signals2: シグナルとスロット(イベント系)
- Smart Pointers: new したら勝手にdeleteされるポインタ
- Spirit: 構文解析( qi::parseとか >> とか )
- Statechart: 状態マシン
- meta state machine ってのもあるらしい
- Static Assert: コンパイル時のアサート。BOOST_STATIC_ASSERT
- String Algo: 文字列のアルゴリズム。to_upperとかtrim_rightとか
- Swap: std::swapの強化版。特化したswapがすでにあればそのロジックを使うもの。
- System: OS非依存のエラーコード
- Test: 単体テストライブラリ
- Thread: スレッド。joinとかの実装。移植性。
- Timer: 時間計測。定義 → t.elapsed() までの時間
- Tokenizer: トークン分割
- Tribool: 3値のbool。true, false, indeterminate
- Tuple: std::pairの3つ以上版。戻り値として使う等。
- 取り出しは tie(n, ignore, d) (ignoreは捨て)
- Typeof: 型推論。BOOST_TYPEOF(c++0xのdecltype)とBOOST_AUTO(C++0xのauto)
- uBLAS: 線形代数。高速らしい
- Units: 単位変換。mとか。
- Unordered: ハッシュテーブルによる連想コンテナ。std::mapとほぼ同じ
- Utility
- boost::noncopyable: コピー禁止クラスを作る
- boost::result_of : 戻り値の型を取得
- Variant: 指定した型の格納ができるUnion
- Wave: C++,C99プリプロセッサの拡張ができる
- Xpressive: 正規表現ライブラリ
この時点でスケジュールの40分押しですねえ・・・。
Boost.MultiIntrusivedex - k.inabaさん
MultiIndex
- データ構造好き
- MultiIndex 複数のインデックス
- 例: 2つのIDによる検索、ソート
- for_eachではだめ
- std::setを使って、検索を速く
- 複数パターンでの検索 → Boost.MultiIndex
- boost.MultiIndex
- multi_index_containerでコンテナを定義
- indexed_by, orderd_unique, sequenced でインデックス指定
- get<インデックス番号> のような使い方
- Q.: 三つデータ構造を作るのとどう違う?
- A. 容量の都合と、更新時の整合性。
- インデックスの種類
- ordered_(non_)unique, hashed_(non_)unique, sequenced, random_access
- 普通のsetよりも便利なことも多い(検索にインスタンスが要らないとか)
Intrusive
- データ内に、リスト管理用のフィールドを侵入させる
- 通常は構造の管理データは外にある
- メリットとかデメリットは別として・・・setの種類が多い!!
- set, avl_set, sg_set, splay_set, treap_set: マニアックなset達
混ぜる
- avl, aplay, sg, treap のIndexをMultiIndexに実装
- いまはまだ出来ないらしい。ソースを読んで予想した。
- ノードクラスを作る( 全てのインデックスに関するデータを格納してある )
- 利点: 1つのノードから、任意のインデックスによって隣接するノードを全て見つけられる
- 継承で実装されている。インデックスを追加するごとに継承でフィールドを作る
- 親クラスを後から指定できるようにして、俺ノードを作る
- 継承チェーンは毎回変わるので
- インデックスの実装も継承。外からMetaクラスを差し込む
- メソッド例: pop_back
- final_erase_を使い、全インデクスに削除をしてもらう必要がある
- erase_ は自分のインデックスの削除を実装
- IndexSpecifierを作る: 指定するインデックスの名前 (node_classとindex_classを持つ)
- githubにあげてあるよ!!
- 質疑応答
- Q. 計算量を書くだけでインデックス貼られるようにならない?
- A. 面白そう。
- Q. インデックスの順番は定数値ってどうなの?
- A. 名前(タグ)もつけられる。class Tag で指定可能
LT
俺Tokenizerを作る - tt_clownさん
Boost.Graph 入門の入門 - egtraさん
- vertexとedgeからなるデータ構造の表現
- 有向グラフも無向グラフもOK
- adjacency_list<> : グラフ
- add_vertex, add_edge
- verticesをBOOST_FOREACHで頂点を辿る
- adjacent_vertices(隣の頂点)、adjacent_edges(接する辺)
- 探索などの関数もある
- source, target, edge, edge_range, vertex
- adjacency_list のテンプレート引数の多さで難しく見える
- OutEdgeList, VertexList, Directed, 以外の引数は入門的には使わない
- 他
Introduction to The Boost.Polygon library - dark-yoshiさん
Boost.Coroutine - melponさん
- 関数の実行を凍結、再実行させる機構
- self& self, self.yield, self.exit
- 別名: micro-thread, fiber, continuation
- スレッドと類似: 手動のコンテキストスイッチなので同期がとりやすい
- 正式に入っているライブラリではない
- Boost.Vault から持ってくる
- 12/1版でスタックが壊れるバグが直ったみたい
- 使い方
- coroutine
: Tはyield時の戻り値 - coroutine
::self& を引数にとる関数で初期化 - generator
とすると、イテレータと同じ使い方が出来るようになる。
- coroutine
- Coroutine の使用例: シューティングの弾の動きを1関数内で直感的にかける
- generator の使用例
- EnumWindows(コールバックをとる) をイテレータ風に使えるように書き換える
- 実装について
- コンテキストの実装
- 他の方法での実装
- Coroutineの未来
- 作者は元気だけどやる気がない
- 作者以外の人が頑張っている
- Boost.Fiber も出て来ている
- 自分で作ったほうがいいかも
- まとめ: Boost.Coroutine は 実装の模範例とみよう
- 質疑応答
- Q. self.exitって?
- A. 例外を投げてる
- Q. 終了するのでは?
- A. 実装は例外を投げて受けている。終了するという認識でよい。
- Q. 終了後呼ぶと例外を出すのでは?
- A. 終了後呼ぶと例外が出る。std::nothrowを使うと例外が飛ばない。
Boost.Asio - xyuyuxさん
- Asio は Asynchronous I/O の省略
- スレッドやロックを使わずにブロックを処理する
- 元々はネットワーキングリソースを想定
- UDP
- TCP
- tcp::iostream (普通にreadlineとかできる)
- タイマー処理
- deadline_timer, t.wait()
- t.async_wait(), io.run() - 代わりにlambdaを読む
- 休憩
- Asioの作者が、マクロでCoroutineを作ったらしい
- reenterがswitchでyieldがcaseでforループをcaseで飛び越えてうんぬんかんぬん
- 閑話休題
- ssl::context 簡単(?)に暗号化。要OpenSSL
- serial_port 簡単(?)にシリアルポート
- プラットフォームごとの実装の違い
- select ,epoll, poll, kqueue, overlapped I/O, I/O completion ports などなど
- 非同期シングルスレッド時
- io_suervice の run() を呼ぶと、 io_service がコールバックや OS とやりとり
- マルチスレッドにすると、run()が複数のWorkerスレッドから呼ばれる
Boost.Preprocessorでプログラミングしましょう - DigitalGhostさん
Hello, World!
- BOOST_PP_ENUM_SHIFTED : 数字を増やしつつコピペするマクロ
- BOOST_PP_ENUM_SHIFTED_PARAMS : 数字付きのパラメータを作る
- BOOST_PP_SHIFTED_BINARY_PARAMS : ダブルで展開
- BOOST_PP_CAT : 結合
- ## と展開順序が違う
- 実装は、間にBOOST_PP_I を挟んでいるだけ
- BOOST_PP_IIF 1か0の判定。それ以外は駄目。
- 1LLや1.0 は駄目
- プリプロセッサでは、括弧やカンマ以外はトークンになる
- BOOST_PP_BOOL : 整数を1か0に変換、 BOOST_PP_NOT : 論理否定
- BOOST_PP_IS_EMPTY : 空トークンのみ 1
- BOOST_PP_MOD, BOOST_PP_ADD, ... : 四則演算
- 1 + 1 とかは認識できない。ADDを使うこと
- 実装
- 例: タプルを作る。
- const の有無で、2の階乗個定義が必要
- ブログ参照
- 代入: defineだとundefすると展開が起きなくなる → BOOST_PP_ASSIGN_SLOT
- Boost.Typeof で利用しているらしい
- BOOST_PP_ITERATE : BOOST_PP_ENUM では大き過ぎる場合
- 注意: BOOST_PP_AUTO_REC マクロが読みにくいので注意。
- ブログを見て!
- 質疑応答
- Q. なんで始めたの?
- A. そこにプリプロセッサがあったから。
- A. C++0xでは可変長引数のマクロが使える。
- Q. 実行時の可変長をやるためにBoost使うことが多いが、C++0xでどう改善される?
- A. 大半消えると思う
- Q. 型チェック時の副作用は必要。ファイルとか読めるといいと思いますよね?
- A. そこまでは・・・。まあたまには。
- Q. デバグはどうするの?
- A. gcc -P でできます。ライブラリの中にマクロがあるっぽいけど調べてない。
- Q. Boost.Preprocessの展開を途中で止めることは?
- A. なかなか難しい。Boost.Wave に手を入れてステップ実装とか。
バグベアード入門 - wraith13さん
- Boost C++ Libraries とは別。英語コミュニケーションできる人手伝って欲しい
- printf デバッギング用のヘッダーファイル bug.h
- 機能
- 動作ログ
- プロファイリング
- カバレッジ測定
- 特徴
- 使い方
- BUG_STATEMENT_HACK の制約
- while 内とかで int iとかしちゃだめ
- 例外仕様構文はだめ
- undef BUG_STATEMENT_HACK して bug.h を include しなおせば、切り替えが可能
- BUG_MULTI_THREADでマルチスレッド対応
- ログはスレッド毎に別ファイルの指定が必要
- プロファイリングは、プロファイル用のおまじないを指定
- 合計自実働時間が遅いものがネックとなる部分
- MinStampとMaxStampを比べれば最速動作と最遅動作の速さが見れる
- カバレッジ
- カウントが0の部分を追えばいい
- 問題: switchは非対応、実行されないifは出ない
- 悪魔の契約について
- ヒント
- - ? - : - より if
- returnを省略しない
- フィルタ機能を使うとよい
- 質疑応答
- Q. コンパイル時間がかかるのでは
- A. テンプレートメタプログラムよりは速い
- Q. 実行速度は?
- A. 当然遅い。リリース版には埋め込まないように。
Boost.SmartPtr:shared_ptr + weak_ptr - Cryoliteさん
- 所有(ownership)
- 権利: 誰かが捨てない → Dangling pointer防止
- 義務: 自分が捨てる → Memory Leak防止
- 共有: boost::shared_ptr
- 誰が片付けるのか。使ってる人がいる。
- 所有カウントによって、簡単に扱う
- 0より大きければ、使ってる人が居る
- 0になれば、誰も使ってない → 片付ける義務
- 普通のポインタとして動作する (強いポインタ)*2
- デリータ(後片付け)の実行も可能
- カウンタについてスレッドセーフ
- 循環参照を扱えない(開放されない)
- shared_ptr 使い方
- shared_ptr
インスタンスを作成 - 普通に*pみたいに使える
- shared_ptr
- shared_ptrの設計思想
- バイナリの境界を越える
- 所有を開始する時に、deleteの処理が紐づいているのがポイント
- shared_ptr
により、削除を遅らせることができる - 削除が重い処理等。voidのshared_ptrで所有を続け、好きなタイミングで開放
- weak_ptr: 弱いカウント
- 所有カウントが0になると、所有物を片付ける
- 弱いカウントが0になると、カウンタを片付ける
- これにより、所有カウントの数(有無)に常にアクセスできる = 対象の生死を判定するプロクシ
- weak_ptrからshared_ptr も作れる ( lock() )
- 例: 普通のポインタからshared_ptr を作る
- shared_ptr で自分の参照を持つと循環する。weak_ptrを使う
- 例: Observerでよく起こる事故 = Subscriberがnotifyの時にはもう死んでいる
- 死んだオブジェクトにアクセスしない、イベント通知中に死なせない
- PublisherにSubscriberのweak_ptrを持たせる
- Publisherがイベントを送る際に、lock()してshared_ptrを作る
- →これはBoost::Signal2で実装されている
- 例: オブジェクト間のグローバルマッピング
- share_ptrにすると、map用のエントリがリークする
- 案1) weak_ptr を使う。
- 案2) カスタマイズしたデリータで、オブジェクトが消えたらエントリも削除する
- 例: xとyに循環参照的にgetSharedを持たせる
- 親のshared_ptrにxとyへのポインタを持たせる(循環させない)
- まとめ
- 所有は大事
- shared_ptr: 所有カウントを使う。互換性が高い
- weak_ptr: チェック、格上げ。
- 質疑応答
- Q. 最後の循環参照の問題は、weak_ptrとlock()でなんとかできないのか?
- A. 今の文脈だと、うまく行く。ただ、xかyが死んでいる可能性がある。
Boost.MPL - uskzさん
- コンパイル時無限リスト
- Haskellだと、 iterate f e = [e, f e, f (f e), ... ]
- repeat
>(無限リスト) とか from >(0 からインクリメンタル) - take_viewの実装は・・・? → 遅延してアクセスするために sequence view を被せる
- メタ関数の適用を、普通の関数風に書けないか( <> じゃなくて () )
- 単位行列の作成
- べた書きの方が速い → メタプログラミングで
- 識別子の生成 : C++0x可変長引数ではうまくいかない例
- v[xxy] とか v[rgb]みたいなアクセス
- Placeholder Expression
- メタ関数じゃないのになぜ動くのか
- _1とか_2って何? → typedef arg<1> _1; です
- 質疑応答
- Q. チャーチ数と関係あるの?
- A. あると言えばある?
えと・・・お疲れ様でした!
余談: アンケートにご協力を!