ここ数年、私たちは「C++ルネサンス」について語ってきました。Microsoftがこの動きの大きな担い手だったことは認めなければなりません。Craig Symonds と Mohsen Agsen がそれについて語ったこの 動画 を覚えています。
2011年、Microsoftは多くの記事でC++の復活を発表し、Herb Sutter をはじめとするMicrosoftのC++専門家たちは、なぜC++が復活したのかを説明する講演を数多く行い、主にModern C++の使用を推奨しました。同時期にC++11標準が承認され、私たちはC++を新しい言語として語り始めました。
2011年の時点で、C++はすでに30年以上使われていました。新しいC++が実際にC++利用の多くの苛立たしい側面を単純化し、C++コードを改善する新しいモダンな方法があることを開発者に納得させるのは容易ではありませんでした。
例としてメモリ管理を見てみましょう。これはおそらくC++で最も批判されてきた側面の1つです。長年、オブジェクトの割り当てには new キーワードが使われ、開発者はコード内のどこかで delete を呼び出すことを覚えておく必要がありました。「Modern C++」は、スマートポインタの使用を推進することでこの問題を解決しました。
数年前にC++0xが発表されたとき、私はそれがC++言語に大きな影響を与えることはないだろうと考えていましたが、それは間違いでした。Follyのこのコードスニペットを見てください。まるで新しい言語で開発されたかのようです。

同じことがFollyのほぼすべてのソースコードに当てはまります。その実装はC++03コードとは大きく異なって見えます。
C++の過去の影響をどう限定するか?
魔法のような解決策はありません。C++コンパイラが、古い文字列操作関数(strcpy、strcat など)のような非推奨の慣行について警告を出して助けてくれることを期待できます。しかし、この解決策の影響はそれほど大きくありません。Modern C++とは、主に新しいイディオムを学び、実践することです。
もう1つの方法は、「Modern C++」という新しい言語が作られたと考えることです。以前と同じWeb検索を、今度は「Modern C++」のオブジェクト割り当てについて行ってみましょう。最初のリンクはスマートポインタについて説明しているはずです。
新しい言語 MC++ を発見する
MC++の力をよりよく知るには、その機能を使っている成熟したプロジェクトのソースコードを探索するのが良い方法です。FacebookのFollyは非常に良い候補です。
Follyで使われているMC++の機能をいくつか見てみましょう。
1. auto
C++11では auto キーワードによる型推論が導入されました。これにより、コンパイラは変数の宣言時にその型を推論します。Follyではほぼすべての変数宣言で auto が使われています。ソースコードからの例を次に示します。

auto キーワードを使えば、コンパイラがすでに知っていることを書く時間を減らせます。
2. nullptr
従来、定数0は整数定数とヌルポインタ定数という2つの役割を担ってきました。C++11では、区別可能なヌルポインタ定数として機能する新しいキーワード nullptr が導入され、この問題が修正されました。
Follyのソースコードでは、すべてのヌルポインタが新しいキーワード nullptr で表されており、定数0が使われている場所はありません。
3. shared_ptr
スマートポインタは新しい概念ではありません。多くのライブラリが何年も前に実装しており、最も有名なのは boost::shared_ptrです。新しいのは、それらが標準化された点です。スマートポインタを使うために外部ライブラリを利用する必要はもうありません。
Follyでは標準化された共有ポインタが広範に使われており、ソースコード内に残っている生ポインタはごくわずかです。
4. 強く型付けされた列挙型
C++の「従来の」列挙型は、列挙子を周囲のスコープへエクスポートします。そのため、同じスコープ内の異なる2つの列挙型が同名の列挙子を定義すると、名前衝突が発生する可能性があります。
C++11では enum class キーワードが導入されました。これらの列挙型は列挙子を周囲のスコープへエクスポートしなくなりました。さらに、列挙型の基底型を指定できるようになりました。

5. static assert
C++11では、新しいキーワード static_assert を使って、コンパイル時にアサーションをテストする新しい方法が導入されました。この機能は、Follyのソースコードにある次のテンプレートクラスのように、テンプレートパラメータへ条件を追加する際に非常に便利です。

