C++ソフトウェア設計 読書会vol.30
https://scrapbox.io/files/677e58cd6851aa4933a854f0.jpeg
#C++ソフトウェア設計
開催日時
2026年5月20日(水) 21:00~22:30
開催URL
https://cpp-osaka.connpass.com/event/393216/
参加人数
7人
読み進め方
ウォーミングアップ
ガイドライン 25:通知を抽象化するには Ob­server パターン
Ob­server パターンの古典的実装
読者は問うでしょう。「こういう時は std::unique_ptr か std::shared_ptr を使うんじゃないの?」
shared_ptrを使うとPersonが保持するのでずっと残り続けてしまう
insertの戻り値の型pairを構造化束縛で受けている
std::pair使わずにクラス書いた方がいいのでは?
戻り値1つだったのを2つにするときにpairにしがちだが、そういう場合往々にして3つ返したくなることが多い
クラスを作る方が拡張性があるし名前があってわかりやすい
そう思ってテストでクラスを書いてたら「わざわざクラスかかずに構造化束縛で書けばいいじゃん」というマサカリご指摘があった
チームの共通コーディングスタイルを決めておいた方がいい
生ポインタだとダングリングする可能性がある
ダングリングを完璧に防ごうと思うとshared_ptrとweak_ptrの形が必要になってくる
Ob­server パターンのもう 1 つの核は notify() 関数です
StateChangeはPersonクラスの外に出してしまえる
そうなるとusing PersonObserverもPersonクラスの定義が終わった直後に持ってこれる
値セマンティクスベースの Ob­server パターン実装
std::function 型に与えた関数シグニチャに合致さえすれば良いのです
最初は合致していたけれど合致しなくなることがある
一斉にシグニチャ変更を変更しなくちゃいけなくなる
今だとAIで変更してくれるのでは
癖があるのでもう一段賢くなるまでは注意が必要
例:生成AIがやたらとfriendを使いたがる
C++はいろんな書き方ができるのでAIビリティが低い・・・
Goとかかっちりしてそう
大規模なコードも生成AIは苦手
Ob­server パターンの短所を分析
本文とは関係ないshared_ptrの参照を返していた例
code: cpp
// thisがconstかどうかで値か参照か返すものが変わる趣深いコード
std::shared_ptr<...> get() ;
const std::shared_ptr<...>& get() const; // !?
// 非const時に値を返すにしてもインクリメントデクリメントが激しい芸術的なコード
if (a->get() && a->get()->hoge()) {
auto b = a->get()->hoge()/* ... */;
}
ガイドライン 26:型を静的に区別するには CRTP パターン
次回ここから
お悩み雑談室
code: cpp
reinterpret_cast<std::pair<T, S>&>(std::pair<const T, S>&())
このコードはUB?
なんでconst外したいの?
B木のキーがconstになっていて値の代入をするときにキーを変更したい要求
この二つは厳密には異なる型になるのでダメそう
レイアウトが一致する保証がない
用語集
ISP
インタフェース分離の原則
ISP は SRP の特殊なケースと捉える。
SRP
単一責任の原則
OCP
開放/閉鎖原則
LSP
サブタイプ(派生クラス)が満たすべきふるまい
リスコフの置換原則 (ガイドライン6)
サブタイプでは事前条件を強化してはならない
サブタイプは事後条件を弱めてはならない
サブタイプの関数の戻り型は共変(covariance)でなければならない
サブタイプの関数パラメータは反変(contravariance)でなければならない
スーパタイプの不変条件はサブタイプでも維持されなければならない
DIP
依存関係逆転の原則(ガイドライン9)
依存関係を管理するには、具象型や実装詳細ではなく抽象化に依存すべきである