我有两个版本的程序。第一:
template<class T>
void f(T i, T j) = delete;
template<>
void f(int i, int j) {
cout << i << j << endl;
};
int main()
{
f(1.5, 2);
return 0;
}
第二个:
template<class T>
void f(T i, T j) = delete;
void f(int i, int j) {
cout << i << j << endl;
};
int main()
{
f(1.5, 2);
return 0;
}
第一个版本无法编译,因为 1.5
和 2
有不同的类型。在第二个版本中,我删除了 template<>
所以1.5
将转换为 1
程序将成功运行。
所以,当我们删除 template<>
,它仍然是模板特化,还是别的什么?除了隐式类型转换之外还有什么区别吗?有用吗?
最佳答案
对于(非限定的)函数调用为 f(1.5, 2)
在您的代码中,编译器构建了一组候选函数,其中包含常规函数和从模板生成的函数。在解析和替换模板参数之前,函数模板不是函数。参见 overload resolution了解全部详情。
f
是函数模板,它不能推导T
来自 double
类型的参数和 int
.不考虑模板特化,因为模板参数推导失败。可行的函数集为空,编译无法编译调用。
你可以解析T
如果将其称为 f<int>
,编译器会产生歧义但这样的电话考虑f
仅限模板(因为您明确指定了模板参数)。
如果对 f
进行完全特化不是模板,它成为一个常规函数。在这种情况下,模板参数推导仍然像以前一样失败,但现在有另一个函数 f
并且候选函数集包含一个函数 f
.可以使用提供的参数调用它,因为 double
隐式转换为 int
.
对于类型不是从参数类型推导出来的函数参数(即参数类型不是模板参数或显式指定的模板参数),编译器会考虑将参数类型隐式转换为函数参数类型和 double
至 int
处于隐式转换中,这就是为什么调用重载函数 f
成功。
关于没有 template<> 的 C++ 模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64837323/