继续 我进入variadic模板世界的旅程, ,我遇到了另一个问题。

假设以下模板类:

template < typename T >
struct foo 
{
    //default implementation
};

可以部分地将其部分专门用于variadic模板的实例:

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

在成员函数声明中,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"
}

我不确定该代码是否严格符合,但是就我阅读N3225 14.5.3而言,我找不到说明哪些说明模板参数包必须是最后一个模板参数。

编辑:
我重读N3225并找到以下陈述:

8.3.5/4如果参数 - 删除 - 惯例用省略号或函数参数包终止(14.5.3),则参数的数量应等于或大于没有默认参数和没有默认参数和的参数数量不是功能参数包。

14.8.2.5/10 [注意:一个函数参数包只能在参数 - 数据结束时(8.3.5)的末尾发生。 - 末尾注

因此,正如您提到的那样,函数参数包必须不幸的是最后一个参数。
当该类实例化(完全专业)时,类模板的非模板成员函数是该类的普通函数。因此,我希望这个问题中的代码可以作为一种特殊情况来逻辑上编译。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top