【发布时间】:2021-01-14 03:07:15
【问题描述】:
最新c++标准中非特化类模板成员的显式特化声明规则如下:
在为类模板的成员或出现在命名空间范围内的成员模板的显式特化声明中,成员模板和它的一些封闭类模板可能保持非特化,除非声明不应显式特化一个类成员模板,如果它的封闭类模板也没有明确专门化。在这样的显式特化声明中,应提供后跟模板参数列表的关键字模板,而不是在成员的显式特化声明之前的模板。模板参数列表中模板参数的类型应与主模板定义中指定的相同。
老实说,我对这一段有很多困惑。请考虑写在本规则下面的例子。
template <class T1> class A {
template<class T2> class B {
template<class T3> void mf1(T3);
void mf2();
};
};
template <class Y>
template <>
void A<Y>::B<double>::mf2() { } // error: B<double> is specialized but
// its enclosing class template A is not
正如评论所说,成员mf2 的这个明确的专业化声明格式不正确,但是,我不明白为什么这个声明通过这条规则是不正确的。我的理由是粗体字,它表示声明不应明确特化类成员模板,如果它的封闭类模板也没有明确特化。但是,在此示例中,声明是 mf2 的显式特化,它不是类成员模板,而是类模板的成员。所以严格来说,它不符合异常的条件,为什么声明是错误的?感觉这一段不太清楚。于是深入挖掘,我发现有缺陷的报告是CWG529。
上面写着:
在对类模板的成员或出现在命名空间范围内的成员模板的显式特化声明中,成员模板和它的一些封闭类模板可能保持非特化,即相应的模板前缀可以指定一个模板-parameter-list 而不是 template 和命名模板的模板 ID 使用这些模板参数作为模板参数编写。在这样的声明中,模板参数的数量、种类和类型应与主模板定义中指定的相同,模板参数在模板ID中的命名顺序应与它们出现的顺序相同在模板参数列表中。 在命名成员的限定 ID 中,非特化模板 ID 不得位于模板特化的名称之前。
想了想,还是觉得提案不足以解释这些案例,例如:
template <class T1> class A {
template<class T2> class B {
template<class T3> void mf1(T3);
void mf2();
};
};
template<>
template <class T>
void A<int>::B<T>::mf2(){}
首先,mf2 不是模板特化,但是模板 ID B<T> 在 mf2 之前,此声明格式不正确。它仍然无法解释这个例子:
template <class T1> class A {
template<class T2> class B {
template<class T3> void mf1(T3);
void mf2();
};
};
template<>
template <class T>
template <class U>
void A<int>::B<T>::mf1(U){}
mf1 是模板名称,但不是模板 ID(即模板特化)
所以在考虑了这些格式错误的例子之后,恕我直言,这个修改过的句子是这条规则的意图吗?
在为类模板的成员或出现在命名空间范围内的成员模板的显式特化声明中,成员模板和它的一些封闭类模板可能保持未特化。在这样的显式特化声明中,应提供后跟模板参数列表的关键字模板,而不是在成员的显式特化声明之前的模板。模板参数列表中模板参数的类型应与主模板定义中指定的相同。 在此声明中,nested-name-specifier 中未特化的每个
template-id都应显式特化。
template <class T1> class A {
template<class T2> class B {
template<class T3>
void mf1(T3);
void mf2();
};
};
template<> // explicit specialization for `B`
template<class T>
class A<int>::B{
template<class U>
void mf1(U);
};
template<>
template<class T>
template <class U>
void A<int>::B<T>::mf1(U){}
这个例子的格式不正确,虽然B<T> 是非特化的,但它已经被显式特化了。这是一个很好的解释吗?或者,如果我看错了原始规则,请解释如何理解它。
【问题讨论】:
标签: c++ templates language-lawyer