调用模板函数而不使用<>;类型推断

时间:2010-05-14 11:26:21

标签: c++ templates types inference

如果我有一个带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中是否可以使用“类型推断”?

3 个答案:

答案 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);
如果您尝试转换不相关的类型,

静态强制转换将始终失败。这有助于调试。