我创建了一个带有额外模板参数的简单圆形模板函数,该参数定义了在返回之前需要将舍入值转换为的类型。
template <typename T, typename U>
T round(U val) {
T result;
if (val >= 0)
result = (T)(floor(val + (U)(.5)));
else
result = (T)(ceil( val - (U)(.5)));
return result;
}
int a = round<int>(5.5); // = 6
// no compiler warnings
但我也希望有可能留下额外的模板参数,这样你就不必插入已经添加的类型作为参数。
template <typename T>
T round(T val) {
return round<T>(val);
}
double b = round(5.5) // = 6.0
// C2668
然而,现在编译器抱怨:
错误C2668:对重载函数的模糊调用
我认为编译器总会选择最具体的模板,这应该是最后一个模板。为什么不是这种情况,是否有任何解决方法(不是专门用于此轮函数)?
模棱两可的电话并未指向round(5.5)
,而是指向return round<T>(val);
。因此,这个问题的答案是将重载函数的返回值重写为
return round<T,T>(val);
解决了这个问题。
答案 0 :(得分:2)
您收到错误,因为在模板参数扣除期间不会推断出返回类型。相反,它们可以从推导出的函数参数中替换。因为两个重载具有相同的参数推导,所以过载资源是不明确的,这给编译器错误。
在C ++ 11中,您可以为函数模板定义默认模板参数。如果添加一个额外的默认函数参数等于默认返回值,除非显式传递默认返回值,否则总是将参数类型作为返回类型:
#include <iostream>
#include <cmath>
#include <type_traits>
template <typename T, typename Ret = T>
Ret xround(T val, Ret ret = Ret()) {
return static_cast<Ret>(
(val >= 0) ?
floor(val + (T)(.5)) :
ceil( val - (T)(.5))
);
}
int main()
{
auto a = xround(5.5, int()); // = 6
static_assert(std::is_same<decltype(a), int>::value, "");
std::cout << a << "\n";
auto b = xround(5.5); // = 6.0
static_assert(std::is_same<decltype(b), double>::value, "");
std::cout << b << "\n";
}
请注意,我使用了三元运算符而不是if-else
,并且我将函数重命名为xround
,因为在C ++ 11中,round
内部已<cmath>
(当然你也可以使用)。
注意:临时类似于标签调度:它完全用于确定返回类型,实际的临时应该由编译器优化掉。
答案 1 :(得分:0)
您的问题不是模板专业化,而是过载模糊。
这是类似的:
int fn(int) { return 0; }
// error: new declaration ‘double fn(int)’
// error: ambiguates old declaration ‘int fn(int)’
double fn(int) { return 0; }
拥有U将T作为默认参数的模板将无法做得更好:
template <typename T, typename U = T>
T fn(U val) {
return T();
}
int main() {
// error: no matching function for call to ‘fn(double)’
// note: template argument deduction/substitution failed:
double d = fn(1.5); // fn<double>(1.5) will work
}
不允许部分专业化:
template <typename T, typename U>
T fn(U val) {
return T();
}
// error: function template partial specialization ‘fn<T, T>’ is not allowed
template <typename T>
T fn<T, T>(T val) {
return T();
}