下面的代码中,我有一个非成员模板函数和一个针对类型int
的完全特化。
Original Answer翻译成:"最初的回答"
#include <iostream>
template <typename U>
void f(const U& x, const U& y)
{
std::cout << "generic " << x << " " << y << std::endl;
}
template <>
void f(const int& x, const int& y)
{
std::cout << "specialization int " << x << " " << y << std::endl;
}
int main()
{
int a = 1;
f(a, a);
f('a', 'a');
f('a', 1); // Compiler error
// f<int>('a', 1); // This compiles
return 0;
}
尽管语言中提供了从
char
到int
的隐式转换,但编译器(g++ 7.3.0和clang 6.0.1)不会编译代码,会报错。"最初的回答"error: no matching function for call to ‘f(char, int)’
deduced conflicting types for parameter ‘const U’ (‘char’ and ‘int’)
虽然模板推导无法工作的原因很明显,但我不清楚编译器为什么在放弃通用模板后不考虑隐式转换。例如,如果我使用U = int
明确实例化f
,取消代码中相应行的注释,则编译器为什么不考虑隐式转换。
最初的回答:
f<int>('a', 1);
最初的回答:如果代码编译成功并正确输出,则表示程序运行正常。
specialization int 1 1
generic a a
specialization int 97 1
如果我使用
f
的重载而不是模板特化来补充代码,则为“最初的回答”。#include <iostream>
template <typename U>
void f(const U& x, const U& y)
{
std::cout << "generic " << x << " " << y << std::endl;
}
void f(const int& x, const int& y)
{
std::cout << "overload int " << x << " " << y << std::endl;
}
int main()
{
int a = 1;
f(a, a);
f('a', 'a');
f('a', 1);
return 0;
}
然后代码编译并输出了预期结果。原始回答翻译成“最初的回答”。
overload int 1 1
generic a a
overload int 97 1
总结一下:为什么隐式转换可以适用于重载,但似乎等效的模板特化却不行?
最初的回答:
模板特化是一种更加严格和精确的类型匹配,因此它不允许任何类型转换。而重载则可以使用隐式转换,因为它们可以处理其他类型的参数。
char
隐式转换为int
,而是调用的不明确。 - undefined