13

如果我有一个带有 的函数模板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 个类型名,这是真的吗?我认为原因是因为 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 中是否可以进行“类型推断”?

4

3 回答 3

19

重载解析仅基于函数参数完成;根本不使用返回值。如果无法根据参数确定返回类型,则必须显式指定它。

我不会走通过引用参数“返回”值的路径;这使得调用代码不清楚。例如,我更喜欢这个:

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类型的用途。

于 2010-05-14T11:31:34.107 回答
3

结论是避免使用返回函数,更喜欢编写模板时通过引用返回的 void 函数

没有为什么?你有什么收获?仅类型推断(因此编写的代码更少)。但是您失去了分配值的更合乎逻辑的语法(以及因此要编写的更多代码)。所以一件事得到,另一件事失去。我看不到一般的好处。

必须明确指定模板类型甚至可能会有所帮助:考虑lexical_cast. 不指定返回模板类型会令人困惑。

于 2010-05-14T11:39:11.717 回答
2

让我通过说您应该更喜欢 C++ 转换而不是 C 样式转换来补充其他人所说的话。

vret = (TOut)(vin + 0.5);

相对

vret = static_cast<TOut>(vin + 0.5);

如果您尝试转换不相关的类型,静态转换总是会失败。这有助于调试。

于 2010-05-14T11:55:16.477 回答