C++11
これは再帰呼び出しを使っている。可変長テンプレート引数バージョンのprintfは自身を再帰的に呼び出し、argsが空の場合はシンプルな方のprintfが呼ばれることになる。
可変長テンプレート引数に順次アクセスする簡単な方法は無い。しかし、unpack演算子を用いることで、どこでも仮想的にテンプレート引数を解体できる。
例えば、クラスを以下のように使用できる:
unpack演算子により、ClassNameの各基底クラス型が複製され、このクラスは渡された各型の導出クラスとなる。また、ClassNameの基底型を初期化できるように、コンストラクタは各基底クラスへの参照を取る。
関数テンプレートでは、取った可変長引数を先へと転送できる。右辺値参照と組み合わせることで、完璧な転送が行える。
この特殊なファクトリ関数は、メモリリークに対する安全性のため、割り当てられたメモリをtr1::shared_ptrに自動的に包むものである。上記のように、引数リストを解体してTypeToConstructのコンストラクタへと渡している。static_cast<Args&&>(params)構文で、const性などを保ちつつ、引数の適切な型をコンストラクタへと転送できる。unpack演算子により、それぞれのパラメータに上記の伝播文法を適用できる。
また、テンプレートパラメータの数を以下のように決定できる:
SomeStruct<Type1, Type2>::sizeは2となり、SomeStruct<>::sizeは0となるであろう。
C++03では、初期化子リスト (initializer list) の考え方を C から引き継いでいる。つまり、構造体のメンバ定義の順に、引数を波括弧{ }の中に記述するというものである。初期化子リストは再帰的に適用されるので、構造体の配列や構造体を含む構造体にも使用できる。
この初期化子リストは、静的なデータの初期化や構造体を特定の値に初期化したいときなどに有用である。C++ にはコンストラクタもあるが、初期化子リストの方が有用である。しかし、C++03 では初期化子リストは Plain Old Data (POD) 型と認識された構造体・クラスにしか適用できなかった。std::vector などの非 POD クラスには初期化子リストは使えなかった。
C++11 では、初期化子リストの考え方がテンプレートと結び付けられた。これには、std::initializer_list を用いる。これによって、コンストラクタなどの関数は、初期化子リストを引数として取ることができる。
C++03 には既に定数式が存在している。定数式とは、3 + 4 のように、常に同じ結果を返し副作用の無いものである。定数式はコンパイラの最適化の対象となり、多くの場合コンパイル時に演算が行われ、プログラム中にはその結果のみが格納される。また、C++ の仕様中でも、多くの箇所で定数式の使用が必要となる。配列の定義にも要素数として定数式が必要であるし、列挙子の値にも必要である。
しかし、関数呼び出しやオブジェクトコンストラクタが出現すると、定数式ではなくなる。単純な例を挙げると:
GetFive() + 5 が定数式でないため、これは C++03 では不正となる。実際には GetFive は実行時に一定値を返すが、コンパイラにそれを知らせる方法がないのである。理論上、関数はグローバル変数に影響を与える、実行時に結果が変わる他の関数を呼ぶ、などの理由がある。
C++11 では、キーワード constexpr が導入される。これにより、関数やオブジェクトコンストラクタがコンパイル時定数であることを保証できる。上の例は、以下のように書き直せる:
これによりコンパイラは、GetFive がコンパイル時定数であることを理解し、検証できる。
constexpr を関数に使用する場合、関数内でできることは非常に制限される。まず、関数は非 void 型の戻り値を持たねばならず、内容として return expr の形を持たねばならない。そして、引数を置き換えた後、expr は定数式でなくてはならない。ここでいう定数式では、constexpr として定義された他の関数を呼ぶか、他の定数式データ変数を使うかしかできない。