2011-01-16 46 views
15

继续my journey into the world of variadic templates,我遇到了另一个问题。具有多个模板参数包的部分模板专业化

假设下面的模板类:

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局部特殊化,我试图定义一个成员函数,它都TArgsUArgs参数:

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 
    { 
    } 
}; 

在成员函数声明,海湾合作委员会给我的错误

参数包必须是在参数列表的末尾。

据我所知,编译器应该能够为给定的模板实例化定义正确的成员函数,例如, bar< std::tuple< int, char >, std::tuple<float> >应该包含一个成员函数void method(int, char, float)。难道我做错了什么?或者我想做一些不可能的事情?如果是这样,那么为什么这是不可能的吗?

+0

整洁,我不知道你可以专门化/指定(模板列表的一部分)作为模板本身的元素。 – JAB

回答

6

也许这个答案不会直接清除你的问题, ,但是当我测试时,下面的代码在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" 
} 

我不知道该代码严格一致,但 据我读N3225 14.5.3,我找不到其中提到 该模板参数包必须是最后一个模板的声明参数。

编辑:
我重读N3225,发现下面的语句:

8.3.5/4如果参数声明子句 以省略号或 函数参数包终止(14.5.3 ),参数数量 应该等于 或大于 参数的数量,该参数没有默认的 参数,并且不是功能 参数包。

14.8.2.5/10 [注意:函数参数包只能在 参数声明表(8.3.5)的末尾 处出现。末端 注]

所以,正如你所说,函数参数包必须是最后一个参数 不幸。
类模板的非模板成员函数是该类在实例化(完全专用化)时的普通函数 。 所以我希望在这个问题中的代码可以逻辑编译,作为 特殊情况。

+0

你是对的,代码完美编译!我添加的问题其实有点不同,我会编辑这个问题...抱歉给您带来不便... –

+0

@LucTouraille:别担心:-)这对我来说是一个很好的自我教育场合。 –

+0

有些东西让我觉得这个报价并不打算在这里适用,因为这两个参数包都是已知的,只是需要扩展。如果铿锵会接受此代码,我不会感到惊讶 –