2010-02-28

gcc4.5がVariadic TemplateのDependant name resolutionに対応していない

追記:これはgccのバグではなく、規格上の問題であった。

Dependant Nameは、Point of instantiationに解決される。つまり、

// point of difination of f
template < typename T >
void f(T x) { g(x) ; }

// point of difination of g
template < typename T >
void g(T) { }

int main()
{
// point of instantiation of f.
// also g.
        f(0) ;
}

このコードは、well-formedである。たしかに、fのpoint of difinationからは、gという名前は見えない。しかし、g(x)という式は、type-dependant expressionであるので、Dependant nameである。したがって、gのname lookupは、point of instantiationに行われる。すなわち、mainの中である。mainでは、gはすでに宣言されているので、問題なくgを使うことができる。

gccはVariadic Tempalteをサポートしていると聞いたので、以下のようなコードを書いてみた。

template < typename T, typename ... Args >
T max( T const & a, T const & b, Args ... rest)
{
        return max( max(a, b), rest ... ) ;
}

template < typename T >
T max( T const & a, T const & b )
{
        return a < b ? b : a ;
}


int main()
{
        max(1, 2, 3) ;
}

ところが、gccは、このコードに対して、エラーを吐いた。しかし、どうもそのエラーメッセージがおかしい。試しに、以下のように書き換えてみたところ、

// 順番を逆にした
template < typename T >
T max( T const & a, T const & b )
{
        return a < b ? b : a ;
}

template < typename T, typename ... Args >
T max( T const & a, T const & b, Args ... rest)
{
        return max( max(a, b), rest ... ) ;
}

これは、コンパイルが通った。明らかに、Variadic TemplateがらみのDependant Nameを、point of difinationで解決している。これは誤りである。

No comments: