//(1)
template <class T>
void f(T) {}
//(2)
template <class T>
void f(T*) {}
//(3)
template <>
void f<>(int*) {}
//(4)
void f(int*) {}
int main()
{
int* p;
f(p); // which function will be called?
return 0
}
我已经知道这种行为:
- 这取决于是否存在过载 (4)。
- 取决于(1)、(2)、(3)的声明顺序
令我困扰的是顺序很重要(因为它在我编写代码时增加了不确定性和猜测工作),尤其是我知道如果这些是类特化,那么顺序就无关紧要,编译器会调用最专业的类。
有人可以向我解释这是如何工作的吗?编译器遵循哪些规则来找到合适的函数特化?
最佳答案
基本规则实际上相当简单:函数和函数模板参与重载决策。显式函数模板特化不要。
因此,对于调用 f(p)
,编译器会进行重载决策以在 (1)、(2) 和 (4) 之间进行选择。 (3) 从不考虑重载决议。
重载解析选择单个函数或函数模板。 完成后,如果它选择了一个函数模板,然后将考虑该模板的特化。
让我们分析您提供的声明的不同组合。
如果 (4) 存在,它将被明确选择。当其他一切都相同时,非模板函数比函数模板更适合重载。
假设我们按顺序只有 (1)、(2) 和 (3)。过载解决方案在 (1) 和 (2) 之间选择。 (2) 更好,因为它更专业。所以函数模板(2)是由重载决议选择的。
然后,编译器会查看模板是否有任何特化。事实上,它确实如此——特化 (3),对于
T = int
。所以选择了这个专业。现在,假设顺序是 (1)、(3)、(2)。同样,重载决策在 (1) 和 (2) 之间进行选择(记住特化,即 (3) 永远不会参与重载决策)。 (2) 再次选择。这一次,(3) 是 (1) 的特化,对于
T = int*
。这是因为当 (3) 被声明时 (2) 还不存在,所以没有 (2) 可以专门化。但是 (1) 没有被重载决策选择,所以没有考虑。(2)、(3)、(1)的顺序与(1)、(2)、(3)相同。 (2)、(1)、(3)的顺序与(1)、(3)、(2)相同。 (1) 和 (2) 的相对顺序无关紧要 - (3) 的位置决定了它将专门化哪个模板。
关于c++ - 查找调用了哪个模板函数重载的规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29432792/