我正在观看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;
}
我希望编译错误,抱怨结构的声明不可插入,第二个模板参数太多。 上述情况如何不是错误?
答案 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 = int
和N = 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.
}