在模板中浮动转换

时间:2013-05-16 09:50:53

标签: c++ templates

采用此功能模板:

template <typename T>
T divby2(T a)
{
  return .5 * a;
}

是否存在指定(.5),double常量的方法,以便在T时不会在运行时将其转换为T != double(比如,当Tfloat时)?

关于.5常数的替代规范的一些想法:

template <typename T>
T divby2(T a)
{
  return T(.5) * a;
}

template <typename T>
T divby2(T a)
{
  return (T(1) / T(2)) * a;
}

1 个答案:

答案 0 :(得分:6)

在运行时没有关于转换的决定。是否将值转换为另一种类型的决定是在编译时进行的。

    无论如何,
  • .5将是双倍的。
  • a将是您拥有的任何模板专精,即类型T
  • 乘法的结果类型(我们称之为X)将是operator*(double, T)给出的任何值。所有内置数字的双倍,除了long double,它给出了一个很长的双倍
  • 由于您要返回T,因此乘法返回的X将转换为T
  • T(0.5)将永远是T.

如果未定义任何转换或operator*,则会出现编译时错误。类型与运行时无关(除非您有虚函数等)。

发表评论:T(.5)是T类型的表达式。的转换将概念在运行时进行。但是,允许编译器优化它,例如,如果T为int,编译器将使用T(.5)实例化int(.5)并立即将其优化为0

根据您的问题,我假设您可能不了解模板的性质。与 compiletime 中的模板进行评估和实例化,与其他语言中的泛型函数不同。模板实例化意味着编译器为您使用模板的每种类型生成独立函数。所以例如如果您在不同的地方使用T=doubleT=intT=long double的该功能,就好像您已经编写了三个功能一样:

double divby2(double a)
{
  return .5 * a;
}

int divby2(int a)
{
  return .5 * a;
}

long double divby2(long double a)
{
  return .5 * a;
}

在第一个函数中,根本不会发生任何转换,因为所有内容都是双倍的。在第二个函数中,编译器知道double乘以int得到一个double,但是double会被转换回int。您可能会收到有关此问题的警告。在第三个函数中,double和long double的乘法给出了long double。由于返回类型也是一个很长的双倍,一切都很好,你不会收到警告。