继续学习可变参数模板,我遇到了另一个问题。
假设有以下模板类:
template < typename T >
struct foo
{
//default implementation
};
可以对可变模板实例进行部分特化,例如:
template < template < typename ... > class T, typename ...Args >
struct foo< T< Args... > >
{
//specialized implementation
};
有了这个,foo< int >
将对应于默认实现,foo< std::tuple< int,char >>
将对应于专门的实现。
然而,当使用多个模板参数时,情况变得更加复杂。例如,如果我们有以下模板类
template < typename T, typename U >
struct bar {};
如果像我们对foo
所做的那样部分专门化它,我们将无法实现。
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > > {};
//This would correspond to the specialized version with
//T=std::tuple,
//TArgs=int,char
//U=std::tuple,
//UArgs=float
bar< std::tuple< int, char >, std::tuple< float > > b;
事实上,如果我没记错的话,在模板参数列表中我们只能有一个模板参数包,并且它必须位于末尾。我理解在模板声明中这是强制性的原因,但对于某些部分模板特化(比如上面的例子),这不应该成为问题。
是否可能使用多个模板参数包来实现部分模板特化?
编辑: 现在我感到有点傻...我上面给出的代码可以完美编译(至少在gcc 4.5下是可以的)。我遇到的编译错误不是因为多个参数包,而是因为它们作为成员函数参数的使用。在bar
的部分特化中,我尝试定义一个同时接受TArgs
和UArgs
参数的成员函数:
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > >
{
void method( TArgs... targs, UArgs... uargs ) //compile error here
{
}
};
在成员函数声明中,gcc给出了错误提示:
据我所知,编译器应该能够为给定的模板实例定义正确的成员函数,例如参数包必须在参数列表末尾。
bar< std::tuple< int, char >, std::tuple< float > >
应该包含一个成员函数void method( int, char, float )
。我做错了什么吗?或者我试图做一些不可能的事情吗?如果是这样,有没有一个很好的理由说明为什么这不可能?