可変長テンプレートの使い道が「型安全な printf」と「tuple」と「転送関数 (関数オブジェクト)」ぐらいだと思っている人へ送る,ちょっと早めの素敵な variadic Valentine プレゼント

N2461 より "12.6.2 Initializing bases and members" の 10 の例示コード.

template<class... Mixins>
class X : public Mixins...
{
public:
X(const Mixins&... mixins) : Mixins(mixins)... { }
};

同じく N2461 より "14.5.3 Variadic templates" の 5 における例示コード.

template<typename...> struct Tuple {};
template<typename T1, typename T2> struct Pair {};
template<class ... Args1> struct zip {
  template<class ... Args2> struct with {
    typedef Tuple<Pair<Args1, Args2> ... > type;
  };
};
typedef zip<short, int>::with<unsigned short, unsigned>::type T1;
  // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>
typedef zip<short>::with<unsigned short, unsigned>::type T2;
  // error: different number of arguments specified for Args1 and Args2
template<class ... Args> void g(Args ... args)
  {
  f(const_cast<const Args*>(&args)...); // OK: “Args” and “args” are expanded
  f(5 ...); // error: pattern does not contain any parameter packs
  f(args); // error: parameter pack “args” is not expanded
  f(h(args ...) + args ...); // OK: first “args” expanded within h, second “args” expanded within f
  }

もう完全に syntax レベルのメタプログラミングやね.こういう面白い使い方見せられるともっと汎用なメタプログラミングツールとして規格化して欲しかったにゃーって思うけれど.
N2461 の段階で想定されている, pack expansion が可能な場所は

  • initializer-list
  • base-specifier-list
  • mem-initializer-list
  • template-argument-list
  • exception-specification

だけなんだよねー.まぁ,これだけの場所で使うことができるなら,できないことはほとんどない気もするけれど.