読者です 読者をやめる 読者になる 読者になる

EMC++ Chapter5

序文

用語

ムーブセマンティクス

  • コピー演算をムーブ演算に置き換え可能にする。
  • ムーブコンストラクタ、ムーブ代入演算子はオブジェクトのムーブセマンティクスを制御する。

完全転送

  • 任意の実引数を取り、他の関数へ転送する関数テンプレートの記述を可能にする。転送先関数は完全に同じ実引数を直接受け取ったかのように動作する。

rvalue reference

  • ムーブセマンティクスと完全転送を実現するための言語機能。
  • std::moveはrvalueへの無条件キャストを実行する。自身は何もムーブしない。
  • std::forwardは実引数がrvalueにバインドされている場合に限り、その実引数をrvalueへキャストする。
  • std::move, std::forwardともに、プログラム実行時には何も実行しない。

問題

  1. std::moveのサンプルの実装を示せ。
  2. 以下のプログラムはtextからvalueへ、ムーブとコピーのどちらが行われるか。その理由を答えよ。
class Annotation {
public:
  explicit Annotation(const std::string text) : value(std::move(text)) {}

private:
  std::string value;
};
  1. std::moveとstd::forwardの違いを答えよ。

解答

template<typename T>
decltype(auto) move(T&& param)
{
  using ReturnType = remove_reference_t<T>&&;
  return static_cast<ReturnType>(param);
}
  1. コピーされる。textはstd::moveによって、rvalueのconst std::stringにキャストされる。std::stringの実装は以下のようになっている。

class string {
public:
  ...
  string(const string& rhs);
  string(string&& rhs);
  ...
};

ムーブコンストラクタにはconstが付いていないため、textを渡すことは出来ない。 しかし、const lvalueのconst rvalueへのバインドは認められているため、textを渡すことが出来る。 その為、コピーコンストラクタが呼ばれる。

  1. std::moveは無条件でrvalueにキャストする。std::forwardは実引数がrvalueで初期化された場合のみ、rvalueにキャストする。

EMC++ Chapter5

序文

用語

ムーブセマンティクス

  • コピー演算をムーブ演算に置き換え可能にする。
  • ムーブコンストラクタ、ムーブ代入演算子はオブジェクトのムーブセマンティクスを制御する。

完全転送

  • 任意の実引数を取り、他の関数へ転送する関数テンプレートの記述を可能にする。転送先関数は完全に同じ実引数を直接受け取ったかのように動作する。

rvalue reference

  • ムーブセマンティクスと完全転送を実現するための言語機能。
  • std::move, std::foward はrvalueへのキャストである。

問題

  1. std::moveのサンプルの実装を示せ。
  2. 以下のプログラムはtextからvalueへ、ムーブとコピーのどちらが行われるか。その理由を答えよ。
class Annotation {
public:
  explicit Annotation(const std::string text) : value(std::move(text)) {}

private:
  std::string value;
};
  1. std::moveとstd::forwardの違いを答えよ。

解答

template<typename T>
decltype(auto) move(T&& param)
{
  using ReturnType = remove_reference_t<T>&&;
  return static_cast<ReturnType>(param);
}
  1. コピーされる。textはstd::moveによって、rvalueのconst std::stringにキャストされる。std::stringの実装は以下のようになっている。

class string {
public:
  ...
  string(const string& rhs);
  string(string&& rhs);
  ...
};

ムーブコンストラクタにはconstが付いていないため、textを渡すことは出来ない。 しかし、const lvalueのconst rvalueへのバインドは認められているため、textを渡すことが出来る。 その為、コピーコンストラクタが呼ばれる。

  1. std::moveは無条件でrvalueにキャストする。std::forwardは実引数がrvalueで初期化された場合のみ、rvalueにキャストする。

TPOP - UNIX思想 3.37〜 (WIP)

UNIX思想

UNIX設計思想の正しさ

  • UNIXは1969年に生まれて現在まで使われている。設計思想の正しさは長い実績が保証している。