6. 可変引数テンプレート
可変引数テンプレートとは、任意の型のテンプレート引数を任意の数だけ受け取れるテンプレートです。クラステンプレートと関数テンプレートの両方を可変引数にできます。Follyでは多くの可変引数テンプレートが定義されています。Follyのソースコードから、2つの可変引数テンプレート関数を次に示します。

7. 範囲ベースforループ
C++11では、コレクションを反復処理する「foreach」パラダイムをサポートするために for 文が拡張されました。これによりコードがよりシンプルでクリーンになります。Follyではこの機能が広く使われています。例を次に示します。

8. 初期化子リスト
C++03では、初期化子リストは配列にのみ適用されます。C++11では、配列に限定されなくなりました。 {}リストを受け取る仕組みは、 std::initializer_list<T>型の引数を受け取る関数(多くの場合コンストラクタ)です。std::initializer_list を引数として受け取る関数の例を次に示します。

そして、次がその呼び出し方法です。

9. noexcept
関数が例外をスローできない場合、またはプログラムが関数からスローされる例外を処理するように書かれていない場合、その関数は noexcept として宣言できます。
Follyのソースコードからの例を次に示します。

10. move
C++11では、左辺値への参照と右辺値への参照を区別するために、右辺値参照(&& で指定)の概念が導入されました。左辺値は名前を持つオブジェクトで、右辺値は名前を持たないオブジェクト(一時オブジェクト)です。ムーブセマンティクスにより、右辺値を変更できます。
これをサポートするため、C++11では2つの新しい特殊メンバ関数が導入されました。 ムーブコンストラクタ と ムーブ代入演算子。


こちらの 優れたドキュメント では、ムーブセマンティクスの利点がより詳しく説明されています。
11. ラムダ
C++11では、ラムダ関数と呼ばれる無名関数を作成する機能が提供されました。この新機能の詳細は こちら を参照してください。
Follyでは多くの関数でラムダが使われています。ソースコードからの例を次に示します。

12. 明示的にデフォルト化・削除された特殊メンバ関数
C++03では、クラス自身が定義していない場合、コンパイラはデフォルトコンストラクタ、コピーコンストラクタ、コピー代入演算子(operator=)、デストラクタを提供します。プログラマーはカスタム版を定義して、これらの既定実装を上書きできます。
しかし、これらの既定実装の生成を制御する手段はほとんどありません。たとえば、クラスを本質的にコピー不可にするには、プライベートなコピーコンストラクタとコピー代入演算子を、定義せずに宣言する必要がありました。
C++11では、特定の特殊メンバ関数を明示的に無効化できます。たとえば、次の型はコピー不可であり、コードがよりシンプルでクリーンになります。

13. override識別子
C++03では、基底クラスの関数をオーバーライドするつもりだったのに、誤って新しい仮想関数を作成してしまう可能性がありました。
「 override 」という特殊識別子を指定すると、コンパイラは基底クラス(複数の場合もあります)を調べ、まったく同じシグネチャを持つ仮想関数があるかを確認します。存在しない場合、コンパイラはエラーを報告します。
Follyではこの新機能が広く使われています。

14. std::thread
スレッドクラス(std::thread)が提供されており、新しいスレッドで実行する関数オブジェクトと、必要に応じて渡す一連の引数を受け取ります。
C++11ではスレッドを扱うのがより簡単になりました。Follyのソースコードから、新しいスレッドを定義する標準的な方法を次に示します。

15. 順序付けされていないコンテナ
順序付けされていないコンテナは、一種のハッシュテーブルです。C++11では次の4つの標準コンテナが提供されています。
- unordered_map
- unordered_set
- unordered_multimap
- unordered_multiset
Follyでは、これらの新しいコンテナが多くの場所で使われています。

まとめ:
新しいC++開発者へのアドバイスとして、C++は名前が変わったと考え、Web検索では単にC++ではなく「Modern C++」を使ってください。結果は大きく変わります。C++だけで検索すると、多くの場合、古い慣行にたどり着いてしまいます。
