如果我有一个带typename T
的函数模板,编译器可以自己设置类型,我在调用函数时不必显式写入类型:
template < typename T >
T min( T v1, T v2 ) {
return ( v1 < v2 ) ? v1: v2;
}
int i1 = 1, i2 = 2; int i3 = min( i1, i2 ); //no explicit <type>
但是如果我有一个包含两个不同类型名称的函数模板,例如:
template < typename TOut, typename TIn >
TOut round( TIn v ) {
return (TOut)( v + 0.5 );
}
double d = 1.54;
int i = round<int>(d); //explicit <int>
我总是必须指定至少1个typename吗?我假设原因是因为C ++无法区分不同返回类型之间的函数。
但是如果我使用void函数并移交引用,我再次不能明确指定返回类型名称:
template < typename TOut, typename TIn >
void round( TOut & vret, TIn vin ) {
vret = (TOut)(vin + 0.5);
}
double d = 1.54;
int i; round(i, d); //no explicit <int>
结论是否应避免使用返回函数,而更喜欢在编写模板时通过引用返回的void
函数?或者是否有可能避免显式写入返回类型?像模板的“类型推断”之类的东西。 C ++ 0x中是否可以使用“类型推断”?
答案 0 :(得分:16)
重载解析仅基于函数参数进行;根本没有使用返回值。如果无法根据参数确定返回类型,则必须明确指定它。
我不会沿着通过参考参数“返回”值的路径走下去;这使得调用代码不清楚。例如,我更喜欢这个:
double x = round<double>(y);
对此:
double x;
round(x, y);
因为在后一种情况下,很容易混淆输入和输出,而且x
被修改并不清楚。
在round
的特定情况下,您可能只需要TOut
的一种或两种类型,因此您可以将该模板参数保留为:
template<typename TIn>
int roundToInt(TIn v) {
return (int)(v + 0.5);
}
我发现roundToInt(x)
比round<int>(x)
更清晰,因为很清楚int
类型的用途是什么。
答案 1 :(得分:3)
结论是避免函数返回,更喜欢在编写模板时通过引用返回的void函数
不,为什么?你有什么收获?只输入推理(所以编写的代码更少)。但是你失去分配值的更合理的语法(因此更多的代码要写)。所以有一件事情,另一件事输了。我没有看到一般的好处。
甚至可能帮助必须明确指定模板类型:考虑lexical_cast
的情况。不指定返回模板类型会让人感到困惑。
答案 2 :(得分:2)
让我再说一下其他人所说的你应该更喜欢C ++演员而不是C风格的演员。
vret = (TOut)(vin + 0.5);
与
vret = static_cast<TOut>(vin + 0.5);
如果您尝试转换不相关的类型,静态强制转换将始终失败。这有助于调试。