以下は、GoingNative 2012でのAndrei Alexandrescuによる講演「Variadic Templates are Funadic」からの引用です。可変テンプレートの良い入門書としてお勧めします。
Variadicパックでできることは2つあります。応募可能ですsizeof...(vs)
要素の数を取得して拡張するためするです。
拡張ルール
Use Expansion
Ts... T1, ..., Tn
Ts&&... T1&&, ..., Tn&&
x<Ts,Y>::z... x<T1,Y>::z, ..., x<Tn,Y>::z
x<Ts&,Us>... x<T1&,U1>, ..., x<Tn&,Un>
func(5,vs)... func(5,v1), ..., func(5,vn)
拡張は内側に向かって外側に進みます。ロックステップで2つのリストを展開する場合、それらは同じサイズでなければなりません。
その他の例:
gun(A<Ts...>::hun(vs)...);
Ts
のテンプレート引数リストのすべてを展開するA
と、関数hun
はallで展開されますvs
。
gun(A<Ts...>::hun(vs...));
すべての拡大Ts
のテンプレート引数リスト内A
とすべてvs
のための関数の引数としてhun
。
gun(A<Ts>::hun(vs)...);
ロックステップ機能hun
付きTs
およびvs
ロックステップ機能を拡張します。
注意:
Ts
はタイプでvs
はなく、値でもありません!これらは、タイプ/値のリストのエイリアスです。どちらのリストも空になる可能性があります。どちらも特定のアクションのみに従います。したがって、以下は不可能です。
typedef Ts MyList; // error!
Ts var; // error!
auto copy = vs; // error!
拡張軌跡
関数の引数
template <typename... Ts>
void fun(Ts... vs)
初期化リスト
any a[] = { vs... };
基本指定子
template <typename... Ts>
struct C : Ts... {};
template <typename... Ts>
struct D : Box<Ts>... { /**/ };
メンバー初期化子リスト
// Inside struct D
template <typename... Us>
D(Us... vs) : Box<Ts>(vs)... {}
テンプレートの引数リスト
std::map<Ts...> m;
引数が一致する可能性がある場合にのみコンパイルされます。
キャプチャリスト
template <class... Ts> void fun(Ts... vs) {
auto g = [&vs...] { return gun(vs...); }
g();
}
属性リスト
struct [[ Ts... ]] IAmFromTheFuture {};
仕様書にはありますが、型として表現できる属性はまだありません。
...
、識別子が導入される前にが来ます。どちらか一方または両方のタイプのパックを使用する場合、...
は展開する表現パターンの後に来ます。