仍然拿max
函数举例。
使用double
重载max
函数。
然后分别使用float
和double
实例化:
template
T max(T lhs,T rhs) {
return (lhs > rhs)? lhs : rhs;
}
double max(double lhs, double rhs) {
return (lhs > rhs)? lhs : rhs;
}
int main() {
max(10.5f, 5.5f); // (1)
max(10.5, 5.5); // (2)
}
此时(1)和(2)分别会调用哪个函数?
答案是编译器会选择最匹配的函数。
- (1):函数模板是更好的匹配,因为函数需要类型转换;
- (2):函数模板和函数都可以匹配,在这种情况下,编译器会选择函数。
C++ Insights输出如下:
template
T max(T lhs,T rhs) {
return (lhs > rhs)? lhs : rhs;
}
/* First instantiated from: insights.cpp:12 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
float max(float lhs, float rhs)
{
return (lhs > rhs) ? lhs : rhs;
}
#endif
double max(double lhs, double rhs)
{
return (lhs > rhs) ? lhs : rhs;
}
int main()
{
max(10.5F, 5.5F);
max(10.5, 5.5);
return 0;
}
不同的模板参数
如果向max传递2个不同类型的参数:
template
T max(T lhs,T rhs) {
return (lhs > rhs)? lhs : rhs;
}
int main() {
max(10.5f, 5.5);
}
C++ Insights输出如下:
/home/insights/insights.cpp:8:5: error: no matching function for call to 'max'
max(10.5f, 5.5);
^~~
/home/insights/insights.cpp:2:3: note: candidate template ignored: deduced conflicting types for parameter 'T' ('float' vs. 'double')
T max(T lhs,T rhs) {
^
1 error generated.
Error while processing /home/insights/insights.cpp.
编译器会报错,原因如下:
- 如果可能的话,编译器将从函数参数推导模板参数;
- 编译器会对每个函数模板参数进行推导;
- 对于10.5f,编译器推导T为float;对于5.5,编译器推导T为double;
- 显然,T不可能同时为float和double。
所以编译器报错了。
解决这个问题也很简单,使用2个类型参数即可:
template
??? max(T lhs,T2 rhs) {
return (lhs > rhs)? lhs : rhs;
}
int main() {
max(10.5f, 5.5);
}
这个函数的返回值有可能是T,T2或从T/T2派生出来的类型,在C++11里面实现很简单。
有以下几种方式:
// automaticReturnTypeDeduction.cpp
#include
template // (1)
typename std::conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type max1(T1 lhs,T2 rhs) {
return (lhs > rhs)? lhs : rhs;
}
template // (2)
typename std::common_type::type max2(T1 lhs,T2 rhs) {
return (lhs > rhs)? lhs : rhs;
}
template // (3)
auto max3(T1 lhs,T2 rhs) {
return (lhs > rhs)? lhs : rhs;
}
int main() {
max1(10.5f, 5.5);
max2(10.5f, 5.5);
max3(10.5f, 5.5);
}
- (1):
typename std::conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type
返回其中较大者;std::conditional
是编译时的三元 *** 作符; - (2):
typename std::common_type
返回参数列表中类型的公共类型,其可以接受任意数量的参数;::type - (3):使用了auto的自动类型推导。
其中的typename是为了告诉编译器T1和T2是类型,当然,它们也可能是无类型或者模板。
C++ Insights主要输出如下:
- (1)中较小类型float会被转换为double
#ifdef INSIGHTS_USE_TEMPLATE
template<>
typename std::conditional<(sizeof(float) > sizeof(double)), float, double>::type max1(float lhs, double rhs)
{
return (static_cast(lhs) > rhs) ? static_cast(lhs) : rhs;
}
#endif
- (2)
/* First instantiated from: insights.cpp:10 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
typename std::common_type::type max2(float lhs, double rhs)
{
return (static_cast(lhs) > rhs) ? static_cast(lhs) : rhs;
}
#endif
- (3)
#ifdef INSIGHTS_USE_TEMPLATE
template<>
double max3(float lhs, double rhs)
{
return (static_cast(lhs) > rhs) ? static_cast(lhs) : rhs;
}
#endif
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)