Luc*_*lle 15 c++ templates variadic-templates c++11
继续我的可变模板世界之旅,我遇到了另一个问题.
假设以下模板类:
template < typename T >
struct foo
{
//default implementation
};
Run Code Online (Sandbox Code Playgroud)
它可以部分地专门用于变量模板实例化,如下所示:
template < template < typename ... > class T, typename ...Args >
struct foo< T< Args... > >
{
//specialized implementation
};
Run Code Online (Sandbox Code Playgroud)
有了这个,foo< int >将对应于默认实现和foo< std::tuple< int, char > >专门的实现.
但是,使用多个模板参数时,事情会变得更加复杂.例如,如果我们有以下模板类
template < typename T, typename U >
struct bar {};
Run Code Online (Sandbox Code Playgroud)
我们想要像我们所做的那样对它进行部分专业化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;
Run Code Online (Sandbox Code Playgroud)
实际上,如果我是正确的,我们只能有一个模板参数包,它必须位于参数列表的末尾.我理解为什么这在模板声明中是强制性的,但对于某些部分模板特化(如上面的例子),这应该不是问题.
是否可以使用多个模板参数包实现部分模板专业化?
编辑:现在我觉得很傻......我上面给出的代码完美编译(至少使用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
{
}
};
Run Code Online (Sandbox Code Playgroud)
在成员函数声明中,gcc给出了错误
参数包必须位于参数列表的末尾.
据我所知,编译器应该能够为给定的模板实例化定义正确的成员函数,例如bar< std::tuple< int, char >, std::tuple< float > >应该包含成员函数void method( int, char, float ).难道我做错了什么?还是我想做一些不可能的事情?如果是这样,是否有充分理由说明这是不可能的?
可能这个答案不会直接解决你的问题,但是当我测试时,下面的代码在ideone(gcc-4.5.1)上编译.
#include <cstdio>
#include <tuple>
template< class, class > struct S {
S() { puts("primary"); }
};
template<
template< class... > class T, class...TArgs
, template< class... > class U, class...UArgs
>
struct S< T< TArgs... >, U< UArgs... > > {
S() { puts("specialized"); }
};
int main()
{
S< int, int > p; // "primary"
S< std::tuple< int, char >, std::tuple< float > > s; // "specialised"
}
Run Code Online (Sandbox Code Playgroud)
我不确定这段代码是否严格符合,但就我读N3225 14.5.3而言,我找不到提及模板参数包必须是最后一个模板参数的语句.
编辑:
我重读N3225并发现以下声明:
8.3.5/4如果参数声明子句以省略号或函数参数包(14.5.3)结束,则参数个数应等于或大于没有默认参数的参数个数.不是函数参数包.
14.8.2.5/10 [注意:函数参数包只能出现在参数声明列表(8.3.5)的末尾. - 尾注]
因此,正如您所提到的,不幸的是,函数参数包必须是最后一个参数.
类模板的非模板成员函数是实例化(完全专用)时该类的普通函数.所以我希望这个问题中的代码可以逻辑编译,作为一个特例.