c++ - 具有多个模板参数包的部分模板特化

标签 c++ templates c++11 variadic-templates

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

在成员函数声明中,gcc 给了我错误

parameters packs must be at the end of the parameter list.

据我所知,编译器应该能够为给定的模板实例定义正确的成员函数,例如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 If the parameter-declaration-clause terminates with an ellipsis or a function parameter pack (14.5.3), the number of arguments shall be equal to or greater than the number of parameters that do not have a default argument and are not function parameter packs.

14.8.2.5/10 [Note: A function parameter pack can only occur at the end of a parameter-declarationlist(8.3.5). -end note]

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

关于c++ - 具有多个模板参数包的部分模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4706677/

相关文章:

c++ - Eclipse 方法无法在简单程序 C++ 中解析

c++ - 使用 Poco 迭代 json 结构

c++ - 如何从 QFile 中读取带符号的 16 位整数?

c++ - 接受可变数量的相同类型的参数

c++ - 编译器忽略的指针运算

c++ - 为什么默认模板参数不适用于 using 声明?

php - JavaScript:如何获取绝对 Base-URL?

c++ - 如何创建仅包含主文件和模板 header 的 makefile (C++)

c++ - 编译模板时出现 clang 错误

c++ - 为什么 weak_ptr 没有比较运算符==?