近年、「C++のルネサンス」について多くの議論が交わされてきました。この復活においてMicrosoftが重要な役割を果たしたことは否定できません。
2011年、Microsoftは多くの記事でC++の復活を発表し、Herb SutterなどのMicrosoft C++エキスパートは、主にModern C++の使用を推奨しながら、C++が復活した理由を説明する多くの講演を行いました。同時期にC++11標準が承認され、私たちはC++を新しい言語として語るようになりました。
2011年までに、C++は30年以上使用されてきました。現代的なC++が実際にC++使用時の多くの苛立たしい側面を簡素化し、C++コードを改善する新しい現代的な方法があることを開発者に納得させるのは容易ではありませんでした。
まだC++11へ移行していないC++開発者は、clang-tidyを使ってコードベースのどこをモダナイズできるかの提案を得るか、 CppDependのモダナイズ機能を試すことができます。以下は、オープンソースC++ライブラリで最も広く使われている15の機能です。
例として、Facebookが6年前に公開した Follyを見てみましょう。Follyは、Facebook内部で広く使用されている、再利用可能なC++ライブラリコンポーネントの大規模なコレクションです。そのWebサイトでは、作成の背景にある動機が次のように説明されています:
Folly(Facebook Open Source Libraryをゆるやかに略したもの)は、実用性と効率を重視して設計されたC++11コンポーネントのライブラリです。これはBoostや、もちろん stdと競合するのではなく、それらを補完するものです。実際、必要なものが利用できない場合や、必要な性能特性を満たさない場合にのみ、独自コンポーネントの定義に取りかかります。そのソースコードから、15のC++11機能を見ていきましょう:
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は標準化されたshared pointerを広く使用しており、そのソースコードには生ポインタがわずかしか残っていません。
4. 強く型付けされたenum
C++の「従来の」enumは、その列挙子を周囲のスコープへエクスポートします。そのため、同じスコープ内の2つの異なるenumが同名の列挙子を定義すると、名前衝突につながる可能性があります。
C++11では、enum classキーワードが導入されました。これらは列挙子を周囲のスコープへエクスポートしなくなりました。さらに、enumの基底型を指定できるようになりました。

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

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

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

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

そして、その呼び出し方法は次のとおりです。

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

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


ムーブセマンティクスの利点をより詳しく説明している 優れたドキュメント はこちらです。
11. lambda
C++11では、 ラムダ関数。
Follyは多くの関数でそれらを使用しています。以下は、そのソースコードからの例です:

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

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

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

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

