2012-08-24

Variadic templateのものすごいコード

14.5.3 paragraph 4に、以下のような記述がある。

Pack expansions can occur in the following contexts:

-- In a template parameter pack that is a pack expansion (14.1):

-- if the template parameter pack is a type-parameter with a template-parameter-list; the pattern is the corresponding type-parameter without the ellipsis.

ここで詰まってしまった。この条件に当てはまるコードがさっぱり思いつかない。一体、これはどのようなコードのための条件なのだろうか。

まず、template-parameter-listのあるtype-parameterとは、template template parameterのことである。それはいい。しかし、そのcorresponding type-parameterとは一体何だ。しかも、それはtemplate parameter packであると同時に、pack expansionでなければならないのだ。

pack expansionとなるtemplate parameter packの例としては、以下のようなコードがある。

template < typename T, T ... Values >
struct X ;

この場合、"T ..."はpack expansionであると同時に、template parameter packでもある。だから、以下のようなコードも書ける。

template < typename T, T * ... Values >
struct X ;

この場合は、ひとつ上の条件である。

-- if the template parameter pack is a parameter-declaration; the pattern is the parameter-declaration without the ellipsis;

に合致する。なぜならば、T ...はparameter-declarationだからだ。

では、parameter-declarationではない場合とは何か。これがさっぱり思いつかない。

とりあえず以下のようなコードを思いついたが、これは違う。

template < typename T, template < T ... > class ... Temps >
struct X ;

なぜならば、T...はparameter-declarationだからだ。

一向に分からなかったので、人に聞いた。すると、とんでもないコードが返ってきた。

template< typename ... Types >
struct Outer
{
    template< template< Types > class ... X >
    struct Inner ;
} ;

なるほど、たしかにこれはpack expansionなtemplate parameter packで、template-parameter-listのあるtype-parameterがtemplate parameter packだ。すべての条件を満たすコードだ。

問題は、現在このコードを通すC++コンパイラーが存在しないという事だ。

追記:このことはだいぶ前に、core issueにも上がっていたらしい。現在の文面は、その解決案らしい。

Core issue 778

また、clangでも実装するべく動いている。

Bug 9023 – Prematurely diagnoses unexpanded parameter packs

No comments: