RiNG
Kanalga Telegram’da o‘tish
2 276
Obunachilar
+124 soatlar
+47 kunlar
+1530 kunlar
Postlar arxiv
2 275
课后作业:
#include <iostream>
template <class T>
void f(T) {
std::cout << "func 1";
}
template <class T>
void f(T *) {
std::cout << "func 3";
}
template <>
void f<>(int *) {
std::cout << "func 2";
}
int main() {
int *p;
f(p);
}2 275
与类模板不同,函数模板并不存在偏特化(partial specialization),所以 34 是 1 的重载,他们在重载决议(overload resolution)中地位等价。
2 与 5 分别是 1 与 3 的显式特化(explicit specialization),所以该代码能够编译而不会产生重定义,原因暂且按下不表,后文阐述。
重载决议首先进行名字查找(name lookup)与参数依赖查找(argument-dependent name lookup),该阶段仅关心函数名的可见性,而对参数是否匹配并不关心,所以 25 仅作为特化而非重载并不参与。查找生成候选函数(candidate function)集合,包含 134。
对于候选函数中的每一个函数模板,因为调用时并没有显式指定模板实参(explicit template argument specification),所以将进行模板实参推导(template argument deduction)。4 推导失败,将不会加入可行函数(viable function)集合。而 13 推导成功,将对应的模板特化 25 加入可行函数集合。
对于可行函数,将两两比较以确定最佳可行函数(best viable function),其规则众多,这里地方虽然够大但是也写不下。对于两函数模板,将按照模板特化偏序规则(partial ordering of function template)进行比较。
模板特化偏序规则比较的是函数模板本身,而非模板特化。简单的来说,若 f 比 g 接受更少的类型,则 f 比 g 更特殊,即 f 优于 g。显然 3 比 1 更特殊,所以其对应特化 5 是最佳可行函数。
在不存在 5 的情况下,模板实参推导成功后 3 将进行隐式特化(implicit specialization),最终调用的为该隐式特化。
2 与 5 分别是 1 与 3 的显式特化的原因是:在 2 定义时,仅有 1 一个函数模板可见,它只能成为 1 的特化;而在 5 定义时,1 与 3 两个函数模板均对其可见,模板特化偏序规则在此又将被应用,选择更特殊的 3,成为其特化。
---
如果添加一个 6:
void f(int *) {
std::cout << "func 6";
}
注意到 6 并非函数模板,而最佳可行函数的确定规则中有一条:非模板函数始终优于模板函数。所以将毫无悬念地调用 6。2 275
#include <iostream>
template <class T>
void f(T) {
std::cout << "func 1";
}
template <>
void f<>(int *) {
std::cout << "func 2";
}
template <class T>
void f(T *) {
std::cout << "func 3";
}
template <class T>
void f(int *) {
std::cout << "func 4";
}
template <>
void f<>(int *) {
std::cout << "func 5";
}
int main() {
int *p;
f(p);
}2 275
今日份的啥都忘了的我
是什么浪费了我一个小时
#include <iostream>
template <class T>
void f(T) {
std::cout << "func 1";
}
template <>
void f<>(int *) {
std::cout << "func 2";
}
template <class T>
void f(T *) {
std::cout << "func 3";
}
int main() {
int *p;
f(p);
}
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