モジュール化の原則

  • モジュールは自己完結させる。
    • 理由
      • 問題の発生箇所がモジュール内に局所化できる。
    • 方法
      • 関連性の高いもののみを集める。
      • 極限までシンプルなインターフェースにする。

明確性の原則

  • 人間にとって明確なコードはめったに壊れない
    • 複雑なコードは障害の発生箇所となる。
  • コードはマシンのためではなく、保守する人のために書く。
    • 保守作業は新規開発より高いコストがかかる。
  • コードを解読する作業が高々1度で済むように留める。
    • 2度目の解読が発生した場合、3度目の解読を引き起こさないように改善をする。

組立部品の原則

  • ソフトウェアをテキスト形式のデータストリームのフィルタリングとして捉える
    • 入力と出力を意識し、ソフトウェアはどんな加工を行うか。
    • テキストストリームは、ソフトウェアを強制的に情報隠蔽する
    • 凝ったプロセス間通信は、互いに内部構造を曝け出してしまう。
  • 入出力をテキストストリームとする利点

TPOP principle3.29 7つの設計原理

第3章

principle 3.29〜3.36 7つの設計原理

コード妥当性レビュー観点

  • 単純原理
  • 同型原理
  • 対称原理
  • 階層原理
  • 透明原理
  • 明証原理
  • 安全原理
  • 線形原理

単純原理

  • 局所的な完全性を重視する

    • ひと目で自明がいいに決まってる
  • 複雑なところにバグが出る

    • 基本的に独自のイディオムに頼らずきれいなコードを書きたい
      • マクロとか

同型原理

  • 形に拘る

    • レビューワーが一旦コードの形を捉えれば、そのノリでだいたい読めてしまうのが良い
  • 「異物」が目立つ

    • 突如違ったコーディングスタイルが入ってきたら気になる
  • 一貫性のあるコード

    • 他と同様の記法で書けるものに局所的に"ハック"しようとしても無意味
    • "ハック"の要求に狩られる場面が多ければ、別の言語を使うか、全体をライブラリ化してしまうことを検討する
      • 内部DSLとか構築する場合もある

対称原理

  • 形の対称性にこだわる
    • Aと¬Aを考えた命名規則や処理フローなど
    • 対称性は読み手に予測を促す
    • 一般的な命名の対称性を利用しよう
      • set/get
      • push/pop
      • start/stop
      • begin/end

階層原理

  • 主従関係、前後関係、本末関係などの階層関係を意識する
    • 階層的なアーキテクチャ
    • delegaterとdelegatee
    • コーディングを意味ごとの塊にまとめて、前後関係が混濁しないようにする
  • 同じ種類の処理が異なる階層を跨がないようにする
    • リソースの獲得/解放 RAIIに従う
      • vendorのライブラリの関数に生ポインタを渡した時、そのライブラリの関数内でdeleteされてしまうことはないだろうか?
    • mutexの獲得/放棄
  • 上位と下位の階層関係を明確にし、同レベルの階層に同一の処理を記述する
    • 適切な委譲をして、メソッドの責務が一言で表現する
    • 同一階層内でも、即時実行するラムダ式等を用いることで、階層関係を明らかにすることが出来る

線形原理(透過原理)

  • 処理の流れを直線的にすることを意識する(透過的にする)
    • メソッドが管理する状態を減らす
    • 反復しない
      • 上に行ったり下に行ったりすると読みにくい
      • 線形結合的なシーケンスの重ね合わせで機能を実現する
    • 制御文は処理のブランチを分けていることを意識してみる
      • 早期returnなど、ちょっとブランチ切ってもすぐにメインのブランチに復帰するから直線的な処理のフローが保たれる
      • Gitとかでマージしてないブランチがたくさんあったら管理しきれないイメージ(ほんまか)
    • switch文を使って各々個別の処理を書く行為は、同じ関数内に多くの異なるフローをもたせることになる
      • そのくらいだったら委譲、ディスパッチ、サブクラス化とかして、直線的なフローを独立して管理できるようにしたいよねという話

