【发布时间】:2019-04-29 09:05:44
【问题描述】:
在下面的代码中,我有一个非成员模板函数和它的完整特化类型int。
#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
总结:为什么隐式转换适用于重载而不适用于看似等效的模板特化?
【问题讨论】:
-
您是否阅读了编译器错误信息?它说我像
"template parameter 'U' is ambiguous"。所以问题不在于无法从char隐式转换为int,而是调用的歧义。 -
来自this template argument deduction reference(更具体地说是implicit conversion section):“类型推导不考虑隐式转换......:这是重载解析的工作,稍后会发生。”
-
@vahancho 对不起,我使用和提到的编译器没有给出警告 ambigous。
-
另一个更喜欢重载而不是专业化的原因。
标签: c++ templates language-lawyer