[英]function template explicit specialization
在本文中 ,他们说(c)明确专门化(b)。 我怀疑为什么我们不能说这是(a)的明确专业化? 因为我们可以为任何特定类型专门化模板。 所以虽然专注于int *,但为什么他们说(c)明确专门化(b)。
template<class T> // (a) a base template
void f( T );
template<class T> // (b) a second base template, overloads (a)
void f( T* ); // (function templates can't be partially
// specialized; they overload instead)
template<> // (c) explicit specialization of (b)
void f<>(int*);
任何评论都有助于理解事物。
如果(b)不存在,则(c)确实是(a)的有效专业化。 实际上,只是改变源代码行的顺序,以便(c)在编译器看到(b)之前出现,将使它成为(a)的特化!
请考虑以下代码:
int main()
{
int a;
f(&a);
return 0;
}
现在把自己放在编译器的鞋子里。 您需要使用int*
参数找到匹配的函数f
。 你是做什么?
f
的非模板函数,并查看是否存在与参数类型匹配的任何函数(在本例中为int*
)。 f<T>
和f<T*>
。 请注意,与类不同,函数模板不能部分专用,因此就编译器而言,这些是完全独立的重载。 f<T*>
基本模板是更好的匹配,因此您使用T=int
实例化它。 现在,如果您已经看过f<int*>
,那么您可以使用它,否则您将生成该函数。 现在这是有趣的事情。 如果我们更改原始代码的顺序,请转到
template<class T> void f( T ); // (i)
template<> void f<>(int*); // (ii)
template<class T> void f( T* ); // (iii)
那么编译器现在看到(ii)作为(i)的特化 - 因为它按顺序处理事物,并且在它达到(ii)时它不知道(iii)存在了! 但由于它仅匹配基础模板,因此它决定(iii)是比(i)更好的匹配 - 现在(iii)没有任何特化,因此您获得默认实例化。
这一切都让人很困惑,有时甚至会让最有经验的C ++程序员绊倒。 所以基本规则是: 不要专门化函数模板,而是使用普通函数重载 。 一个普通的旧的非模板
void f(int*);
在其他事情之前会匹配,并避免这一切混乱。
编辑: nm请求在评论中引用标准。 我担心我只有C ++ 03版本,但是这里有:
第4.7.3.3段: “明确专门化的函数模板或类模板的声明应在声明明确专业化的范围内。” 。
这就是为什么在上面的例子中,(ii)不能被视为(iii)的明确专业化,因为(iii)还不在范围内。
第4.8.3节: “当写入对[函数]名称的调用时...对每个函数模板执行模板参数推导(14.8.2)和检查任何显式模板参数(14.3)以查找模板参数值(如果有的话),可以与该函数模板一起使用,以实例化可以使用调用参数调用的函数模板特化。“
换句话说,(正如我所读到的,无论如何)它始终会查看每个基本模板,无论如何 - 提供明确的专业化没有任何区别。
同一段落继续: “对于每个函数模板,如果参数推导和检查成功,则使用模板参数(推断和/或显式)来实例化单个函数模板特化,该特殊化被添加到候选函数集中。用于重载分辨率。 “
因此,只有在这一点(我读到它)才会考虑显式特化。
最后,也许最重要的是在这种情况下,第13.3.3节涉及选择过载集中的“最佳可行功能”。 两个项目是相关的:
F1优于F2,如果: “F1和F2是功能模板特化,F1的功能模板比F2模板更专业,根据14.5.5.2中描述的偏序规则” 。 这就是f<T*>
版本在尝试匹配f(int*)
时在f<T>
版本之前被选中的原因 - 因为它是一个“更专业”的模板
F1优于F2,如果: “F1是非模板函数,F2是函数模板特化” ,这是我在原始答案结束时的建议的基础。
唷!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.