这是一个什么专业化?

时间:2014-12-28 16:29:29

标签: c++ template-meta-programming

我正在观看this讲座,其中以下示例(@ 29.43)作为专业展示:

template<class T>
struct rank
{
    static const size_t value = 0u; 
}

// partial specialization
template<class U, size_t N>
struct rank<U[N]>
{
    static const size_t value = 1 + rank<U>::value; 
}

我希望编译错误,抱怨结构的声明不可插入,第二个模板参数太多。 上述情况如何不是错误?

2 个答案:

答案 0 :(得分:10)

专业化可以自己拥有模板参数。具有模板参数的专业化称为部分专业化。

template<class T>
struct rank { ...1 };

表示rank<T>是一个类,除非另有说明,...1是类的定义。

template<class U, size_t N>
struct rank<U[N]> { ...2 };

是“另行指定”:这意味着如果T中的rank<T>可以写为U[N]某种类型U而某些常量N },然后...2是类的定义。

您可以像rank<int[2]>一样使用它,它会使用U = intN = 2的第二个类定义。

答案 1 :(得分:4)

这不是错误,因为它有效。

  

[C++11: 14.5.5/1]:主类模板声明是类模板名称是标识符的声明。类模板名称为 simple-template-id 的模板声明是 simple-template-id 中命名的类模板的部分特化。当特殊化中的参数与部分特化(14.5.5.1)中给出的参数匹配时,类模板的部分特化提供了替代主要定义的模板的替代定义。 [..]

根本没有规则禁止它,事实上,该标准包含了一个恰好这种情况的例子:

  

[C++11: 14.5.5/3]: [例如:

template<class T1, class T2, int I> class A { };             // #1
template<class T, int I>            class A<T, T*, I> { };   // #2
template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3
template<class T>                   class A<int, T*, 5> { }; // #4
template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5
     

第一个声明声明了主(非特定)类模板。第二个和后续声明声明了主模板的部分特化。 -end example]

具有讽刺意味的唯一限制因素是更接近(尽管不是精确地)与你声称的相反:

  

[C++11: 14.5.5/8]:在类模板部分特化的参数列表中,以下限制适用:

     
      
  • [..]
  •   
  • 专业化的参数列表不应与主模板的隐式参数列表相同。
  •   
  • [..]
  •   

您可以使用主要和模板以及部分专业化,如下所示:

int main()
{
    rank<char>   a;   // uses the primary
    rank<int[5]> b;   // uses the partial spec.
}