6年前、Facebookは FollyというC++ライブラリを公開しました。これは、Facebook内部で広く使われている再利用可能なC++ライブラリコンポーネントの大規模なコレクションです。
しかし、成熟したオープンソースのC++ライブラリはすでに多数存在します。では、なぜ新たなライブラリを導入したのでしょうか。そのWebサイトで説明されている、開発の動機は次のとおりです。
Folly(Facebook Open Source Library をゆるやかに略した名称)は、実用性と効率性を念頭に設計されたC++11コンポーネントのライブラリです。Boost、そしてもちろん stdといった既存の提供物と競合するのではなく、それらを補完します。実際、必要なものが利用できないか、必要なパフォーマンス特性を満たしていない場合にのみ、独自のコンポーネントを定義しています。たとえば、Follyが新たなベクタークラス FBVector を導入した理由については、こちらの 詳細な説明 を参照してください。Follyの開発者が主張しているように、これはC++11コンポーネントのライブラリです。その主張はソースコードを見れば十分に裏付けられます。C++11機能が広範に使われており、さらに、ほぼすべての新しいC++11機能が使われています。
数年前にC++0xが発表されたとき、私はそれがC++言語に大きな影響を与えることはないだろうと考えていましたが、それは間違いでした。Follyのこのコードスニペットを見てください。まるで新しい言語で開発されたかのようです。

同じことがFollyのほぼすべてのソースコードに当てはまります。その実装はC++03のソースコードとは異なって見えます。
新しいC++11機能の習得に関心がある開発者にとって、最良のアプローチの1つは、成熟したライブラリがそれらをどう使っているかを見ることです。Follyは新機能を探索するうえで非常に良い候補です。そのソースコードからいくつかを見てみましょう。
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では、コレクションに対する範囲ベースの反復処理をサポートするように for 文が拡張されました。これによりコードがよりシンプルでクリーンになります。Follyではこの機能が広く使われています。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では、これらの新しいコンテナが多くの場所で使われています。

まとめ
Follyでは、ほぼすべての新しいC++11機能が使われています。そのソースコードを探索すれば、新しいC++の機能と、それらが実際にどう使われているかをより深く理解できます。
C++11に関心のあるすべてのC++開発者に、FollyのソースコードをダウンロードしてモダンC++の力を探索することをお勧めします。