明証原理

  • 明証性にこだわる
    • 明証になるためなら、コメントやドキュメント、図を導入することをいとわない
    • コメントやドキュメントの作成などが面倒であるとなれば、コーディング自体を明証性のあるものにする
  • 不確実性を取りのずく
    • トリッキーなコードに注意

安全原理

(WIP)

TPOP principle 3.64 UNIX哲学9 - フィルタ化

第3章

principle 3.64 UNIX哲学9 - フィルタ化

ソフトウェアはフィルタである

  • データを生成するのは人間
  • データにフィルタをかけて別の出力を表示するのがコンピュータ
  • 故に、まず入力ストリームと出力ストリームに着目し、そのフィルタリングとして設計を考えればよい
  • UNIXではstdin, stdout, stderrをインターフェースとしてソフトウェア同士をコネクタブルにしている

UNIX哲学・小定理

  • 環境カスタマイズ

    • 最初の学習コストが高くても、ある程度学べばユーザがチューニングできるようになる方が長く使われるソフトウェアになる
  • 軽薄短小カーネル

    • カーネルにアプリケーションを組み込んだら、そのアプリケーションを保守する人がいなくなる
  • 小文字使用

    • 小文字で短く、目に優しくする
    • ソート時に大文字が目立つ
  • 森林保護

    • ドキュメントは電子化されていなければフィルタリング出来ない
  • 沈黙は金

    • 必要な情報が無駄な情報に埋もれてはならない
    • エラーなどには基本的に沈黙し、成功したときだけ有益な出力を返す
  • 並列思考

  • 部品コラボレーション
  • 90パーセント解

    • 90パーセントを効率的に処理することを保証し、10パーセントはユーザに任せる
    • 10パーセントの、時間のかかる処理や、プログラミングしにくい処理を故意に無視する
  • 劣るが勝る

    • 単一の巨大なソフトウェアよりも、小さい劣ったソフトウェアの最大公約数で勝負する
  • 階層指向

    • 階層構造アーキテクチャ
    • 各々の階層構造で成功実績を収める
      • プロセスツリー
      • Xウィンドウシステム
      • ネットワークサービス

TPOP principle 4.5 コードの臭い

第4章 視点

principle 4.5 コードの臭い Bad smell in code.

言葉の復習

  • 設計とは何か。
    • principle 1.2 コードは設計書
    • 「基本設計」「詳細設計」「プログラミング」「テスト」「デバッグ」全てを「設計」と呼び、「コード」は設計書、「リリースビルド」が製造である。

臭いの傾向

よく見る
  • 状態
    • そっくりのコードがあちこちに存在する
  • 改善策
    • 重複したコードを一つにまとめる
長過ぎる
  • 状態
    • 「この関数でやっていることはAである」と一言で言えない
  • 改善策
    • 関数を分割して、関数の責務を一言で表現できるようにする
大きすぎる
  • 状態
    • モジュールの責務が大きい
    • モジュールの修正の機会が多い
    • 時間経過に連れ、モジュールの規模が増加し続ける
  • 改善策
    • 分割して、モジュールの責務を一言で表現できるようにする
多すぎる
  • 状態
    • モジュールの数が多すぎて、依存関係、処理の流れを追うことが出来ない
  • 改善策
    • 仲介役の削除、統廃合によりモジュールの数を減らす
名前が合わない
  • 状態
    • 名前と実際のコードの内容が合わない
  • 改善策
    • 表現したい概念と合っていなければ、直ちに適切な名前に修正する
    • 以前正しかった名前でも、改修によって正しくなくなることがあるので、その時点で名前も修正する

C++TT Chapter5 - SFINAE

考察・まとめ

問題

  1. SFINAEは何の略か。
  2. SFINAEとはどのような仕組みのことを言うか。
  3. 型特性を英語で言え。
  4. 型特性メタ関数とは何か。
  5. 型Tがiterator型を持っているか判定するhas_iteratorを様々な方法で実装せよ。
続きを読む