C++完全理解ガイド Rev1.4.01

# はじめに

C++を完全理解したので完全理解ガイドを書く。
__最初に言っておくがタイトルは詐欺で、実際はポエムである。__

~~僕は仕事でC++を書いたことはないのでなんか変なことを言っているかも知れない。
__ところで無職になったので、普通にC++で職がほしい。__~~
~~__2018年6月から受託で仕事をもらい、毎日C++17を書いています。__~~
__2018年9月から雇用され、毎日C++17を書いています。__

かなり雑に書いているはずなので、コメント等でどんどんマサカリを投げてほしい。

# 僕は何者か

~~工学部を卒業して4年ほど高校の理科教師をやっていたが、現在無職になった人。~~
工学部を卒業して4年ほど高校の理科教師をやっていた。
最初は良かったのですが、授業に慣れ、このまま自分の成長が止まってしまうのかとなぁと思い、辞めて無職に。
一ヶ月無職を楽しんだあと、某から受託でC++を書く仕事をもらい、C++17を書いている。

主にツイッターに生息していて、たまにTLの迷えるC++erを救っている。

~~C++を生業としてるわけではないが~~、Boost勉強会に顔を出したり、大坂C++読書会に顔を出したりしていた。
C++が生業となりました。

僕がどれくらいC++ができるのか気になる人は[このリポジトリ](https://github.com/LoliGothick/mitama-cpp-result)や[このリポジトリ](https://github.com/LoliGothick/mitama-dimensional)を見て判断してほしい。

主な趣味は、ラーメン、けん玉、リコーダー、紅茶、エロゲ、読書など。


# § 0 序論

C++をやめる。
すると、救いがある。
例えばRustを始めよう。

C++には救いがない。
それでもあなたはC++を書くというのかい？

よろしい、では救いのないセカイでC++にまみれよう。

## なぜC++をやるのか

C++は第一選択肢としてはもはや優秀じゃない。
特にスタートアップとか、開発速度が要求される場合ダメな気がする。
いいところはたくさんあるので、しばらく滅びることはなさそうだ。

### C++の特徴

#### ワールドワイドなISO/IECの国際規格がある

C++の処理系（コンパイラやライブラリ）はたくさんあります。
国際規格によってそれらの挙動は高いレベルで統一されているらしいです。

#### 多種のコンピュータ用コンパイラとライブラリがある

C++を使って多種のコンピュータをターゲットに開発できるということです。

#### C言語との互換性

C++からC言語のコードを利用できます。

#### つまり

これらの特徴から、多くの基幹アプリケーションやソフトウェアや各種ミドルウェアがC++で開発されてきましたし、いまもされています。
これまで開発されてきた膨大なソフトウェア資産があり、それらを利用することができるということです。
今後も基幹的なソフトウェアや高速性が要求されるソフトウェアの開発にはC++が使われ続けるでしょう。

### 僕がC++を使う理由

#### 速いコードを生成するから

速度は大正義である。
パフォーマンスが必要だからC++を使っている。

C++と同等の速度を求めるなら、他の選択肢はFortranかRustくらい。
そこそこ速いくらいの言語はたくさんあるが、C++と比べると一段劣るように見える。

#### ハードウェアリソースやシステム関数に直接アクセスできる

これがC++をやめられない理由。
C++が何でもできると言われている所以の一つでもある。

Rustが登場した時、本気でC++をやめようと思った。
でも、やめられなかった。
RustはLLVMにのっかっているのでLLVMができないことはどうしようもない。
C++はコンピュータができることなら、できる。

昔話をしよう。
僕の卒業研究は『区間解析を用いた大域的最適化手法の改良』だった。
区間解析の特性上、浮動小数点演算の丸め誤差を制御する必要があった。
浮動小数点演算に関しては[IEEE 754](https://ja.wikipedia.org/wiki/IEEE_754)で規定されている。
これに規定された浮動小数点数の丸めの「方向丸め」をプログラムで指定できないといけない。
これをライブラリで提供している言語はかなり少ない。
僕が知る限りでは

- C
- C++
- D
- Fortran
- Haskell

くらい。
スクリプト言語とかはそもそも調べてすらいないのだが。

結局、浮動小数点数の丸めの「方向丸め」が指定できて、
かつ高速に動作する言語となると選択肢があまりなく、
慣れ親しんだC++から離れられなかった。



## C++を完全理解する目的

>C++ has indeed become too "expert friendly". -- Bjarne Stroustrup

>『The Problem with Programming, Technology Review, Nov 2006. 』


生みの親も言っているように、C++はその進化とともに玄人に優しくなりすぎた。
C++の進化とともに、ある程度深い知識がなければ、
より良いコードを選択しC++の真の力を発揮することが困難になってきた。

__C++の現代的なイディオムを知るごとに、C++はずっとフレンドリーに感じられ__
__C++の規格書を理解するごとに、エラーメッセージはずっとフレンドリーに感じられる__
そして、理解が更なる理解の助けとなる……

とは言ったものの、普段のプログラミングで支障がない程度に、
ほどほどにC++に精通していればいいのではないかと自分でも思っている。

完全理解なんて人間のすることじゃない。
完全理解なんて完全に趣味だ。

それでも完全理解を目指すのなら、まずは人間をやめることだ。
__人間をやめるのなら、ネコになるのがいい。__
__ネコはC++の理解に適正があることが知られている。__
(= ' w ' =)＜にゃーん
ネコが無理でも、せめて猫耳くらいは生やしたほうがいいだろう。

## C++の完全理解は幻想か

C++は常に進化している。
C++のテクニックも常に生まれているように思える。

気がついたら新しいコンパイラが出てくる。
気がついたらC++がメジャーアップデートされてる。
気がついたら新しいIdiomが流行っている。

仮に、ひとときC++を完全理解できたとしても、
C++の進化とのいたちごっこだ。
最新の規格書のドラフトを参照し、Proposalを読み漁り、CppConの動画を視聴し、Boostの次期リリースのイケイケコードを読んで、色々書いては試し書いては試し、、、時にはコンパイラ内部エラーを目の当たりにしてバグレポを送り、知見を貯め続けなければならない。

C++完全理解は到達不可能目標であるように思える。

## 仕方ないので完全理解のレベルを現実的に設定する

覚えることは不可能っぽいので、
集合知にアクセスする方法を知っていいいことにしよう。
つまり、覚えていなくても、何をどう調べればいいかが分かればいいということだ。

ところで、何を知っていればいいのだろうか？

1. コア言語機能
2. 標準ライブラリ
3. コンパイラについて
2. テンプレートメタプログラミング技法
3. エラーメッセージの読み方
4. 標準にはない外部ライブラリ
5. 性能評価
6. テスト
7. デバッグ
6. 規格書
7. （数学）

くらいだろうか。
これらについては後で語ることにしよう。

付属的に英語が必要だ。
英語が読めない・聞けないとお話しにならん。
エラーメッセージが意味不明になりがちだし、
集められる情報がショボすぎになるし、
情報収集速度が著しく低下する。

# § 1 C++を始める前に

## 1.1 マシンや周辺環境を用意する

目的にあったPCを用意しよう。
個人的には以下の3点に気をつけてほしい。

- メモリ：あればあるだけいい。16GBは欲しい（ブラウジングしながらプログラミングするだけでメモリ6~12GBは必要と考えている）。
- CPU：あまり雑魚くなければまあ何でもいいけど、AVX512くらいはほしい
- ディスプレイ：ブラウジング用と開発用に最低2つほしい、4Kがいいぞ

特にメモリはケチるな。
C++はコンパイル時にいろいろできる。
でもいろいろやってしまうと、莫大なメモリを消費する。
というか並列ビルドするだけで10GB単位でメモリ奪われることもある。

## 1.2 快適にプログラミングできる状態になる

自分の状態を良好に保つことが肝要である。

### いい椅子に座る

いい椅子に座ることで長時間のプログラミングにも耐えうる。
アーロンチェアを買えとは言わないが、それなりに良い椅子に座るべき。
暇がるなら中古のオフィス家具屋を回ってみるのもいいだろう。

### お気に入りのドリンクを用意する

個人的に重要なポイント。

__紅茶__かなーやっぱりww
旬の紅茶を追いかけて取り揃えてるwww
こないだショッピングに行った時も気が付いたら意識無くて15gで3,000円の紅茶を手に持ってたwww
ちなみに正山小種は切らしたことはない(聞いてないw)

### 音楽を聴きながら

僕は音楽がないと生き続けることができない。
音楽に興味がなくて、雑音にしか思えない人もいるだろうけど。

ショスタコーヴィチでテンションがあがる。
ショスタコーヴィチの「ピアノとトランペット、弦楽合奏のための協奏曲ハ短調」は特にテンション爆上げ。

### 良いキーボードを使う

良いキーボードを使うと気分が高揚する（重要
正直なんでもいいかもしれないけど、疲れにくさが結構違うんですよね。

しばらく青軸のメカニカルキーボードを使っていた。
最近はHHKB Professional 2 を使っている。

### 疲れたらプリキュアを見る


たいへんに癒やされる。
なにせprettyでcure cureである。
名前からして癒やしている。
特に『魔法つかいプリキュア』は尊ひ……


『ご注文はうさぎですか？』でもいいぞ。
ところで、ごちうさもプリキュアもエンジニアの必須知識らしい。


# § 2 C++を始める

C++を始めるにあたっての一連の流れを考えてみる。

## 2.1 C++を始めるにはまず人脈♪

__正直言って、一人でも全く問題ない。__
しかしながら、質問できる人がいると色々と便利だろう。
Twitterに強い人がごろごろしてるから雑にフォローしまくればいい。
なんなら僕([いなむのみたま](https://twitter.com/range_v3))をフォローしてくれ。
そして、例えば次のようにつぶやく。
「なんでコンパイルエラーになるんだ？ *ここにwandboxのリンクを貼る*」

うまくいけば、優秀なC++プログラマがやってきて優しく教えてくれるだろう。
実行可能なコードへのリンクを付属することが最低限のエチケットだ。

## 2.2 C++のコンパイラを用意する

### 2.2.1 手元にC++のコンパイラを用意しない

最初からガチで環境構築すると挫折しがちだ。
[Wandbox](https://wandbox.org)でC++を書いてコンパイルすることができるので、とりあえずそちらで試す。
WandboxはC++に関してはありえないほど充実しているので良い。

### 2.2.2 手元にC++のコンパイラを用意したい

#### Linux系の使い手
gccかclangをパッケージマネージャで入れたらいいかもしれない。
でもパッケージマネージャで入るコンパイラは古そうなので、最新版を入れた方がいいかも。
Linuxを使っているような人は、おしなべてオタクなのでお茶の子さいさいだろう。

#### Windowsの使い手

主な選択肢を以下に挙げる。
好きなものを選ぶといい。

- VS2017
- LLVM
- mingw64
- msys2
- bcc
- TDM-gcc
- Intel C++ Compiler（有料）

この中でオススメはLLVM（Clang）かなと思う。
Intel C++ CompilerはWindowsで非常に高速に動作するバイナリを生成することで有名。

また、WSL（Windows Subsystem for Linux）上にC++コンパイラを用意するという方法もある。
WSLは失敗しても何も考えずにまっさらにしてやり直せばいいので気が楽。


![2018-03-11 (1).png](https://qiita-image-store.s3.amazonaws.com/0/100319/cbd182b1-a13f-1495-77e4-3bd188dee8e2.png)
WSLでg++, clang++を用意した図


#### スタバに行ってMac開く系の人

Mac嫌いなんで適当に書きます。
多分OSを消し飛ばすのが一番いいです。


Mac OS Xでは、Xcode 4.2からClang is デフォルトコンパイラ。

もしくは（Apple Clangイミフメー、自分で入れるわって場合）

```
$ brew install --with-tool-chain llvm
```

でClangを入れる。
[（こちらを参考にするべし）](https://embeddedartistry.com/blog/2017/2/20/installing-clangllvm-on-osx)

#### Docker

Dockerコンテナ上に複数のC++ Compilerの環境を整えてしまう。
ローカルの環境を汚さないのが利点。
CIで複数のコンパイラを対象にテストする場合にも役に立つ。
でもコンパイラは常に使うから微妙。

# § 3 C++を書く環境を整える

## 3.1 エディタを使う

Vim, Emacs, Atom, VSCode,（メモ帳）, etc...
好きなエディタを使えばいいよ。

僕はVSCodeとVimを使ってるね。
機能拡張したいならメモ帳は選択肢に入らないね。

個人的には活発なコミュニティがあって、ユーザーがたくさんいるものを使った方が情報が集まっていいと思う。
__つまりVimだな！__

### 3.1.1 Vimについて軽く

Vimは拡張するとほぼ統合開発環境になる。
驚くほど機能をカスタマイズすることができる。

環境が変わっても安定して使えるので強い。
そしてものすごく軽くて速い。
したがって、Vimのパフォーマンス上の障害となるのは「あなた」だ。
あなたがVimのパワーユーザであればVimは最高のエディタとして機能する。

ただ、vimrcをいじっているとこれまた驚くほど時間が溶けていく。

快適にC++を書くにはlanguage serverを使うべきか。

### 3.1.2 VSCodeについて軽く

VSCodeはベータ版から使っているが、ありえん速度で便利になっていきよる。
Built-inで必要なものがエディタ内に揃っているのが特徴。
拡張機能を入れなくてもそこそこ便利。

Electronで作られているのに速いのですごい。

快適にC++を書くにはlanguage serverを使うべきか。

### 3.1.3 他のエディタよく知らない

これ以降の節は編集リクエストがあったら増えるかも。

## 3.2 IDEを使う

IDEを使うなら、インストール直後にまず背景を可愛くすることだ。
これだけでやる気が100倍、実装力も100倍、アンパンマンだ。

![2018-03-13 (1).png](https://qiita-image-store.s3.amazonaws.com/0/100319/c95d3021-7877-8e3c-8fb5-ea9b0fa32abf.png)


## Visual Studio

全機能フルインストールで100GBくらい。
C++のデスクトップ開発だけだと10GBくらい。

これを使うためにWindowsを選ぶ人もいるとかいないとか。
[fafnir](https://github.com/kazatsuyu/fafnir)（ファフニール）を使うことでLLVM-Clangにコンパイルを投げることができる。
つまり、便利なIDEの機能だけ使って、最新のclangでコンパイルできる。


ところで、最近のVisual Studioはかなり先鋭的になってきた。
C++の最新の規格に追従しようとしているし、補完もコード解析もそれなりに強い。
ただ、なんか……安定してない……
インテリセンスが定期的に死ぬし、シンタックスハイライトも定期的に死ぬ。
あと、インテリセンスが解析できてるのにMSVCで内部エラーになったりする。
僕はAppVeyorでテストするときに便利だからアンインストールはやめておく。


## CLion

JetBrains謹製。
なんとなくVisual Studioよりサクサク動くような気がする。
オンザフライのコード分析が強い。
入力したそばからコードが修正されていくので一発でコンパイル通っていく。
DataFlow解析もあるので、無限ループも特定されることある。
マルチプラットフォームなのでWinでもMacでも使えるのでその点オススメ。


# § 4 C++を学ぶ

## 4.1 C++入門

結局ここが一番厳しい。
入門に適した方法がよくわからない。
最適解は、江添さんが入門書を書いているから出版を待つこと（ほんまか🤔

__オススメの入門書があるなら、コメント欄で何がオススメのポイントなのかも一緒に教えてほしい（懇願__

僕はC++に入門したとき学生で、しかも研究室に所属していた。
そのため、研究費用でしこたまC++の技術書を購入してもらい、研究室の本棚の一角をC++コーナーにした。
それらを読み漁り、試しにコードを書いた。
コンパイルエラーが出るたびにググって新しい手法を目の当たりにしては書き直して学んでいった。
これは、非常に効率が悪い。
できれば最新の技法を最初から学びたいところだ。
しかし、最新の技法に対応した入門書なんてありはしない。

僕は少なくとも10以上のプログラミング言語に入門してきた。
最初に入門したのはFortran77だった……
（閑話休題）
大抵の場合は最初に言語の公式ドキュメントを読む。
言語の特徴を雑に理解しておくことが目的だ。
最近の言語はだいたい公式のページにその言語が何のために生まれてきたのか書いてあるので、ドキュメントを読むまでもない。
そのあとで、本を読む。
本はあまり分厚くなくて一通りの言語の基礎が書かれた本が読みたいところだが。。。
残念ながら、C++にはまともな入門書が見当たらない気がする。
良書と言われてきた本も軒並み古くなり、化石のようなコードが書かれている本に成り果てた。
基本文法とライブラリの機能をあらかた自分で調べたし、有名OSSのコードから良さげな書き方を盗んだ。
本もインターネッツの記事も何が間違っているのかわからないし、困る。
ある程度の理解があれば間違っていることに気がつけるのだが……

## 4.2 僕が読んだ本（抜粋）

1. C++ Primer
2. Programing Language C++ 
3. C++ Templates: The Complete Guide
4. C++ テンプレートテクニック
5. Effective C++
6. More Effective C++
7. Effective STL
8. C++11/14 コア言語
9. Effective Modern C++ 
10. Optimized C++
11. C++ ポケットリファレンス

この中で、明らかに外れだったものを挙げるとすれば、２の『プログラミング言語C++』である。
何がダメかと言うと、サンプルコードがまともにコンパイルできない。
サンプルコードがまともにコンパイルできないような技術書は全てクソだ。

良かったものは、最後の『C++ポケットリファレンス』。
やりたいことから方法を調べることができるので、C++の理解が浅くても役に立つ。
基本文法の解説もあるので、文法がよくわからなくなっても開く。
改訂3版が出たのでC++17に対応している！
当然サンプルコードの動作確認はされている。
また、サンプルコードがGitHubでパブリックドメインとして公開されている。

もうひとつ良かったのが、『C++11/14 コア言語』。
コア言語機能の解説しかないが、不必要に詳しい。
これ読んどけばコア言語機能で分からないことはあまりない。
GitHubで本そのもののソースが公開されているので全文を読むこともできる。
~~僕はまだ読んでいないが~~、C++17の機能だけを解説した本も出ている。
GitHub上で読ませてもらった、やっぱりかなり詳しい。

その他は中級者向け～上級者向けが多い。
テンプレートとか書いてるのは上級者向け。
Effective系は中級者向けかな。

## 4.3 C++を学ぶ前にC言語を学ぶべきか？

結論から言うと間違っていると僕は考える。
C言語の方法はC++では安全ではなく、非推奨なことが多い。
よってC言語の知識はC++を学ぶのに邪魔になることが多い。
先にC++をやるべき。

本当に必要になるまでC言語の勉強は遅延したほうがいい。
実際なにかを作るときにC言語の遺産から逃れてC++だけで書けるかというと怪しい。
必要になれば、適宜C言語の知識を増やせばいい。


C言語を先にやったほうがいいという意見もある。
先にC++をやるとC言語の方法とC++の方法の区別がつかず混同してしまう（意訳）という意見だった。
たしかに、C++について調べていてC言語の方法がヒットしても（C++のもっと洗練された方法が他にあったとしても）初学者はそれに気が付かないかもしれない。

ただ、C言語を学ぶのにも時間がかかる。
なんか、トレードオフな気がしてきたぞ。

## 4.4 アセンブラを勉強すべきか？

読めると便利。
書き換えたコードが高速化したのかアセンブラの比較で確認することができるようになる。
別に知らなくても問題はない。

## 4.5 インターネットで調べる

### 4.5.1 特定の機能について調べる

主な方法

- cppreference.comで調べる（英語）

- cpprefjpで調べる（日本語）

上記サイトで無理ならほぼほぼキーワード検索することになる。
このとき、C++の専門用語を知っているとググりやすい。
曖昧な単語でググっても曖昧なこと書いてるページばっかり出てきがち。

### 4.5.2 やりたいから方法を調べる

やりたいことを羅列したAND検索で頑張る。
StackOverflowがヒットすれば解決する可能性が高い。

または、標準ライブラリに何かないかを調べる。
標準ライブラリは貧弱だが、Boostになにかしらある可能性は高い。

### 4.5.3 インターネッツで網羅的な知識を得る

あまりおすすめしない。

江添亮てんてーのGitHubとか、いいかも。



# § 5 C++を極める

## 5.1 コア言語機能を極める

江添さんの本を読めば問題ない気がする。
重箱の隅をつつくために規格書を読む必要もあるだろうが。

cppreference.comを参照するとなぜか半分くらい規格書の文言。
規格書で断片化されている情報がわかりやすくまとまっているのでGood。
まれにpossible implementationが載ってたりして勉強になる。

あと、とにかくコード書いて挙動を確認する。
さらにwandboxで複数のコンパイラを使って確認する。
人は経験からしか、本当の意味で物事を学びとることはできない。
とにかく手を動かし、クソコードを量産してはそれをリファクタリングして学ぶことだ。

様々な落とし穴があるので、自分の足を打ち抜きながら頑張っていく。

ついでに提案書を読むと、現在の言語仕様の問題がわかったりする。
暇があったらCore Issuesも参考にする。

## 5.2 標準ライブラリを極める

最初にポケットリファレンスなどで、基本的な使い方を抑えておくべき。

cpprefjpやcppreference.comでライブラリのヘッダを検索する。
何が含まれているのかがわかるから、一通りながめておく。
必要になったときに、そういや標準ライブラリになんかあったなってなる。

## 5.3 コンパイラのバグ回避方法を極める

前提として、コンパイラはバグっている。
どうにかこうにかワークアラウンドを書かないといけない。

ところで、バグは自分が書いたコードが原因の可能性が99.9%くらいある。
残り0.1%の可能性を疑うなら、複数のコンパイラでコンパイルして特定のコンパイラで落ちるかを確認してみよう。
MSVCだけ落ちて、GCC・Clangが問題なく通すなら、MSVCは怪しい。
というかMSVCは常に怪しいが（笑

暇があれば、コンパイラへのバグレポをながめる。

未知のInternal Compilation Errorに遭遇したら、
最小再現コードを書いてバグレポを投げよう！

## 5.4 テンプレートメタプログラミング技法

C++テンプレートテクニックを読む。
C++テンプレート完全ガイドは古いがいい本だ。

あと、SproutとかBoost.Hanaとかのメタプログラミングライブラリを読む。
C++11/14のメタプログラミング技法はこのあたりのライブラリを読むとかなりカバーできる。


## 5.5 エラーメッセージの読み方を極める

まず、コンパイルエラー起こっているとは
__コンパイラが未然にコードの問題を検知した状態__
である。
どのような問題が検知されたのかをコンパイラが優しく教えてくれる。
どれくらい優しいかと言うと、
__ときに丹精込めて数千行のメッセージを表示してくれるくらい優しい。__
優しすぎて震える。

コンパイラの優しさを無駄にしないためにはエラーメッセージを解読することだ。
まず、英語ができろ。

エラーメッセージにはエラーに関係しているが直接の原因ではない情報が大量に含まれていることが往々にしてあるが、本当に読まないといけないのは__error__って書いてあるところの直後くらいなものだ。


```:エラーメッセージの例
prog.cc:10:38: error: expected primary-expression before ',' token
```

だいたいの場合、該当の行を読んでから、コードを見ればミスに気がつく。
この時、専門用語がわかっていないと、読んでも何もわからないになりがち。
上記の例の場合__Primary Expressions__とは何かがそれにあたる。
まあ、わからなくても問題の解決はできるが、覚えるチャンスなので覚えろ。

なおも意味が分からない場合、メッセージをコピペしてググる。
StackOverflowがヒットする。
そして、解決する。

そうしているうちに、このエラーメッセージなら原因はアレだろうなと分かるようになる。

コンパイラを変えてエラーメッセージを見るのも有効。
エラーメッセージのセカンドオピニオンだよ。
コンパイラでメッセージが違うことも多々ある。
もしかしたら、他のコンパイラがわかりやすいメッセージを出してくれるかもしれない。
普通、最新のコンパイラがよりわかりやすいメッセージを出すので最新も試すといいかもしれない。

## 5.6 外部ライブラリを極める

Boost, Eigen, etc...

知っておかないと、車輪の再開発で時間を無駄にするので定期的にOSS情報は収集すべき。
ナウいOSSのコードは設計の勉強にもなる。
枯れてるOSSのコードも設計の勉強になる。

## 5.7 性能評価を極める

素朴に時間を測る、それが意外と難しい。
プロファイラツールを使って診断させてもいいが、完全に信頼できるかといえばそうでもなかったり。
まあ、ホットパスを見つけることができればそれでいいのかもしれない。

とりあえず『Optimized C++』を読んどけ。

コード片を切り出してアセンブリ出力を比べるという方法もある。
そういうときに便利なサイトが
[Compiler Explorer](https://godbolt.org/)
である。

## 5.8 テスト方法

C++と直接は関係ない気がする。
でも、テストくらい書かないとお話にならんよね（煽り

とりあえず、ユニットテストのフレームワークを使おう。
Google Testとか、CppUnitとか、iutestとか。

適切にstatic_assertを使ってテストするのも効果的である。
関数をconstexpr指定してstatic_assertにてテストケースを記述する。

```cpp
constexpr int twice(int a){ return a*2; }

static_assert( twice(2) == 4, "twice is broken!" );
```

なぜstatic_assertが効果的かというと、未定義動作になる式はコンパイル時定数になれないからである。
static_assertを通った関数は、未定義動作を起こしていないことが保証される。


## 5.9 デバッグ方法

### 5.9.1 printf デバッグ

__printfデバッグ最強__

バグ付近で変数をprintfしまくって引数をいろいろ変えて実行するだけ。
最も効果的である（ほんまか🤔

どの時点で値が期待と異なる結果になっているのかがよくわからないとデバッグできぬ。
それを絞り込むのによい。

### 5.9.2 デバッガ

Visual Studioを使っている場合、デバッガが強い。
もちろんGDBも強い。
実行中のプロセスにアタッチできる。
そして、ステップ実行で挙動を確認したり、ブレークポイントで変数の中身を確認したりできる。

申し訳ないが、デバッガ使わなさすぎて書くことがない。

### 5.9.3 サニタイザ

やばい挙動に遭遇したらまずサニタイザで可能性を潰そう。
サニタイザはコンパイラのオプションである。

[GCC Instrumentation-Options](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html)
[Clang 7 Documentation](http://clang.llvm.org/docs/index.html)

clangを例にすると

- AddressSanitizer
- ThreadSanitizer
- MemorySanitizer
- UndefinedBehaviorSanitizer
- DataFlowSanitizer
- LeakSanitizer

などの様々なサニタイザが存在する。
データフローサニタイザはgccになかったような気がするが、他はあると思う。

例えばclangでは

```-g -fsanitize=address -fno-omit-frame-pointer```

を追加することで実行時にバッファオーバーフロー/ヒープオーバーフローが検出できる。

利用しない手はない。

### 5.9.4 スタックトレース

IDEのサポートで簡単にできる。

IDEを使っていない場合、[Boost.StackTrace](http://www.boost.org/doc/libs/master/doc/html/stacktrace/getting_started.html)が便利。
こちらが[Boost.StackTraceを使っている様子](https://wandbox.org/permlink/wPlaN6qmwu4N4y8i)です。

### 5.9.5 例外

具合がわるいコードを書いたらどこぞから例外が飛んできた。
みたいなことはまあよくある。
デバッグするにはError Conditionが分からないとイカン。

もし標準ライブラリからやってきた例外なら、規格書にError Conditionが書いてある。
例外を投げてそうな関数をcppreference.comで調べるとかしよう。
下手にググるよりに規格書を開いた方が速いだろう。


## 5.10 規格書（Draft）を極める

### 5.10.1 各Versionの規格を理解する

正式な規格書を購入するには198スイスフランの費用がいる。
2018/3/28現在で

```math
198\ CHF = 22,056\ JPY
```

である。
規格書を購入は煩わしい。
大抵はドラフトを参照する。

ドラフトのリポジトリは[ここ](https://github.com/cplusplus/draft)にある。

ISOとISOが発行される直前のワーキングドラフト（ISOに一番近いドラフト）の対応は以下だと思う（自信がない

| Version | Draft | International Standard |
| ------- | ----- | ---------------------- |
| C++11   | N3337 | ISO/IEC 14882:2011     |
| C++14   | N3936 | ISO/IEC 14882:2014     |
| C++17   | N4661 | ISO/IEC 14882:2017     |


あと最新のドラフトを参照したいなら[このサイト](http://eel.is/c++draft/)も便利。
Twitterでドラフトを参照して議論するときとかにどうぞ。

規格書を調べるときは、大雑把にどこに何が書いてあるか把握しておかないとかなり厳しい。
慣れてくると、ググるより必要な情報にたどり着くのが早かったりする。
最初から規格書読んどけばよかったってこともよくある。

### 5.10.2 Proposal（提案書）を追いかける

次期C++の規格に入れるべきであるとする言語機能・ライブラリの提案書がいっぱいある。
👇ここ
[C++ Standards Committee Papers](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/)

~~C++の末路を観察できる。~~



## 5.11 数学をかじる

数学が分かるといろいろ便利。

C++には数学の知識があるとスッと入ってくるが、知識がないと理解が厳しい仕様が結構ある。
計算機数学もそうだけど、群論とかの代数学をわかっておくといい気がする。


そう言えば、C++2aのドラフトに入った__Constraint__の仕様を読んだが、どう見ても記号論理学の言葉で仕様が記述されている。
述語論理をしらなかったら読むのに相当の時間がかかるはずだ。

幸いなことに、解読者がQiitaに記事を書いている。
[制約とコンセプトとオーバーロードと半順序](https://qiita.com/kazatsuyu/items/ea6b8f1c8c7d384505b8)

# § 6 C++かわいい

C++を学ぶ心得=REDサイクル（投稿直前の雑な思いつき

![RED.jpg](https://qiita-image-store.s3.amazonaws.com/0/100319/6b9f6c6e-a88c-1427-3328-886a614d34a7.jpeg)


__R__esearch：C++の規格・ライブラリ・テクニックについて調べる
__E__xperiment：C++の規格・ライブラリ・テクニックを使ってみる
__D__evelopment：蓄えたC++の知識・技法を生かし、より良い開発をする



まあ、最終的に開発に役に立たなければあまり意味がない（おまえがいうな）。
調べたことを実際に使ってみて、しっかりと開発に役に立てていこうみたいなことが言いたい。