C++模板类的成员模板的显式具体化

4
在当前的C++标准草案中,与模板显式特化相关的章节中有这个例子,出现在此段落中。
template<class T> struct A {
   void f(T);
   template<class X1> void g1(T, X1);
   template<class X2> void g2(T, X2);
   void h(T) { }
};

// specialization
template<> void A<int>::f(int);

// out of class member template definition
template<class T> template<class X1> void A<T>::g1(T, X1) { }


// member template specialization
template<> template<class X1> void A<int>::g1(int, X1);  //(1)

// member template specialization
template<> template<>
void A<int>::g1(int, char);                              //(2)

在(1)中,g1 似乎被专门设计成在 A 的专门版本(A< int >)中仍然是一个函数模板,而在(2)中,g1 似乎是针对其自己的一组模板参数进行了特化((int,来自 A< int >),char)。
我认为这些特殊化之间存在差异(再次强调,(1)感觉像是声明 g1 的新版本用于其“容器”A的“特殊版本”,而(2)感觉像是关于 g1 本身(或其自身的模板参数)的特化)。
此外,请考虑以下示例:
template<class T> struct A{
   int f() { return 1; }
}

template<>
int A<int>::f() { return 2; }                            //(3)

对我而言,(1) 和 (3) 是同一种“专业化”,与一个特殊版本的“容器”有关,而 (2) 则是模板实体本身的专业化。
标准是否提到了这种区别,或者这两种专业化被称为相同的专业化?
谢谢。

它们不是相同的。 - Eljay
你能告诉我标准是如何区分这两者的吗? - user42768
1
我不是语言律师。(1) 是部分特化,因为它仍然依赖于模板类型。(3) 是特化。 - Eljay
也许我不应该选择标准库中的示例。如果 g1 被声明为:template<class U> void g1(U);,我相信它们都将是显式特化。 - user42768
1个回答

1

首先,你的#3与引用示例中的第一个特化等效,只是标准的f在其签名中使用了类的模板参数 - 这可能是为了说明,由于特化必须匹配签名,因此可能需要在特殊化声明中重复类的模板参数。

然后,区别在于当Tint时,#1是A<T>成员的特化 - 这是一种缩写,用于编写大部分与主模板相同的A<int>本身的特化。特别是,为了避免误导,正被特化的成员的签名必须与(实例化的)主模板相同。在这种情况下,这意味着它仍然是模板。

另一方面,#2是模板的一种特化形式,恰好是A<int>的成员——该特化形式是A<int>::g1本身的特化,而不是“当TintA<T>::g1”的情况,就像#1一样。当成员是模板时,这当然只适用于不像#3那样的情况。(在这种情况下,#2是由#1声明的模板的特化形式!)

[temp.expl.spec]/15 的部分重点是这两种情况在语法上并没有明显的区别。区别在很大程度上是学术性的:两者都是对某些参数进行手术式更改的 模板实体

谢谢你的回答。我知道它们意思不同,这就是为什么我认为这种差异应该在标准中明确提到的原因。我有一个问题。你说:“特别地,为了避免误导,被专门化成员的签名必须与(实例化的)主模板保持不变。” 我理解为:“当你显式地专门化类模板的成员时,其签名必须与主模板中的签名相同”。这样对吗?[继续] - user42768
如果是这样,那么为什么temp.expl.spec p.5使用以下措辞:“[...]然而,在定义作为类模板显式特化的成员类模板的成员时,使用template<>来进行特化。”?如果其签名不能更改,那么我能想到的唯一其他可能性就是该模板也针对其自身的模板参数进行了特化,即如#2中所示。这正确吗? - user42768
@user42768:关于固定签名:是的,这就是我想说的,但是在实现上存在分歧,即什么构成签名:GCC接受该代码,但如果特化根本不是模板,则会拒绝。 - Davis Herring
@user42768:就 /5 而言,我认为它与专门化的成员定义(https://wandbox.org/permlink/Aj6abalDq9thV4dQ)有所区别,而是针对一些成员模板的模板参数集合(并且在容器模板的特定专业化内部,正如所需)。 - Davis Herring
@user42768:不,我上一条评论完全是关于#b的,而且/5是用来区分#a和#b的。 - Davis Herring
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接